Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: javax/xml/bind/JAXBContext.java


1   /*
2    * Copyright 2003, 2004  The Apache Software Foundation
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15  
16   */
17  package javax.xml.bind;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.lang.reflect.InvocationTargetException;
22  import java.lang.reflect.Method;
23  import java.lang.reflect.Modifier;
24  import java.net.URL;
25  import java.util.Properties;
26  import java.util.StringTokenizer;
27  
28  
29  /** <p>The <code>JAXBContext</code> provides the JAXB users anchor to
30   * the implmentation and hos generated classes. A JAXBContext is used to
31   * obtain instances of {@link javax.xml.bind.Marshaller},
32   * {@link javax.xml.bind.Unmarshaller}, and
33   * {@link javax.xml.bind.Validator}. To obtain a JAXBContext, the
34   * application invokes
35   * <pre>
36   *   JAXBContext context = JAXBContext.newInstance("com.mycompany:com.mycompany.xml");
37   * </pre>
38   * The list of colon separated package names matches the list in the
39   * schemas used to generate classes. In other words: If you have a
40   * schema using package name "com.mycompany.xml", then this package
41   * name has to be part of the list.</p>
42   * <p>The <code>JAXBContext</code> class will scan the given list of packages
43   * for a file called <samp>jaxb.properties</samp>. This file contains the
44   * name of an instantiation class in the property
45   * {@link #JAXB_CONTEXT_FACTORY}. (See {@link #newInstance(String)} for
46   * details on how the class name is obtained.) Once such a file is found, the
47   * given class is loaded via {@link ClassLoader#loadClass(java.lang.String)}.
48   * The <code>JAXBContext</code> class demands, that the created object
49   * has a method
50   * <pre>
51   *   public static JAXBContext createContext(String pPath, ClassLoader pClassLoader)
52   *     throws JAXBException;
53   * </pre>
54   * This method is invoked with the same path and {@link ClassLoader} than
55   * above. See {@link #newInstance(String,ClassLoader)}} for details on the choice
56   * of the {@link ClassLoader}.</p>
57   * <p>The created context will scan the same package path for implementation
58   * specific configuration details (in the case of the <code>JaxMe</code>
59   * application a file called <samp>Configuration.xml</samp> in any of the
60   * packages) and do whatever else is required to initialize the runtime.
61   * In particular it will invoke
62   * {@link DatatypeConverter#setDatatypeConverter(DatatypeConverterInterface)}.</p>
63   *
64   * @author JSR-31
65   * @since JAXB1.0
66   * @see Marshaller
67   * @see Unmarshaller
68   * @see Validator
69   */
70  public abstract class JAXBContext {
71    private static final Class[] CONTEXT_CLASSES = new Class[]{String.class, ClassLoader.class};
72  
73    /** <p>This is the name of the property used to determine the name
74     * of the initialization class: "javax.xml.bind.context.factory".
75     * The name is used by {@link #newInstance(String)} and
76     * {@link #newInstance(String,ClassLoader)}. It contains a class
77     * name. The class must contain a static method
78     * <pre>
79     *   public static JAXBContext createContext(String, ClassLoader) throws JAXBException;
80     * </pre>
81     * which is invoked to create the actual instance of JAXBContext.</p>
82     */
83    public static final java.lang.String JAXB_CONTEXT_FACTORY = "javax.xml.bind.context.factory";
84  
85    /** <p>Creates a new instance of <code>JAXBContext</code> by applying
86     * the following algorithm:
87     * <ol>
88     *   <li>The first step is to determine the name of an initialization class.
89     *     For any of the package names in the list given by
90     *     <code>pPath</code> the <code>JAXBContext</code> class will try to find a file
91     *     called <samp>jaxb.properties</samp>. This file's got to be in
92     *     standard property file format. The <code>JAXBContext</code> class
93     *     will load the property file.</li>
94     *   <li>A property called "javax.xml.bind.context.factory" (see
95     *     {@link #JAXB_CONTEXT_FACTORY}) is evaluated. It must contain the
96     *     name of an initialization class. The initialization class is
97     *     loaded via
98     *     <code>Thread.currentThread().getContextClassLoader().loadClass(String)</code>.</li>
99     *   <li>The initialization class must contain a method
100    *     <pre>
101    *       public static JAXBContext createContext(String, ClassLoader) throws JAXBException;
102    *     </pre>
103    *     which is invoked with the <code>pPath</code> argument and the
104    *     {@link ClassLoader} of the <code>JAXBContext</class> class as
105    *     parameters. The result of this method is also used as the
106    *     result of the <code>newInstance(String)</code> method.</li>
107    * </ol>
108    * @param pPath A colon separated path of package names where to look for
109    *   <samp>jaxb.properties</samp> files. The package names must match the
110    *   generated classes which you are going to use in your application.
111    * @return An initialized instance of <code>JAXBContext</code>.
112    * @throws JAXBException An error occurred while creating the JAXBContext instance. 
113    */  
114   public static JAXBContext newInstance(java.lang.String pPath) throws JAXBException {
115     ClassLoader cl = Thread.currentThread().getContextClassLoader();
116     if (cl == null) {
117       cl = JAXBContext.class.getClassLoader();
118     }
119     return newInstance(pPath, cl);
120   }
121 
122   /** <p>Creates a new instance of <code>JAXBContext</code> by applying
123    * the following algorithm:
124    * <ol>
125    *   <li>The first step is to determine the name of an initialization class.
126    *     For any of the package names in the list given by
127    *     <code>pPath</code> the <code>JAXBContext</code> class will try to find a file
128    *     called <samp>jaxb.properties</samp>. This file's got to be in
129    *     standard property file format. The <code>JAXBContext</code> class
130    *     will load the property file.</li>
131    *   <li>A property called "javax.xml.bind.context.factory" (see
132    *     {@link #JAXB_CONTEXT_FACTORY}) is evaluated. It must contain the
133    *     name of an initialization class. The initialization class is
134    *     loaded via
135    *     <code>pClassLoader.loadClass(String)</code>.</li>
136    *   <li>The initialization class must contain a method
137    *     <pre>
138    *       public static JAXBContext createContext(String, ClassLoader) throws JAXBException;
139    *     </pre>
140    *     which is invoked with the parameters <code>pPath</code> and
141    *     <code>pClassLoader</code>. The result of this method is also
142    *     used as the result of the <code>newInstance(String)</code>
143    *     method.</li>
144    * </ol>
145    * @param pPath A colon separated path of package names where to look for
146    *   <samp>jaxb.properties</samp> files. The package names must match the
147    *   generated classes which you are going to use in your application.
148    * @return An initialized instance of <code>JAXBContext</code>.
149    * @throws JAXBException An error occurred while creating the JAXBContext instance.
150    */
151   public static JAXBContext newInstance(String pPath, ClassLoader pClassLoader) throws JAXBException {
152     if (pPath == null) {
153       throw new JAXBException("The context path must not be null.");
154     }
155     if (pClassLoader == null) {
156       throw new JAXBException("The classloader must not be null.");
157     }
158     for (StringTokenizer st = new StringTokenizer(pPath, ":");  st.hasMoreTokens();  ) {
159       String packageName = st.nextToken();
160       String resourceName = packageName.replace('.', '/') + "/jaxb.properties";
161       URL resource = pClassLoader.getResource(resourceName);
162       if (resource == null) {
163         continue;
164       }
165       Properties props = new Properties();
166       InputStream istream = null;
167       try {
168         istream = resource.openStream();
169         props.load(istream);
170         istream.close();
171         istream = null;
172       } catch (IOException e) {
173         throw new JAXBException("Failed to load property file " + resource, e);
174       } finally {
175         if (istream != null) { try { istream.close(); } catch (Throwable ignore) {} }
176       }
177       String className = props.getProperty(JAXB_CONTEXT_FACTORY);
178       if (className == null) {
179         throw new JAXBException("The property " + JAXB_CONTEXT_FACTORY + " is not set in " + resource);
180       }
181       Class c;
182       try {
183         c = pClassLoader.loadClass(className);
184       } catch (ClassNotFoundException e) {
185         throw new JAXBException("The class " + className + ", referenced by property " +
186                                  JAXB_CONTEXT_FACTORY + " in " + resource + ", could not be loaded.");
187       }
188       Method m;
189       try {
190         m = c.getMethod("createContext", CONTEXT_CLASSES);
191       } catch (NoSuchMethodException e) {
192         throw new JAXBException("The class " + c + " does not have a method 'public static createContext(String, ClassLoader) throws JAXBException'");
193       }
194       int modifiers = m.getModifiers();
195       if (m == null  ||  !Modifier.isStatic(modifiers)  ||  !Modifier.isPublic(modifiers)) {
196         throw new JAXBException("The class " + c + " does not have a method 'public static createContext(String, ClassLoader) throws JAXBException'");
197       }
198       Object o;
199       try {
200         o = m.invoke(null, new Object[]{pPath, pClassLoader});
201       } catch (IllegalAccessException e) {
202         throw new JAXBException("Illegal access to method " + c.getName() +
203                                  ".createContext(String,ClassLoader).", e);
204       } catch (InvocationTargetException e) {
205         Throwable t = e.getTargetException();
206         throw new JAXBException(t.getClass().getName() + " in method " + c.getName() +
207                                  ".createContext(String,ClassLoader): " + t.getMessage(), t);
208       }
209       if (o == null) {
210         throw new JAXBException("The method " + c.getName() +
211                                  ".createContext(String,ClassLoader) returned null.");
212       }
213       try {
214         return (JAXBContext) o;
215       } catch (ClassCastException e) {
216         throw new JAXBException("The object created by " + c.getName() +
217                                  ".createContext(String,ClassLoader) cannot be casted to " +
218                                  JAXBContext.class.getName() + ".", e);
219       }
220     }
221     throw new JAXBException("Failed to resolve resource jaxb.properties via path " + pPath +
222                              " and ClassLoader " + pClassLoader);
223   }
224 
225   /** <p>Creates a new instance of {@link Marshaller}. The
226    * {@link Marshaller} can be used
227    * to convert JAXB objects into XML data.</p>
228    * <p><em>Note</em>: Marshallers are reusable, but not reentrant (thread safe).</p>
229    */
230   public abstract Marshaller createMarshaller() throws JAXBException;
231 
232   /** <p>Creates a new instance of {@link Unmarshaller}. The
233    * {@link Unmarshaller} can be used
234    * to convert XML data into JAXB objects.</p>
235    * <p><em>Note</em>: Unmarshallers are reusable, but not reentrant (thread safe).</p>
236    */
237   public abstract Unmarshaller createUnmarshaller() throws JAXBException;
238 
239   /** <p>Creates a new instance of {@link Validator}. The
240    * {@link Validator} can be used to validate JAXB objects.</p>
241    */
242   public abstract Validator createValidator() throws JAXBException;
243 }