/*
 * Copyright (c) 2003, 2022 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0, which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package jakarta.xml.bind;

import org.w3c.dom.Node;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

/**
 * The {@code JAXBContext} class provides the client's entry point to the
 * Jakarta XML Binding API. It provides an abstraction for managing the XML/Java binding
 * information necessary to implement the Jakarta XML Binding binding framework operations:
 * unmarshal, marshal and validate.
 *
 * <p>A client application normally obtains new instances of this class using
 * one of these two styles for newInstance methods, although there are other
 * specialized forms of the method available:
 *
 * <ul>
 * <li>{@link #newInstance(String, ClassLoader) JAXBContext.newInstance( "com.acme.foo:com.acme.bar" )} <br>
 * The JAXBContext instance is initialized from a list of colon
 * separated Java package names. Each java package contains
 * Jakarta XML Binding mapped classes, schema-derived classes and/or user annotated
 * classes. Additionally, the java package may contain Jakarta XML Binding package annotations
 * that must be processed. (see JLS, Section 7.4.1 "Named Packages").
 * </li>
 * <li>{@link #newInstance(Class...) JAXBContext.newInstance( com.acme.foo.Foo.class )} <br>
 * The JAXBContext instance is initialized with class(es)
 * passed as parameter(s) and classes that are statically reachable from
 * these class(es). See {@link #newInstance(Class...)} for details.
 * </li>
 * </ul>
 *
 * <p><i>
 * The provider must call the
 * {@link DatatypeConverter#setDatatypeConverter(DatatypeConverterInterface)
 * DatatypeConverter.setDatatypeConverter} api prior to any client
 * invocations of the marshal and unmarshal methods.  This is necessary to
 * configure the datatype converter that will be used during these operations.</i>
 *
 * <a id="Unmarshalling"></a>
 * <h2>Unmarshalling</h2>
 * <p>
 * The {@link Unmarshaller} class provides the client application the ability
 * to convert XML data into a tree of Java content objects.
 * The unmarshal method allows for
 * any global XML element declared in the schema to be unmarshalled as
 * the root of an instance document.
 * Additionally, the unmarshal method allows for an unrecognized root element that
 * has  an xsi:type attribute's value that references a type definition declared in
 * the schema  to be unmarshalled as the root of an instance document.
 * The {@code JAXBContext} object
 * allows the merging of global elements and type definitions across a set of schemas (listed
 * in the {@code contextPath}). Since each schema in the schema set can belong
 * to distinct namespaces, the unification of schemas to an unmarshalling
 * context must be namespace independent.  This means that a client
 * application is able to unmarshal XML documents that are instances of
 * any of the schemas listed in the {@code contextPath}.  For example:
 *
 * <pre>
 *      JAXBContext jc = JAXBContext.newInstance( "com.acme.foo:com.acme.bar" );
 *      Unmarshaller u = jc.createUnmarshaller();
 *      FooObject fooObj = (FooObject)u.unmarshal( new File( "foo.xml" ) ); // ok
 *      BarObject barObj = (BarObject)u.unmarshal( new File( "bar.xml" ) ); // ok
 *      BazObject bazObj = (BazObject)u.unmarshal( new File( "baz.xml" ) ); // error, "com.acme.baz" not in contextPath
 * </pre>
 *
 * <p>
 * The client application may also generate Java content trees explicitly rather
 * than unmarshalling existing XML data.  For all Jakarta XML Binding-annotated value classes,
 * an application can create content using constructors.
 * For schema-derived interface/implementation classes and for the
 * creation of elements that are not bound to a Jakarta XML Binding-annotated
 * class, an application needs to have access and knowledge about each of
 * the schema derived {@code ObjectFactory} classes that exist in each of
 * java packages contained in the {@code contextPath}.  For each schema
 * derived java class, there is a static factory method that produces objects
 * of that type.  For example,
 * assume that after compiling a schema, you have a package {@code com.acme.foo}
 * that contains a schema derived interface named {@code PurchaseOrder}.  In
 * order to create objects of that type, the client application would use the
 * factory method like this:
 *
 * <pre>
 *       com.acme.foo.PurchaseOrder po =
 *           com.acme.foo.ObjectFactory.createPurchaseOrder();
 * </pre>
 *
 * <p>
 * Once the client application has an instance of the the schema derived object,
 * it can use the mutator methods to set content on it.
 *
 * <p>
 * For more information on the generated {@code ObjectFactory} classes, see
 * Section 4.2 <i>Java Package</i> of the specification.
 *
 * <p>
 * <i>The provider must generate a class in each
 * package that contains all of the necessary object factory methods for that
 * package named ObjectFactory as well as the static
 * {@code newInstance( javaContentInterface )} method</i>
 *
 * <h3>Marshalling</h3>
 * <p>
 * The {@link Marshaller} class provides the client application the ability
 * to convert a Java content tree back into XML data.  There is no difference
 * between marshalling a content tree that is created manually using the factory
 * methods and marshalling a content tree that is the result an {@code unmarshal}
 * operation.  Clients can marshal a java content tree back to XML data
 * to a {@code java.io.OutputStream} or a {@code java.io.Writer}.  The
 * marshalling process can alternatively produce SAX2 event streams to a
 * registered {@code ContentHandler} or produce a DOM Node object.
 * Client applications have control over the output encoding as well as
 * whether or not to marshal the XML data as a complete document or
 * as a fragment.
 *
 * <p>
 * Here is a simple example that unmarshals an XML document and then marshals
 * it back out:
 *
 * <pre>
 *        JAXBContext jc = JAXBContext.newInstance( "com.acme.foo" );
 *
 *        // unmarshal from foo.xml
 *        Unmarshaller u = jc.createUnmarshaller();
 *        FooObject fooObj = (FooObject)u.unmarshal( new File( "foo.xml" ) );
 *
 *        // marshal to System.out
 *        Marshaller m = jc.createMarshaller();
 *        m.marshal( fooObj, System.out );
 * </pre>
 *
 *
 * <h3>Validation</h3>
 * <p>
 * In Jakarta XML Binding, the {@link Unmarshaller} has included convenience methods that expose
 * the JAXP {@link javax.xml.validation} framework.  Please refer to the
 * {@link Unmarshaller#setSchema(javax.xml.validation.Schema)} API for more
 * information.
 *
 *
 * <h3>Jakarta XML Binding Runtime Framework Compatibility</h3>
 * <p>
 * The following JAXB 1.0 restriction only applies to binding schema to
 * interfaces/implementation classes.
 * Since this binding does not require a common runtime system, a Jakarta XML Binding
 * client application must not attempt to mix runtime objects ({@code JAXBContext,
 * Marshaller}, etc. ) from different providers.  This does not
 * mean that the client application isn't portable, it simply means that a
 * client has to use a runtime system provided by the same provider that was
 * used to compile the schema.
 *
 *
 * <h3>Discovery of Jakarta XML Binding implementation</h3>
 * <p>
 * To create an instance of {@link JAXBContext}, one of {@code JAXBContext.newInstance(...)} methods is invoked. After
 * JAX-B implementation is discovered, call is delegated to appropriate provider's method {@code createContext(...)}
 * passing parameters from the original call.
 * <p>
 * JAX-B implementation discovery happens each time {@code JAXBContext.newInstance} is invoked. If there is no user
 * specific configuration provided, default JAX-B provider must be returned.
 * <p>
 * Implementation discovery consists of following steps:
 *
 * <ol>
 *
 * <li>
 * If the system property {@link #JAXB_CONTEXT_FACTORY} exists, then its value is assumed to be the provider
 * factory class. This phase of the look up enables per-JVM override of the Jakarta XML Binding implementation.
 *
 * <li>
 * If the property {@link #JAXB_CONTEXT_FACTORY} exists in the {@code Map<String, ?>} passed to {@link #newInstance(Class[], Map)}
 * or to {@link #newInstance(String, ClassLoader, Map)}, then its value is assumed to be the fully qualified provider factory class name.
 * This phase of the look up enables context sensitive selection of the Jakarta XML Binding implementation.
 *
 * <li>
 * Provider of {@link jakarta.xml.bind.JAXBContextFactory} is loaded using the service-provider loading
 * facilities, defined by the {@link java.util.ServiceLoader} class, to attempt
 * to locate and load an implementation of the service using the {@linkplain
 * java.util.ServiceLoader#load(java.lang.Class) default loading mechanism}: the service-provider loading facility
 * will use the {@linkplain java.lang.Thread#getContextClassLoader() current thread's context class loader}
 * to attempt to load the context factory. If the context class loader is null, the
 * {@linkplain ClassLoader#getSystemClassLoader() system class loader} will be used.
 * <br>
 * In case of {@link java.util.ServiceConfigurationError service
 * configuration error} a {@link jakarta.xml.bind.JAXBException} will be thrown.
 *
 * <li>
 * Finally, if all the steps above fail, then the rest of the look up is unspecified. That said,
 * the recommended behavior is to simply look for some hard-coded platform default Jakarta XML Binding implementation.
 * This phase of the look up is so that the environment can have its own Jakarta XML Binding implementation as the last resort.
 * </ol>
 *
 * <p>
 * Once the provider factory class is discovered, context creation is delegated to one of its
 * {@code createContext(...)} methods.
 *
 * @implNote
 * Within the last step, if Glassfish AS environment detected, its specific service loader is used to find factory class.
 *
 * @author <ul><li>Ryan Shoemaker, Sun Microsystems, Inc.</li>
 *             <li>Kohsuke Kawaguchi, Sun Microsystems, Inc.</li>
 *             <li>Joe Fialli, Sun Microsystems, Inc.</li></ul>
 *
 * @see Marshaller
 * @see Unmarshaller
 * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-7.html#jls-7.4.1">S 7.4.1 "Named Packages"
 *      in Java Language Specification</a>
 *
 * @since 1.6, JAXB 1.0
 */
