View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package javax.xml.bind;
18  
19  import java.lang.reflect.Method;
20  import java.util.Map;
21  import java.util.Properties;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.BufferedReader;
25  import java.io.InputStreamReader;
26  
27  class ContextFinder {
28  
29      private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.bind.v2.ContextFactory";
30      private static final String JAXB_CONTEXT_PROPERTY = JAXBContext.class.getName();
31      private static final String JAXB_CONTEXT_FACTORY = JAXBContext.JAXB_CONTEXT_FACTORY;
32  
33      public static JAXBContext find(String contextPath, ClassLoader classLoader, Map properties) throws JAXBException {
34          contextPath = contextPath.trim();
35          if (contextPath.length() == 0 || contextPath.equals(":")) {
36              throw new JAXBException("Invalid contextPath");
37          }
38          String className = null;
39          String[] packages = contextPath.split("[:]");
40          for (String pkg : packages) {
41              String url = pkg.replace('.', '/') + "/jaxb.properties";
42              className = loadClassNameFromProperties(url, classLoader);
43              if (className != null) {
44                  break;
45              }
46          }
47          if (className == null) {
48              className = System.getProperty(JAXB_CONTEXT_PROPERTY);
49          }
50          if (className == null) {
51              String url = "META-INF/services/" + JAXB_CONTEXT_PROPERTY;
52              className = loadClassName(url, classLoader);
53          }
54          if (className == null) {
55              className = PLATFORM_DEFAULT_FACTORY_CLASS;
56          }
57          Class spi = loadSpi(className, classLoader);
58          try {
59              Method m = spi.getMethod("createContext", new Class[] { String.class, ClassLoader.class, Map.class });
60              return (JAXBContext) m.invoke(null, new Object[] { contextPath, classLoader, properties });
61          } catch (NoSuchMethodException e) {
62              // will try JAXB 1.0 compatible createContext() method
63          } catch (Throwable t) {
64              throw new JAXBException("Unable to create context", t);
65          }
66  
67          // try old JAXB 1.0 compatible createContext() method
68          try {
69              Method m = spi.getMethod("createContext", new Class[] { String.class, ClassLoader.class });
70              return (JAXBContext) m.invoke(null, new Object[] { contextPath, classLoader });
71          } catch (Throwable t) {
72              throw new JAXBException("Unable to create context", t);
73          }
74      }
75  
76  
77      public static JAXBContext find(Class[] classes, Map properties) throws JAXBException {
78          String className = null;
79          for (Class cl : classes) {
80              Package pkg = cl.getPackage();
81              if (pkg != null) {
82                  String url = pkg.getName().replace('.', '/') + "/jaxb.properties";
83                  className = loadClassNameFromProperties(url, cl.getClassLoader());
84                  if (className != null) {
85                      break;
86                  }
87              }
88          }
89          if (className == null) {
90              className = System.getProperty(JAXB_CONTEXT_PROPERTY);
91          }
92          if (className == null) {
93              String url = "META-INF/services/" + JAXB_CONTEXT_PROPERTY;
94              className = loadClassName(url, Thread.currentThread().getContextClassLoader());
95          }
96          if (className == null) {
97              className = PLATFORM_DEFAULT_FACTORY_CLASS;
98          }
99          Class spi = loadSpi(className, Thread.currentThread().getContextClassLoader());
100         try {
101             Method m = spi.getMethod("createContext", new Class[] { Class[].class, Map.class });
102             return (JAXBContext) m.invoke(null, new Object[] { classes, properties });
103         } catch (Throwable t) {
104             throw new JAXBException("Unable to create context", t);
105         }
106     }
107 
108     private static String loadClassNameFromProperties(String url, ClassLoader classLoader) throws JAXBException {
109         try {
110             InputStream is;
111             if (classLoader != null) {
112                 is = classLoader.getResourceAsStream(url);
113             } else {
114                 is = ClassLoader.getSystemResourceAsStream(url);
115             }
116             if (is != null) {
117                 try {
118                     Properties props = new Properties();
119                     props.load(is);
120                     String className = props.getProperty(JAXB_CONTEXT_FACTORY);
121                     if (className == null) {
122                         throw new JAXBException("jaxb.properties file " + url + " should contain a " + JAXB_CONTEXT_FACTORY + " property");
123                     }
124                     return className.trim();
125                 } finally {
126                     is.close();
127                 }
128             } else {
129                 return null;
130             }
131         } catch (IOException e) {
132             throw new JAXBException(e);
133         }
134     }
135 
136     private static String loadClassName(String url, ClassLoader classLoader) throws JAXBException {
137         try {
138             InputStream is;
139             if (classLoader != null) {
140                 is = classLoader.getResourceAsStream(url);
141             } else {
142                 is = ClassLoader.getSystemResourceAsStream(url);
143             }
144             if (is != null) {
145                 try {
146                     BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
147                     return r.readLine().trim();
148                 } finally {
149                     is.close();
150                 }
151             }
152             return null;
153         } catch (IOException e) {
154             throw new JAXBException(e);
155         }
156     }
157 
158     private static Class loadSpi(String className, ClassLoader classLoader) throws JAXBException {
159         Class spiClass;
160         try {
161             if (classLoader != null) {
162                 spiClass = classLoader.loadClass(className);
163             } else {
164                 spiClass = Class.forName(className);
165             }
166         } catch (ClassNotFoundException e) {
167             throw new JAXBException("Provider " + className + " not found", e);
168         }
169         return spiClass;
170     }
171 
172 
173 }