in jaxb-api-2.2/src/main/java/javax/xml/bind/ContextFinder.java [314:397]
static JAXBContext find( Class[] classes, Map properties ) throws JAXBException {
// TODO: do we want/need another layer of searching in $java.home/lib/jaxb.properties like JAXP?
final String jaxbContextFQCN = JAXBContext.class.getName();
String factoryClassName;
// search for jaxb.properties in the class loader of each class first
for (final Class c : classes) {
// this classloader is used only to load jaxb.properties, so doing this should be safe.
ClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return c.getClassLoader();
}
});
Package pkg = c.getPackage();
if(pkg==null)
continue; // this is possible for primitives, arrays, and classes that are loaded by poorly implemented ClassLoaders
String packageName = pkg.getName().replace('.', '/');
// TODO: do we want to optimize away searching the same package? org.Foo, org.Bar, com.Baz
// classes from the same package might come from different class loades, so it might be a bad idea
// TODO: it's easier to look things up from the class
// c.getResourceAsStream("jaxb.properties");
// build the resource name and use the property loader code
String resourceName = packageName+"/jaxb.properties";
logger.fine("Trying to locate "+resourceName);
Properties props = loadJAXBProperties(classLoader, resourceName);
if (props == null) {
logger.fine(" not found");
} else {
logger.fine(" found");
if (props.containsKey(JAXB_CONTEXT_FACTORY)) {
// trim() seems redundant, but adding to satisfy customer complaint
factoryClassName = props.getProperty(JAXB_CONTEXT_FACTORY).trim();
return newInstance(classes, properties, factoryClassName);
} else {
throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, JAXB_CONTEXT_FACTORY));
}
}
}
// search for a system property second (javax.xml.bind.JAXBContext)
logger.fine("Checking system property "+jaxbContextFQCN);
factoryClassName = AccessController.doPrivileged(new GetPropertyAction(jaxbContextFQCN));
if( factoryClassName != null ) {
logger.fine(" found "+factoryClassName);
return newInstance( classes, properties, factoryClassName );
}
logger.fine(" not found");
// search META-INF services next
logger.fine("Checking META-INF/services");
BufferedReader r;
try {
final String resource = new StringBuilder("META-INF/services/").append(jaxbContextFQCN).toString();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL resourceURL;
if(classLoader==null)
resourceURL = ClassLoader.getSystemResource(resource);
else
resourceURL = classLoader.getResource(resource);
if (resourceURL != null) {
logger.fine("Reading "+resourceURL);
r = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "UTF-8"));
factoryClassName = r.readLine().trim();
return newInstance(classes, properties, factoryClassName);
} else {
logger.fine("Unable to find: " + resource);
}
} catch (UnsupportedEncodingException e) {
// should never happen
throw new JAXBException(e);
} catch (IOException e) {
throw new JAXBException(e);
}
// else no provider found
logger.fine("Trying to create the platform default provider");
return newInstance(classes, properties, PLATFORM_DEFAULT_FACTORY_CLASS);
}