public abstract class JAXBContext {

    /**
     * The name of the property that contains the name of the class capable
     * of creating new {@code JAXBContext} objects.
     */
    public static final String JAXB_CONTEXT_FACTORY = "jakarta.xml.bind.JAXBContextFactory";

    protected JAXBContext() {
    }


    /**
     * Create a new instance of a {@code JAXBContext} class.
     *
     * <p>
     * This is a convenience method to invoke the
     * {@link #newInstance(String,ClassLoader)} method with
     * the context class loader of the current thread.
     *
     * @param contextPath the context path
     *
     * @return the new instance of a {@code JAXBContext} class
     *
     * @throws JAXBException if an error was encountered while creating the
     *                       {@code JAXBContext} such as
     * <ol>
     *   <li>failure to locate either ObjectFactory.class or jaxb.index in the packages</li>
     *   <li>an ambiguity among global elements contained in the contextPath</li>
     *   <li>failure to locate a value for the context factory provider property</li>
     *   <li>mixing schema derived packages from different providers on the same contextPath</li>
     *   <li>packages are not open to {@code jakarta.xml.bind} module</li>
     * </ol>
     */
    public static JAXBContext newInstance( String contextPath )
            throws JAXBException {

        //return newInstance( contextPath, JAXBContext.class.getClassLoader() );
        return newInstance( contextPath, getContextClassLoader());
    }

