src/share/jaxws_classes/javax/xml/bind/ContextFinder.java

Tue, 07 Nov 2017 18:54:04 -0800

author
asaha
date
Tue, 07 Nov 2017 18:54:04 -0800
changeset 1528
f453f4eaf8b4
parent 397
b99d7e355d4b
child 637
9c07ef4934dd
permissions
-rw-r--r--

Added tag jdk8u162-b06 for changeset 6095742f8034

ohair@286 1 /*
mkos@397 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
ohair@286 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ohair@286 4 *
ohair@286 5 * This code is free software; you can redistribute it and/or modify it
ohair@286 6 * under the terms of the GNU General Public License version 2 only, as
ohair@286 7 * published by the Free Software Foundation. Oracle designates this
ohair@286 8 * particular file as subject to the "Classpath" exception as provided
ohair@286 9 * by Oracle in the LICENSE file that accompanied this code.
ohair@286 10 *
ohair@286 11 * This code is distributed in the hope that it will be useful, but WITHOUT
ohair@286 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ohair@286 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ohair@286 14 * version 2 for more details (a copy is included in the LICENSE file that
ohair@286 15 * accompanied this code).
ohair@286 16 *
ohair@286 17 * You should have received a copy of the GNU General Public License version
ohair@286 18 * 2 along with this work; if not, write to the Free Software Foundation,
ohair@286 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ohair@286 20 *
ohair@286 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@286 22 * or visit www.oracle.com if you need additional information or have any
ohair@286 23 * questions.
ohair@286 24 */
ohair@286 25
ohair@286 26 package javax.xml.bind;
ohair@286 27
ohair@286 28 import java.util.Iterator;
ohair@286 29 import java.io.BufferedReader;
ohair@286 30 import java.io.IOException;
ohair@286 31 import java.io.InputStream;
ohair@286 32 import java.io.InputStreamReader;
ohair@286 33 import java.io.UnsupportedEncodingException;
ohair@286 34 import java.lang.reflect.InvocationTargetException;
ohair@286 35 import java.lang.reflect.Method;
ohair@286 36 import java.net.URL;
ohair@286 37 import java.util.Map;
ohair@286 38 import java.util.Properties;
ohair@286 39 import java.util.StringTokenizer;
ohair@286 40 import java.util.logging.ConsoleHandler;
ohair@286 41 import java.util.logging.Level;
ohair@286 42 import java.util.logging.Logger;
ohair@286 43 import java.security.AccessController;
ohair@286 44
ohair@286 45 import static javax.xml.bind.JAXBContext.JAXB_CONTEXT_FACTORY;
ohair@286 46
ohair@286 47
ohair@286 48 /**
ohair@286 49 * This class is package private and therefore is not exposed as part of the
ohair@286 50 * JAXB API.
ohair@286 51 *
ohair@286 52 * This code is designed to implement the JAXB 1.0 spec pluggability feature
ohair@286 53 *
ohair@286 54 * @author <ul><li>Ryan Shoemaker, Sun Microsystems, Inc.</li></ul>
ohair@286 55 * @see JAXBContext
ohair@286 56 */
ohair@286 57 class ContextFinder {
ohair@286 58 private static final Logger logger;
ohair@286 59 static {
ohair@286 60 logger = Logger.getLogger("javax.xml.bind");
ohair@286 61 try {
ohair@286 62 if (AccessController.doPrivileged(new GetPropertyAction("jaxb.debug")) != null) {
ohair@286 63 // disconnect the logger from a bigger framework (if any)
ohair@286 64 // and take the matters into our own hands
ohair@286 65 logger.setUseParentHandlers(false);
ohair@286 66 logger.setLevel(Level.ALL);
ohair@286 67 ConsoleHandler handler = new ConsoleHandler();
ohair@286 68 handler.setLevel(Level.ALL);
ohair@286 69 logger.addHandler(handler);
ohair@286 70 } else {
ohair@286 71 // don't change the setting of this logger
ohair@286 72 // to honor what other frameworks
ohair@286 73 // have done on configurations.
ohair@286 74 }
ohair@286 75 } catch(Throwable t) {
ohair@286 76 // just to be extra safe. in particular System.getProperty may throw
ohair@286 77 // SecurityException.
ohair@286 78 }
ohair@286 79 }
ohair@286 80
ohair@286 81 /**
ohair@286 82 * If the {@link InvocationTargetException} wraps an exception that shouldn't be wrapped,
ohair@286 83 * throw the wrapped exception.
ohair@286 84 */
ohair@286 85 private static void handleInvocationTargetException(InvocationTargetException x) throws JAXBException {
ohair@286 86 Throwable t = x.getTargetException();
ohair@286 87 if( t != null ) {
ohair@286 88 if( t instanceof JAXBException )
ohair@286 89 // one of our exceptions, just re-throw
ohair@286 90 throw (JAXBException)t;
ohair@286 91 if( t instanceof RuntimeException )
ohair@286 92 // avoid wrapping exceptions unnecessarily
ohair@286 93 throw (RuntimeException)t;
ohair@286 94 if( t instanceof Error )
ohair@286 95 throw (Error)t;
ohair@286 96 }
ohair@286 97 }
ohair@286 98
ohair@286 99
ohair@286 100 /**
ohair@286 101 * Determine if two types (JAXBContext in this case) will generate a ClassCastException.
ohair@286 102 *
ohair@286 103 * For example, (targetType)originalType
ohair@286 104 *
ohair@286 105 * @param originalType
ohair@286 106 * The Class object of the type being cast
ohair@286 107 * @param targetType
ohair@286 108 * The Class object of the type that is being cast to
ohair@286 109 * @return JAXBException to be thrown.
ohair@286 110 */
ohair@286 111 private static JAXBException handleClassCastException(Class originalType, Class targetType) {
ohair@286 112 final URL targetTypeURL = which(targetType);
ohair@286 113
ohair@286 114 return new JAXBException(Messages.format(Messages.ILLEGAL_CAST,
ohair@286 115 // we don't care where the impl class is, we want to know where JAXBContext lives in the impl
ohair@286 116 // class' ClassLoader
ohair@286 117 getClassClassLoader(originalType).getResource("javax/xml/bind/JAXBContext.class"),
ohair@286 118 targetTypeURL));
ohair@286 119 }
ohair@286 120
ohair@286 121 /**
ohair@286 122 * Create an instance of a class using the specified ClassLoader
ohair@286 123 */
ohair@286 124 static JAXBContext newInstance( String contextPath,
ohair@286 125 String className,
ohair@286 126 ClassLoader classLoader,
ohair@286 127 Map properties )
ohair@286 128 throws JAXBException {
ohair@286 129 try {
ohair@286 130 Class spFactory = safeLoadClass(className,classLoader);
ohair@286 131 return newInstance(contextPath, spFactory, classLoader, properties);
ohair@286 132 } catch (ClassNotFoundException x) {
ohair@286 133 throw new JAXBException(
ohair@286 134 Messages.format( Messages.PROVIDER_NOT_FOUND, className ),
ohair@286 135 x);
ohair@286 136 } catch (RuntimeException x) {
ohair@286 137 // avoid wrapping RuntimeException to JAXBException,
ohair@286 138 // because it indicates a bug in this code.
ohair@286 139 throw x;
ohair@286 140 } catch (Exception x) {
ohair@286 141 // can't catch JAXBException because the method is hidden behind
ohair@286 142 // reflection. Root element collisions detected in the call to
ohair@286 143 // createContext() are reported as JAXBExceptions - just re-throw it
ohair@286 144 // some other type of exception - just wrap it
ohair@286 145 throw new JAXBException(
ohair@286 146 Messages.format( Messages.COULD_NOT_INSTANTIATE, className, x ),
ohair@286 147 x);
ohair@286 148 }
ohair@286 149 }
ohair@286 150
ohair@286 151 static JAXBContext newInstance( String contextPath,
ohair@286 152 Class spFactory,
ohair@286 153 ClassLoader classLoader,
ohair@286 154 Map properties )
ohair@286 155 throws JAXBException
ohair@286 156 {
ohair@286 157 try {
ohair@286 158 /*
ohair@286 159 * javax.xml.bind.context.factory points to a class which has a
ohair@286 160 * static method called 'createContext' that
ohair@286 161 * returns a javax.xml.JAXBContext.
ohair@286 162 */
ohair@286 163
ohair@286 164 Object context = null;
ohair@286 165
ohair@286 166 // first check the method that takes Map as the third parameter.
ohair@286 167 // this is added in 2.0.
ohair@286 168 try {
ohair@286 169 Method m = spFactory.getMethod("createContext",String.class,ClassLoader.class,Map.class);
ohair@286 170 // any failure in invoking this method would be considered fatal
ohair@286 171 context = m.invoke(null,contextPath,classLoader,properties);
ohair@286 172 } catch (NoSuchMethodException e) {
ohair@286 173 // it's not an error for the provider not to have this method.
ohair@286 174 }
ohair@286 175
ohair@286 176 if(context==null) {
ohair@286 177 // try the old method that doesn't take properties. compatible with 1.0.
ohair@286 178 // it is an error for an implementation not to have both forms of the createContext method.
ohair@286 179 Method m = spFactory.getMethod("createContext",String.class,ClassLoader.class);
ohair@286 180 // any failure in invoking this method would be considered fatal
ohair@286 181 context = m.invoke(null,contextPath,classLoader);
ohair@286 182 }
ohair@286 183
ohair@286 184 if(!(context instanceof JAXBContext)) {
ohair@286 185 // the cast would fail, so generate an exception with a nice message
ohair@286 186 throw handleClassCastException(context.getClass(), JAXBContext.class);
ohair@286 187 }
ohair@286 188 return (JAXBContext)context;
ohair@286 189 } catch (InvocationTargetException x) {
ohair@286 190 handleInvocationTargetException(x);
ohair@286 191 // for other exceptions, wrap the internal target exception
ohair@286 192 // with a JAXBException
ohair@286 193 Throwable e = x;
ohair@286 194 if(x.getTargetException()!=null)
ohair@286 195 e = x.getTargetException();
ohair@286 196
ohair@286 197 throw new JAXBException( Messages.format( Messages.COULD_NOT_INSTANTIATE, spFactory, e ), e );
ohair@286 198 } catch (RuntimeException x) {
ohair@286 199 // avoid wrapping RuntimeException to JAXBException,
ohair@286 200 // because it indicates a bug in this code.
ohair@286 201 throw x;
ohair@286 202 } catch (Exception x) {
ohair@286 203 // can't catch JAXBException because the method is hidden behind
ohair@286 204 // reflection. Root element collisions detected in the call to
ohair@286 205 // createContext() are reported as JAXBExceptions - just re-throw it
ohair@286 206 // some other type of exception - just wrap it
ohair@286 207 throw new JAXBException(
ohair@286 208 Messages.format( Messages.COULD_NOT_INSTANTIATE, spFactory, x ),
ohair@286 209 x);
ohair@286 210 }
ohair@286 211 }
ohair@286 212
ohair@286 213
ohair@286 214 /**
ohair@286 215 * Create an instance of a class using the thread context ClassLoader
ohair@286 216 */
ohair@286 217 static JAXBContext newInstance(
ohair@286 218 Class[] classes,
ohair@286 219 Map properties,
ohair@286 220 String className) throws JAXBException {
ohair@286 221 ClassLoader cl = getContextClassLoader();
ohair@286 222 Class spi;
ohair@286 223 try {
ohair@286 224 spi = safeLoadClass(className,cl);
ohair@286 225 } catch (ClassNotFoundException e) {
ohair@286 226 throw new JAXBException(e);
ohair@286 227 }
ohair@286 228
ohair@286 229 if(logger.isLoggable(Level.FINE)) {
ohair@286 230 // extra check to avoid costly which operation if not logged
ohair@286 231 logger.log(Level.FINE, "loaded {0} from {1}", new Object[]{className, which(spi)});
ohair@286 232 }
ohair@286 233
ohair@286 234 return newInstance(classes, properties, spi);
ohair@286 235 }
ohair@286 236
ohair@286 237 static JAXBContext newInstance(Class[] classes,
ohair@286 238 Map properties,
ohair@286 239 Class spFactory) throws JAXBException {
ohair@286 240 Method m;
ohair@286 241 try {
ohair@286 242 m = spFactory.getMethod("createContext", Class[].class, Map.class);
ohair@286 243 } catch (NoSuchMethodException e) {
ohair@286 244 throw new JAXBException(e);
ohair@286 245 }
ohair@286 246 try {
ohair@286 247 Object context = m.invoke(null, classes, properties);
ohair@286 248 if(!(context instanceof JAXBContext)) {
ohair@286 249 // the cast would fail, so generate an exception with a nice message
ohair@286 250 throw handleClassCastException(context.getClass(), JAXBContext.class);
ohair@286 251 }
ohair@286 252 return (JAXBContext)context;
ohair@286 253 } catch (IllegalAccessException e) {
ohair@286 254 throw new JAXBException(e);
ohair@286 255 } catch (InvocationTargetException e) {
ohair@286 256 handleInvocationTargetException(e);
ohair@286 257
ohair@286 258 Throwable x = e;
ohair@286 259 if (e.getTargetException() != null)
ohair@286 260 x = e.getTargetException();
ohair@286 261
ohair@286 262 throw new JAXBException(x);
ohair@286 263 }
ohair@286 264 }
ohair@286 265
ohair@286 266 static JAXBContext find(String factoryId, String contextPath, ClassLoader classLoader, Map properties ) throws JAXBException {
ohair@286 267
ohair@286 268 // TODO: do we want/need another layer of searching in $java.home/lib/jaxb.properties like JAXP?
ohair@286 269
ohair@286 270 final String jaxbContextFQCN = JAXBContext.class.getName();
ohair@286 271
ohair@286 272 // search context path for jaxb.properties first
ohair@286 273 StringBuilder propFileName;
ohair@286 274 StringTokenizer packages = new StringTokenizer( contextPath, ":" );
ohair@286 275 String factoryClassName;
ohair@286 276
ohair@286 277 if(!packages.hasMoreTokens())
ohair@286 278 // no context is specified
ohair@286 279 throw new JAXBException(Messages.format(Messages.NO_PACKAGE_IN_CONTEXTPATH));
ohair@286 280
ohair@286 281
ohair@286 282 logger.fine("Searching jaxb.properties");
ohair@286 283
ohair@286 284 while( packages.hasMoreTokens() ) {
ohair@286 285 String packageName = packages.nextToken(":").replace('.','/');
ohair@286 286 // com.acme.foo - > com/acme/foo/jaxb.properties
ohair@286 287 propFileName = new StringBuilder().append(packageName).append("/jaxb.properties");
ohair@286 288
ohair@286 289 Properties props = loadJAXBProperties( classLoader, propFileName.toString() );
ohair@286 290 if (props != null) {
ohair@286 291 if (props.containsKey(factoryId)) {
ohair@286 292 factoryClassName = props.getProperty(factoryId);
ohair@286 293 return newInstance( contextPath, factoryClassName, classLoader, properties );
ohair@286 294 } else {
ohair@286 295 throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryId));
ohair@286 296 }
ohair@286 297 }
ohair@286 298 }
ohair@286 299
ohair@286 300 logger.fine("Searching the system property");
ohair@286 301
ohair@286 302 // search for a system property second (javax.xml.bind.JAXBContext)
ohair@286 303 factoryClassName = AccessController.doPrivileged(new GetPropertyAction(JAXBContext.JAXB_CONTEXT_FACTORY));
ohair@286 304 if( factoryClassName != null ) {
ohair@286 305 return newInstance( contextPath, factoryClassName, classLoader, properties );
ohair@286 306 } else { // leave this here to assure compatibility
ohair@286 307 factoryClassName = AccessController.doPrivileged(new GetPropertyAction(jaxbContextFQCN));
ohair@286 308 if( factoryClassName != null ) {
ohair@286 309 return newInstance( contextPath, factoryClassName, classLoader, properties );
ohair@286 310 }
ohair@286 311 }
ohair@286 312
mkos@397 313 // OSGi search
mkos@397 314 Class jaxbContext = lookupJaxbContextUsingOsgiServiceLoader();
mkos@397 315 if (jaxbContext != null) {
mkos@397 316 logger.fine("OSGi environment detected");
mkos@397 317 return newInstance(contextPath, jaxbContext, classLoader, properties);
ohair@286 318 }
ohair@286 319
ohair@286 320 logger.fine("Searching META-INF/services");
ohair@286 321 // search META-INF services next
mkos@397 322 BufferedReader r = null;
ohair@286 323 try {
ohair@286 324 final StringBuilder resource = new StringBuilder().append("META-INF/services/").append(jaxbContextFQCN);
ohair@286 325 final InputStream resourceStream =
ohair@286 326 classLoader.getResourceAsStream(resource.toString());
ohair@286 327
ohair@286 328 if (resourceStream != null) {
ohair@286 329 r = new BufferedReader(new InputStreamReader(resourceStream, "UTF-8"));
mkos@397 330 factoryClassName = r.readLine();
mkos@397 331 if (factoryClassName != null) {
mkos@397 332 factoryClassName = factoryClassName.trim();
mkos@397 333 }
ohair@286 334 r.close();
ohair@286 335 return newInstance(contextPath, factoryClassName, classLoader, properties);
ohair@286 336 } else {
ohair@286 337 logger.log(Level.FINE, "Unable to load:{0}", resource.toString());
ohair@286 338 }
ohair@286 339 } catch (UnsupportedEncodingException e) {
ohair@286 340 // should never happen
ohair@286 341 throw new JAXBException(e);
ohair@286 342 } catch (IOException e) {
ohair@286 343 throw new JAXBException(e);
mkos@397 344 } finally {
mkos@397 345 try {
mkos@397 346 if (r != null) {
mkos@397 347 r.close();
mkos@397 348 }
mkos@397 349 } catch (IOException ex) {
mkos@397 350 Logger.getLogger(ContextFinder.class.getName()).log(Level.SEVERE, null, ex);
mkos@397 351 }
ohair@286 352 }
ohair@286 353
ohair@286 354 // else no provider found
ohair@286 355 logger.fine("Trying to create the platform default provider");
ohair@286 356 return newInstance(contextPath, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties);
ohair@286 357 }
ohair@286 358
ohair@286 359 static JAXBContext find( Class[] classes, Map properties ) throws JAXBException {
ohair@286 360
ohair@286 361 final String jaxbContextFQCN = JAXBContext.class.getName();
ohair@286 362 String factoryClassName;
ohair@286 363
ohair@286 364 // search for jaxb.properties in the class loader of each class first
ohair@286 365 for (final Class c : classes) {
ohair@286 366 // this classloader is used only to load jaxb.properties, so doing this should be safe.
ohair@286 367 ClassLoader classLoader = getClassClassLoader(c);
ohair@286 368 Package pkg = c.getPackage();
ohair@286 369 if(pkg==null)
ohair@286 370 continue; // this is possible for primitives, arrays, and classes that are loaded by poorly implemented ClassLoaders
ohair@286 371 String packageName = pkg.getName().replace('.', '/');
ohair@286 372
ohair@286 373 // TODO: do we want to optimize away searching the same package? org.Foo, org.Bar, com.Baz
ohair@286 374 // classes from the same package might come from different class loades, so it might be a bad idea
ohair@286 375
ohair@286 376 // TODO: it's easier to look things up from the class
ohair@286 377 // c.getResourceAsStream("jaxb.properties");
ohair@286 378
ohair@286 379 // build the resource name and use the property loader code
ohair@286 380 String resourceName = packageName+"/jaxb.properties";
ohair@286 381 logger.log(Level.FINE, "Trying to locate {0}", resourceName);
ohair@286 382 Properties props = loadJAXBProperties(classLoader, resourceName);
ohair@286 383 if (props == null) {
ohair@286 384 logger.fine(" not found");
ohair@286 385 } else {
ohair@286 386 logger.fine(" found");
ohair@286 387 if (props.containsKey(JAXB_CONTEXT_FACTORY)) {
ohair@286 388 // trim() seems redundant, but adding to satisfy customer complaint
ohair@286 389 factoryClassName = props.getProperty(JAXB_CONTEXT_FACTORY).trim();
ohair@286 390 return newInstance(classes, properties, factoryClassName);
ohair@286 391 } else {
ohair@286 392 throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, JAXB_CONTEXT_FACTORY));
ohair@286 393 }
ohair@286 394 }
ohair@286 395 }
ohair@286 396
ohair@286 397 // search for a system property second (javax.xml.bind.JAXBContext)
ohair@286 398 logger.log(Level.FINE, "Checking system property {0}", JAXBContext.JAXB_CONTEXT_FACTORY);
ohair@286 399 factoryClassName = AccessController.doPrivileged(new GetPropertyAction(JAXBContext.JAXB_CONTEXT_FACTORY));
ohair@286 400 if (factoryClassName != null) {
ohair@286 401 logger.log(Level.FINE, " found {0}", factoryClassName);
ohair@286 402 return newInstance( classes, properties, factoryClassName );
ohair@286 403 } else { // leave it here for compatibility reasons
ohair@286 404 logger.fine(" not found");
ohair@286 405 logger.log(Level.FINE, "Checking system property {0}", jaxbContextFQCN);
ohair@286 406 factoryClassName = AccessController.doPrivileged(new GetPropertyAction(jaxbContextFQCN));
ohair@286 407 if (factoryClassName != null) {
ohair@286 408 logger.log(Level.FINE, " found {0}", factoryClassName);
ohair@286 409 return newInstance( classes, properties, factoryClassName );
ohair@286 410 } else {
ohair@286 411 logger.fine(" not found");
ohair@286 412 }
ohair@286 413 }
ohair@286 414
mkos@397 415 // OSGi search
mkos@397 416 Class jaxbContext = lookupJaxbContextUsingOsgiServiceLoader();
mkos@397 417 if (jaxbContext != null) {
ohair@286 418 logger.fine("OSGi environment detected");
mkos@397 419 return newInstance(classes, properties, jaxbContext);
ohair@286 420 }
ohair@286 421
ohair@286 422 // search META-INF services next
ohair@286 423 logger.fine("Checking META-INF/services");
mkos@397 424 BufferedReader r = null;
ohair@286 425 try {
ohair@286 426 final String resource = new StringBuilder("META-INF/services/").append(jaxbContextFQCN).toString();
ohair@286 427 ClassLoader classLoader = getContextClassLoader();
ohair@286 428 URL resourceURL;
ohair@286 429 if(classLoader==null)
ohair@286 430 resourceURL = ClassLoader.getSystemResource(resource);
ohair@286 431 else
ohair@286 432 resourceURL = classLoader.getResource(resource);
ohair@286 433
ohair@286 434 if (resourceURL != null) {
ohair@286 435 logger.log(Level.FINE, "Reading {0}", resourceURL);
ohair@286 436 r = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "UTF-8"));
mkos@397 437 factoryClassName = r.readLine();
mkos@397 438 if (factoryClassName != null) {
mkos@397 439 factoryClassName = factoryClassName.trim();
mkos@397 440 }
ohair@286 441 return newInstance(classes, properties, factoryClassName);
ohair@286 442 } else {
ohair@286 443 logger.log(Level.FINE, "Unable to find: {0}", resource);
ohair@286 444 }
ohair@286 445 } catch (UnsupportedEncodingException e) {
ohair@286 446 // should never happen
ohair@286 447 throw new JAXBException(e);
ohair@286 448 } catch (IOException e) {
ohair@286 449 throw new JAXBException(e);
mkos@397 450 } finally {
mkos@397 451 if (r != null) {
mkos@397 452 try {
mkos@397 453 r.close();
mkos@397 454 } catch (IOException ex) {
mkos@397 455 logger.log(Level.FINE, "Unable to close stream", ex);
mkos@397 456 }
mkos@397 457 }
ohair@286 458 }
ohair@286 459
ohair@286 460 // else no provider found
ohair@286 461 logger.fine("Trying to create the platform default provider");
ohair@286 462 return newInstance(classes, properties, PLATFORM_DEFAULT_FACTORY_CLASS);
ohair@286 463 }
ohair@286 464
mkos@397 465 private static Class lookupJaxbContextUsingOsgiServiceLoader() {
ohair@286 466 try {
mkos@397 467 // Use reflection to avoid having any dependency on ServiceLoader class
ohair@286 468 Class target = Class.forName("com.sun.org.glassfish.hk2.osgiresourcelocator.ServiceLoader");
ohair@286 469 Method m = target.getMethod("lookupProviderClasses", Class.class);
mkos@397 470 Iterator iter = ((Iterable) m.invoke(null, JAXBContext.class)).iterator();
ohair@286 471 return iter.hasNext() ? (Class)iter.next() : null;
ohair@286 472 } catch(Exception e) {
mkos@397 473 logger.log(Level.FINE, "Unable to find from OSGi: javax.xml.bind.JAXBContext");
ohair@286 474 return null;
ohair@286 475 }
ohair@286 476 }
ohair@286 477
ohair@286 478 private static Properties loadJAXBProperties( ClassLoader classLoader,
ohair@286 479 String propFileName )
ohair@286 480 throws JAXBException {
ohair@286 481
ohair@286 482 Properties props = null;
ohair@286 483
ohair@286 484 try {
ohair@286 485 URL url;
ohair@286 486 if(classLoader==null)
ohair@286 487 url = ClassLoader.getSystemResource(propFileName);
ohair@286 488 else
ohair@286 489 url = classLoader.getResource( propFileName );
ohair@286 490
ohair@286 491 if( url != null ) {
ohair@286 492 logger.log(Level.FINE, "loading props from {0}", url);
ohair@286 493 props = new Properties();
ohair@286 494 InputStream is = url.openStream();
ohair@286 495 props.load( is );
ohair@286 496 is.close();
ohair@286 497 }
ohair@286 498 } catch( IOException ioe ) {
ohair@286 499 logger.log(Level.FINE,"Unable to load "+propFileName,ioe);
ohair@286 500 throw new JAXBException( ioe.toString(), ioe );
ohair@286 501 }
ohair@286 502
ohair@286 503 return props;
ohair@286 504 }
ohair@286 505
ohair@286 506
ohair@286 507 /**
ohair@286 508 * Search the given ClassLoader for an instance of the specified class and
ohair@286 509 * return a string representation of the URL that points to the resource.
ohair@286 510 *
ohair@286 511 * @param clazz
ohair@286 512 * The class to search for
ohair@286 513 * @param loader
ohair@286 514 * The ClassLoader to search. If this parameter is null, then the
ohair@286 515 * system class loader will be searched
ohair@286 516 * @return
ohair@286 517 * the URL for the class or null if it wasn't found
ohair@286 518 */
ohair@286 519 static URL which(Class clazz, ClassLoader loader) {
ohair@286 520
ohair@286 521 String classnameAsResource = clazz.getName().replace('.', '/') + ".class";
ohair@286 522
ohair@286 523 if(loader == null) {
alanb@368 524 loader = getSystemClassLoader();
ohair@286 525 }
ohair@286 526
ohair@286 527 return loader.getResource(classnameAsResource);
ohair@286 528 }
ohair@286 529
ohair@286 530 /**
ohair@286 531 * Get the URL for the Class from it's ClassLoader.
ohair@286 532 *
ohair@286 533 * Convenience method for {@link #which(Class, ClassLoader)}.
ohair@286 534 *
ohair@286 535 * Equivalent to calling: which(clazz, clazz.getClassLoader())
ohair@286 536 *
ohair@286 537 * @param clazz
ohair@286 538 * The class to search for
ohair@286 539 * @return
ohair@286 540 * the URL for the class or null if it wasn't found
ohair@286 541 */
ohair@286 542 static URL which(Class clazz) {
ohair@286 543 return which(clazz, getClassClassLoader(clazz));
ohair@286 544 }
ohair@286 545
ohair@286 546 /**
ohair@286 547 * When JAXB is in J2SE, rt.jar has to have a JAXB implementation.
ohair@286 548 * However, rt.jar cannot have META-INF/services/javax.xml.bind.JAXBContext
ohair@286 549 * because if it has, it will take precedence over any file that applications have
ohair@286 550 * in their jar files.
ohair@286 551 *
ohair@286 552 * <p>
ohair@286 553 * When the user bundles his own JAXB implementation, we'd like to use it, and we
ohair@286 554 * want the platform default to be used only when there's no other JAXB provider.
ohair@286 555 *
ohair@286 556 * <p>
ohair@286 557 * For this reason, we have to hard-code the class name into the API.
ohair@286 558 */
ohair@286 559 private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";
ohair@286 560
ohair@286 561 /**
ohair@286 562 * Loads the class, provided that the calling thread has an access to the class being loaded.
ohair@286 563 */
ohair@286 564 private static Class safeLoadClass(String className, ClassLoader classLoader) throws ClassNotFoundException {
ohair@286 565 logger.log(Level.FINE, "Trying to load {0}", className);
ohair@286 566 try {
ohair@286 567 // make sure that the current thread has an access to the package of the given name.
ohair@286 568 SecurityManager s = System.getSecurityManager();
ohair@286 569 if (s != null) {
ohair@286 570 int i = className.lastIndexOf('.');
ohair@286 571 if (i != -1) {
ohair@286 572 s.checkPackageAccess(className.substring(0,i));
ohair@286 573 }
ohair@286 574 }
ohair@286 575
ohair@286 576 if (classLoader == null) {
ohair@286 577 return Class.forName(className);
ohair@286 578 } else {
ohair@286 579 return classLoader.loadClass(className);
ohair@286 580 }
ohair@286 581 } catch (SecurityException se) {
ohair@286 582 // anyone can access the platform default factory class without permission
ohair@286 583 if (PLATFORM_DEFAULT_FACTORY_CLASS.equals(className)) {
ohair@286 584 return Class.forName(className);
ohair@286 585 }
ohair@286 586 throw se;
ohair@286 587 }
ohair@286 588 }
ohair@286 589
ohair@286 590 private static ClassLoader getContextClassLoader() {
ohair@286 591 if (System.getSecurityManager() == null) {
ohair@286 592 return Thread.currentThread().getContextClassLoader();
ohair@286 593 } else {
ohair@286 594 return (ClassLoader) java.security.AccessController.doPrivileged(
ohair@286 595 new java.security.PrivilegedAction() {
ohair@286 596 public java.lang.Object run() {
ohair@286 597 return Thread.currentThread().getContextClassLoader();
ohair@286 598 }
ohair@286 599 });
ohair@286 600 }
ohair@286 601 }
ohair@286 602
ohair@286 603 private static ClassLoader getClassClassLoader(final Class c) {
ohair@286 604 if (System.getSecurityManager() == null) {
ohair@286 605 return c.getClassLoader();
ohair@286 606 } else {
ohair@286 607 return (ClassLoader) java.security.AccessController.doPrivileged(
ohair@286 608 new java.security.PrivilegedAction() {
ohair@286 609 public java.lang.Object run() {
ohair@286 610 return c.getClassLoader();
ohair@286 611 }
ohair@286 612 });
ohair@286 613 }
ohair@286 614 }
ohair@286 615
alanb@368 616 private static ClassLoader getSystemClassLoader() {
alanb@368 617 if (System.getSecurityManager() == null) {
alanb@368 618 return ClassLoader.getSystemClassLoader();
alanb@368 619 } else {
alanb@368 620 return (ClassLoader) java.security.AccessController.doPrivileged(
alanb@368 621 new java.security.PrivilegedAction() {
alanb@368 622 public java.lang.Object run() {
alanb@368 623 return ClassLoader.getSystemClassLoader();
alanb@368 624 }
alanb@368 625 });
alanb@368 626 }
alanb@368 627 }
alanb@368 628
ohair@286 629 }

mercurial