/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package javax.xml.bind; import java.lang.reflect.Method; import java.util.Map; import java.util.Properties; import java.io.IOException; import java.io.InputStream; import java.io.BufferedReader; import java.io.InputStreamReader; import org.apache.geronimo.osgi.locator.ProviderLocator; class ContextFinder { private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.bind.v2.ContextFactory"; private static final String JAXB_CONTEXT_PROPERTY = JAXBContext.class.getName(); private static final String JAXB_CONTEXT_FACTORY = JAXBContext.JAXB_CONTEXT_FACTORY; public static JAXBContext find(String contextPath, ClassLoader classLoader, Map properties) throws JAXBException { contextPath = contextPath.trim(); if (contextPath.length() == 0 || contextPath.equals(":")) { throw new JAXBException("Invalid contextPath"); } String className = null; String[] packages = contextPath.split("[:]"); for (String pkg : packages) { String url = pkg.replace('.', '/') + "/jaxb.properties"; className = loadClassNameFromProperties(url, classLoader); if (className != null) { break; } } if (className == null) { className = System.getProperty(JAXB_CONTEXT_PROPERTY); } Class spi = null; // if no specifically specified name, check for META-INF/services, and // fall back to the default factory class if that fails if (className == null) { spi = loadSPIClass(JAXBContext.class, classLoader); if (spi == null) { spi = loadSpi(PLATFORM_DEFAULT_FACTORY_CLASS, classLoader); } } else { spi = loadSpi(className, classLoader); } try { Method m = spi.getMethod("createContext", new Class[] { String.class, ClassLoader.class, Map.class }); return (JAXBContext) m.invoke(null, new Object[] { contextPath, classLoader, properties }); } catch (NoSuchMethodException e) { // will try JAXB 1.0 compatible createContext() method } catch (Throwable t) { throw new JAXBException("Unable to create context", t); } // try old JAXB 1.0 compatible createContext() method try { Method m = spi.getMethod("createContext", new Class[] { String.class, ClassLoader.class }); return (JAXBContext) m.invoke(null, new Object[] { contextPath, classLoader }); } catch (Throwable t) { throw new JAXBException("Unable to create context", t); } } public static JAXBContext find(Class[] classes, Map properties) throws JAXBException { String className = null; for (Class cl : classes) { Package pkg = cl.getPackage(); if (pkg != null) { String url = pkg.getName().replace('.', '/') + "/jaxb.properties"; className = loadClassNameFromProperties(url, cl.getClassLoader()); if (className != null) { break; } } } if (className == null) { className = System.getProperty(JAXB_CONTEXT_PROPERTY); } ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Class spi = null; // if no specifically specified name, check for META-INF/services, and // fall back to the default factory class if that fails if (className == null) { spi = loadSPIClass(JAXBContext.class, classLoader); if (spi == null) { spi = loadSpi(PLATFORM_DEFAULT_FACTORY_CLASS, classLoader); } } else { spi = loadSpi(className, classLoader); } try { Method m = spi.getMethod("createContext", new Class[] { Class[].class, Map.class }); return (JAXBContext) m.invoke(null, new Object[] { classes, properties }); } catch (Throwable t) { throw new JAXBException("Unable to create context", t); } } private static String loadClassNameFromProperties(String url, ClassLoader classLoader) throws JAXBException { try { InputStream is; if (classLoader != null) { is = classLoader.getResourceAsStream(url); } else { is = ClassLoader.getSystemResourceAsStream(url); } if (is != null) { try { Properties props = new Properties(); props.load(is); String className = props.getProperty(JAXB_CONTEXT_FACTORY); if (className == null) { throw new JAXBException("jaxb.properties file " + url + " should contain a " + JAXB_CONTEXT_FACTORY + " property"); } return className.trim(); } finally { is.close(); } } else { return null; } } catch (IOException e) { throw new JAXBException(e); } } private static Class<?> loadSPIClass(Class<?> iface, ClassLoader classLoader) throws JAXBException { try { // delegate this to common processing return ProviderLocator.getServiceClass(iface.getName(), ContextFinder.class,classLoader ); } catch (ClassNotFoundException e) { throw new JAXBException("Provider " + iface.getName() + " not found", e); } } private static Class loadSpi(String className, ClassLoader classLoader) throws JAXBException { try { return ProviderLocator.loadClass(className, ContextFinder.class, classLoader); } catch (ClassNotFoundException e) { throw new JAXBException("Provider " + className + " not found", e); } } }