    /**
     * Create a new instance of a {@code JAXBContext} class.
     *
     * <p>
     * The client application must supply a context path which is a list of
     * colon (':', \u005Cu003A) separated java package names that contain
     * schema-derived classes and/or fully qualified Jakarta XML Binding-annotated classes.
     * Schema-derived
     * code is registered with the JAXBContext by the
     * ObjectFactory.class generated per package.
     * Alternatively than being listed in the context path, programmer
     * annotated Jakarta XML Binding mapped classes can be listed in a
     * {@code jaxb.index} resource file, format described below.
     * Note that a java package can contain both schema-derived classes and
     * user annotated Jakarta XML Binding classes. Additionally, the java package may
     * contain Jakarta XML Binding package annotations  that must be processed. (see JLS,
     * Section 7.4.1 "Named Packages").
     * </p>
     *
     * <p>
     * Every package listed on the contextPath must meet <b>one or both</b> of the
     * following conditions otherwise a {@code JAXBException} will be thrown:
     * </p>
     * <ol>
     *   <li>it must contain ObjectFactory.class</li>
     *   <li>it must contain jaxb.index</li>
     * </ol>
     *
     * <p>
     * <b>Format for jaxb.index</b>
     * <p>
     * The file contains a newline-separated list of class names.
     * Space and tab characters, as well as blank
     * lines, are ignored. The comment character
     * is '#' (0x23); on each line all characters following the first comment
     * character are ignored. The file must be encoded in UTF-8. Classes that
     * are reachable, as defined in {@link #newInstance(Class...)}, from the
     * listed classes are also registered with JAXBContext.
     * <p>
     * Constraints on class name occuring in a {@code jaxb.index} file are:
     * <ul>
     *   <li>Must not end with ".class".</li>
     *   <li>Class names are resolved relative to package containing
     *       {@code jaxb.index} file. Only classes occuring directly in package
     *       containing {@code jaxb.index} file are allowed.</li>
     *   <li>Fully qualified class names are not allowed.
     *       A qualified class name,relative to current package,
     *       is only allowed to specify a nested or inner class.</li>
     * </ul>
     *
     * <p>
     * If there are any global XML element name collisions across the various
     * packages listed on the {@code contextPath}, a {@code JAXBException}
     * will be thrown.
     *
     * <p>
     * Mixing generated interface/impl bindings from multiple Jakarta XML Binding Providers
     * in the same context path may result in a {@code JAXBException}
     * being thrown.
     *
     * <p>
     * The steps involved in discovering the Jakarta XML Binding implementation is discussed in the class javadoc.
     *
     * @param contextPath
     *      List of java package names that contain schema
     *      derived class and/or java to schema (Jakarta XML Binding-annotated)
     *      mapped classes.
     *      Packages in {@code contextPath} that are in named modules must be
     *      {@code open} to at least the {@code jakarta.xml.bind} module.
     * @param classLoader
     *      This class loader will be used to locate the implementation
     *      classes.
     *
     * @return a new instance of a {@code JAXBContext}
     * @throws JAXBException if an error was encountered while creating the
     *                       {@code JAXBContext} such as
     * <ol>
     *   <li>failure to locate either ObjectFactory.class or jaxb.index in the packages</li>
     *   <li>an ambiguity among global elements contained in the contextPath</li>
     *   <li>failure to locate a value for the context factory provider property</li>
     *   <li>mixing schema derived packages from different providers on the same contextPath</li>
     *   <li>packages are not open to {@code jakarta.xml.bind} module</li>
     * </ol>
     */
    public static JAXBContext newInstance( String contextPath, ClassLoader classLoader ) throws JAXBException {

        return newInstance(contextPath,classLoader,Collections.<String,Object>emptyMap());
    }

