private static JAXBContext createContext(Class<?> clazz) throws JAXBException {
return JAXBContext.newInstance(clazz);
}
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);
contextFinder
private static Class safeLoadClass(String className, ClassLoader classLoader) throws ClassNotFoundException {
logger.fine("Trying to load "+className);
try {
// make sure that the current thread has an access to the package of the given name.
SecurityManager s = System.getSecurityManager();
if (s != null) {
int i = className.lastIndexOf('.');
if (i != -1) {
s.checkPackageAccess(className.substring(0,i));
}
}
if (classLoader == null) {
return Class.forName(className);
} else {
return classLoader.loadClass(className);
}
} catch (SecurityException se) {
// anyone can access the platform default factory class without permission
if (PLATFORM_DEFAULT_FACTORY_CLASS.equals(className)) {
return Class.forName(className);
}
throw se;
}
}
jaxb 在new instance时候的调用classloader的方式
最新推荐文章于 2023-05-31 14:42:50 发布