    /**
     * Create a new instance of a {@code JAXBContext} class.
     *
     * <p>
     * This is mostly the same as {@link JAXBContext#newInstance(String, ClassLoader)},
     * but this version allows you to pass in provider-specific properties to configure
     * the instantiation of {@link JAXBContext}.
     *
     * <p>
     * The interpretation of properties is up to implementations. Implementations must
     * throw {@code JAXBException} if it finds properties that it doesn't understand.
     *
     * @param contextPath
     *      List of java package names that contain schema
     *      derived class and/or java to schema (Jakarta XML Binding-annotated)
     *      mapped classes.
     *      Packages in {@code contextPath} that are in named modules must be
     *      {@code open} to at least the {@code jakarta.xml.bind} module.
     * @param classLoader
     *      This class loader will be used to locate the implementation classes.
     * @param properties
     *      provider-specific or provider selection-specific properties.
     *      Can be null, which means the same thing as passing in an empty map.
     *
     * @return a new instance of a {@code JAXBContext}
     * @throws JAXBException if an error was encountered while creating the
     *                       {@code JAXBContext} such as
     * <ol>
     *   <li>failure to locate either ObjectFactory.class or jaxb.index in the packages</li>
     *   <li>an ambiguity among global elements contained in the contextPath</li>
     *   <li>failure to locate a value for the context factory provider property</li>
     *   <li>mixing schema derived packages from different providers on the same contextPath</li>
     *   <li>packages are not open to {@code jakarta.xml.bind} module</li>
     * </ol>
     * @since 1.6, JAXB 2.0
     */
    public static JAXBContext newInstance( String contextPath,
                                           ClassLoader classLoader,
                                           Map<String,?>  properties  ) throws JAXBException {

        return ContextFinder.find(
                        /* The default property name according to the Jakarta XML Binding spec */
                JAXB_CONTEXT_FACTORY,

                        /* the context path supplied by the client app */
                contextPath,

                        /* class loader to be used */
                classLoader,
                properties );
    }

// TODO: resurrect this once we introduce external annotations
//    /**
//     * Create a new instance of a {@code JAXBContext} class.
//     *
//     * <p>
//     * The client application must supply a list of classes that the new
//     * context object needs to recognize.
//     *
//     * Not only the new context will recognize all the classes specified,
//     * but it will also recognize any classes that are directly/indirectly
//     * referenced statically from the specified classes.
//     *
//     * For example, in the following Java code, if you do
//     * {@code newInstance(Foo.class)}, the newly created {@link JAXBContext}
//     * will recognize both {@code Foo} and {@code Bar}, but not {@code Zot}:
//     * <pre>
//     * class Foo {
//     *      Bar b;
//     * }
//     * class Bar { int x; }
//     * class Zot extends Bar { int y; }
//     * </pre>
//     *
//     * Therefore, a typical client application only needs to specify the
//     * top-level classes, but it needs to be careful.
//     *
//     * TODO: if we are to define other mechanisms, refer to them.
//     *
//     * @param externalBindings
//     *      list of external binding files. Can be null or empty if none is used.
//     *      when specified, those files determine how the classes are bound.
//     *
//     * @param classesToBeBound
//     *      list of java classes to be recognized by the new {@link JAXBContext}.
//     *      Can be empty, in which case a {@link JAXBContext} that only knows about
//     *      spec-defined classes will be returned.
//     *
//     * @return
//     *      A new instance of a {@code JAXBContext}.
//     *
//     * @throws JAXBException
//     *      if an error was encountered while creating the
//     *      {@code JAXBContext}, such as (but not limited to):
//     * <ol>
//     *  <li>No Jakarta XML Binding implementation was discovered
//     *  <li>Classes use Jakarta XML Binding annotations incorrectly
//     *  <li>Classes have colliding annotations (i.e., two classes with the same type name)
//     *  <li>Specified external bindings are incorrect
//     *  <li>The Jakarta XML Binding implementation was unable to locate
//     *      provider-specific out-of-band information (such as additional
//     *      files generated at the development time.)
//     * </ol>
//     *
//     * @throws IllegalArgumentException
//     *      if the parameter contains {@code null} (i.e., {@code newInstance(null);})
//     *
//     * @since JAXB 2.0
//     */
//    public static JAXBContext newInstance( Source[] externalBindings, Class... classesToBeBound )
//        throws JAXBException {
//
//        // empty class list is not an error, because the context will still include
//        // spec-specified classes like String and Integer.
//        // if(classesToBeBound.length==0)
//        //    throw new IllegalArgumentException();
//
//        // but it is an error to have nulls in it.
//        for( int i=classesToBeBound.length-1; i>=0; i-- )
//            if(classesToBeBound[i]==null)
//                throw new IllegalArgumentException();
//
//        return ContextFinder.find(externalBindings,classesToBeBound);
//    }

    /**
     * Create a new instance of a {@code JAXBContext} class.
     *
     * <p>
     * The client application must supply a list of classes that the new
     * context object needs to recognize.
     *
     * Not only the new context will recognize all the classes specified,
     * but it will also recognize any classes that are directly/indirectly
     * referenced statically from the specified classes. Subclasses of
     * referenced classes nor {@code @XmlTransient} referenced classes
     * are not registered with JAXBContext.
     *
     * For example, in the following Java code, if you do
     * {@code newInstance(Foo.class)}, the newly created {@link JAXBContext}
     * will recognize both {@code Foo} and {@code Bar}, but not {@code Zot} or {@code FooBar}:
     * <pre>
     * class Foo {
     *      &#64;XmlTransient FooBar c;
     *      Bar b;
     * }
     * class Bar { int x; }
     * class Zot extends Bar { int y; }
     * class FooBar { }
     * </pre>
     *
     * Therefore, a typical client application only needs to specify the
     * top-level classes, but it needs to be careful.
     *
     * <p>
     * Note that for each java package registered with JAXBContext,
     * when the optional package annotations exist, they must be processed.
     * (see JLS, Section 7.4.1 "Named Packages").
     *
     * <p>
     * The steps involved in discovering the Jakarta XML Binding implementation is discussed in the class javadoc.
     *
     * @param classesToBeBound
     *      List of java classes to be recognized by the new {@link JAXBContext}.
     *      Classes in {@code classesToBeBound} that are in named modules must be in a package
     *      that is {@code open} to at least the {@code jakarta.xml.bind} module.
     *      Can be empty, in which case a {@link JAXBContext} that only knows about
     *      spec-defined classes will be returned.
     *
     * @return
     *      A new instance of a {@code JAXBContext}.
     *
     * @throws JAXBException
     *      if an error was encountered while creating the
     *      {@code JAXBContext}, such as (but not limited to):
     * <ol>
     *  <li>No Jakarta XML Binding implementation was discovered
     *  <li>Classes use Jakarta XML Binding annotations incorrectly
     *  <li>Classes have colliding annotations (i.e., two classes with the same type name)
     *  <li>The Jakarta XML Binding implementation was unable to locate
     *      provider-specific out-of-band information (such as additional
     *      files generated at the development time.)
     *  <li>{@code classesToBeBound} are not open to {@code jakarta.xml.bind} module
     * </ol>
     *
     * @throws IllegalArgumentException
     *      if the parameter contains {@code null} (i.e., {@code newInstance(null);})
     *
     * @since 1.6, JAXB 2.0
     */
    public static JAXBContext newInstance( Class<?> ... classesToBeBound )
            throws JAXBException {

        return newInstance(classesToBeBound,Collections.<String,Object>emptyMap());
    }

    /**
     * Create a new instance of a {@code JAXBContext} class.
     *
     * <p>
     * An overloading of {@link JAXBContext#newInstance(Class...)}
     * to configure 'properties' for this instantiation of {@link JAXBContext}.
     *
     * <p>
     * The interpretation of properties is up to implementations. Implementations must
     * throw {@code JAXBException} if it finds properties that it doesn't understand.
     *
     * @param classesToBeBound
     *      List of java classes to be recognized by the new {@link JAXBContext}.
     *      Classes in {@code classesToBeBound} that are in named modules must be in a package
     *      that is {@code open} to at least the {@code jakarta.xml.bind} module.
     *      Can be empty, in which case a {@link JAXBContext} that only knows about
     *      spec-defined classes will be returned.
     * @param properties
     *      provider-specific or provider selection-specific properties.
     *      Can be null, which means the same thing as passing in an empty map.
     *
     * @return
     *      A new instance of a {@code JAXBContext}.
     *
     * @throws JAXBException
     *      if an error was encountered while creating the
     *      {@code JAXBContext}, such as (but not limited to):
     * <ol>
     *  <li>No Jakarta XML Binding implementation was discovered
     *  <li>Classes use Jakarta XML Binding annotations incorrectly
     *  <li>Classes have colliding annotations (i.e., two classes with the same type name)
     *  <li>The Jakarta XML Binding implementation was unable to locate
     *      provider-specific out-of-band information (such as additional
     *      files generated at the development time.)
     *  <li>{@code classesToBeBound} are not open to {@code jakarta.xml.bind} module
     * </ol>
     *
     * @throws IllegalArgumentException
     *      if the parameter contains {@code null} (i.e., {@code newInstance(null,someMap);})
     *
     * @since 1.6, JAXB 2.0
     */
    public static JAXBContext newInstance( Class<?>[] classesToBeBound, Map<String,?> properties )
            throws JAXBException {

        if (classesToBeBound == null) {
            throw new IllegalArgumentException();
        }

        // but it is an error to have nulls in it.
        for (int i = classesToBeBound.length - 1; i >= 0; i--) {
            if (classesToBeBound[i] == null) {
                throw new IllegalArgumentException();
            }
        }

        return ContextFinder.find(classesToBeBound,properties);
    }

    /**
     * Create an {@code Unmarshaller} object that can be used to convert XML
     * data into a java content tree.
     *
     * @return an {@code Unmarshaller} object
     *
     * @throws JAXBException if an error was encountered while creating the
     *                       {@code Unmarshaller} object
     */
    public abstract Unmarshaller createUnmarshaller() throws JAXBException;


    /**
     * Create a {@code Marshaller} object that can be used to convert a
     * java content tree into XML data.
     *
     * @return a {@code Marshaller} object
     *
     * @throws JAXBException if an error was encountered while creating the
     *                       {@code Marshaller} object
     */
    public abstract Marshaller createMarshaller() throws JAXBException;


    /**
     * Creates a {@code Binder} object that can be used for
     * associative/in-place unmarshalling/marshalling.
     *
     * @param domType select the DOM API to use by passing in its DOM Node class
     *
     * @param <T> the DOM API type
     *
     * @return always a new valid {@code Binder} object.
     *
     * @throws UnsupportedOperationException
     *      if DOM API corresponding to {@code domType} is not supported by
     *      the implementation.
     *
     * @since 1.6, JAXB 2.0
     */
    public <T> Binder<T> createBinder(Class<T> domType) {
        // to make JAXB 1.0 implementations work, this method must not be
        // abstract
        throw new UnsupportedOperationException();
    }

    /**
     * Creates a {@code Binder} for W3C DOM.
     *
     * @return always a new valid {@code Binder} object.
     *
     * @since 1.6, JAXB 2.0
     */
    public Binder<Node> createBinder() {
        return createBinder(Node.class);
    }

    /**
     * Creates a {@code JAXBIntrospector} object that can be used to
     * introspect Jakarta XML Binding objects.
     *
     * @return
     *      always return a non-null valid {@code JAXBIntrospector} object.
     *
     * @throws UnsupportedOperationException
     *      Calling this method on JAXB 1.0 implementations will throw
     *      an UnsupportedOperationException.
     *
     * @since 1.6, JAXB 2.0
     */
    public JAXBIntrospector createJAXBIntrospector() {
        // to make JAXB 1.0 implementations work, this method must not be
        // abstract
        throw new UnsupportedOperationException();
    }

    /**
     * Generates the schema documents for this context.
     *
     * @param outputResolver
     *      this object controls the output to which schemas
     *      will be sent.
     *
     * @throws IOException
     *      if {@link SchemaOutputResolver} throws an {@link IOException}.
     *
     * @throws UnsupportedOperationException
     *      Calling this method on JAXB 1.0 implementations will throw
     *      an UnsupportedOperationException.
     *
     * @since 1.6, JAXB 2.0
     */
    public void generateSchema(SchemaOutputResolver outputResolver) throws IOException  {
        // to make JAXB 1.0 implementations work, this method must not be
        // abstract
        throw new UnsupportedOperationException();
    }

    private static ClassLoader getContextClassLoader() {
        if (System.getSecurityManager() == null) {
            return Thread.currentThread().getContextClassLoader();
        } else {
            return java.security.AccessController.doPrivileged(
                    (java.security.PrivilegedAction<ClassLoader>) ()
                            -> Thread.currentThread().getContextClassLoader());
        }
    }

}
