1 5 6 package javax.xml.bind; 7 8 import java.io.BufferedReader ; 9 import java.io.IOException ; 10 import java.io.InputStream ; 11 import java.io.InputStreamReader ; 12 import java.io.UnsupportedEncodingException ; 13 import java.lang.reflect.InvocationTargetException ; 14 import java.lang.reflect.Method ; 15 import java.net.URL ; 16 import java.util.Map ; 17 import java.util.Properties ; 18 import java.util.StringTokenizer ; 19 import java.util.logging.ConsoleHandler ; 20 import java.util.logging.Level ; 21 import java.util.logging.Logger ; 22 import java.security.AccessController ; 23 import java.security.PrivilegedAction ; 24 25 import static javax.xml.bind.JAXBContext.JAXB_CONTEXT_FACTORY; 26 27 29 39 class ContextFinder { 40 private static final Logger logger; 41 static { 42 logger = Logger.getLogger("javax.xml.bind"); 43 try { 44 if (AccessController.doPrivileged(new GetPropertyAction("jaxb.debug")) != null) { 45 logger.setUseParentHandlers(false); 48 logger.setLevel(Level.ALL); 49 ConsoleHandler handler = new ConsoleHandler (); 50 handler.setLevel(Level.ALL); 51 logger.addHandler(handler); 52 } else { 53 } 57 } catch(Throwable t) { 58 } 61 } 62 63 67 private static void handleInvocationTargetException(InvocationTargetException x) throws JAXBException { 68 Throwable t = x.getTargetException(); 69 if( t != null ) { 70 if( t instanceof JAXBException ) 71 throw (JAXBException)t; 73 if( t instanceof RuntimeException ) 74 throw (RuntimeException )t; 76 if( t instanceof Error ) 77 throw (Error )t; 78 } 79 } 80 81 82 93 private static JAXBException handleClassCastException(Class originalType, Class targetType) { 94 final URL targetTypeURL = which(targetType); 95 96 return new JAXBException(Messages.format(Messages.ILLEGAL_CAST, 97 originalType.getClassLoader().getResource("javax/xml/bind/JAXBContext.class"), 100 targetTypeURL)); 101 } 102 103 106 static JAXBContext newInstance( String contextPath, 107 String className, 108 ClassLoader classLoader, 109 Map properties ) 110 throws JAXBException 111 { 112 try { 113 Class spiClass; 114 if (classLoader == null) { 115 spiClass = Class.forName(className); 116 } else { 117 spiClass = classLoader.loadClass(className); 118 } 119 120 125 126 Object context = null; 127 128 try { 131 Method m = spiClass.getMethod("createContext",String .class,ClassLoader .class,Map .class); 132 context = m.invoke(null,contextPath,classLoader,properties); 134 } catch (NoSuchMethodException e) { 135 } 137 138 if(context==null) { 139 Method m = spiClass.getMethod("createContext",String .class,ClassLoader .class); 142 context = m.invoke(null,contextPath,classLoader); 144 } 145 146 if(!(context instanceof JAXBContext)) { 147 handleClassCastException(context.getClass(), JAXBContext.class); 149 } 150 return (JAXBContext)context; 151 } catch (ClassNotFoundException x) { 152 throw new JAXBException( 153 Messages.format( Messages.PROVIDER_NOT_FOUND, className ), 154 x); 155 } catch (InvocationTargetException x) { 156 handleInvocationTargetException(x); 157 Throwable e = x; 160 if(x.getTargetException()!=null) 161 e = x.getTargetException(); 162 163 throw new JAXBException( Messages.format( Messages.COULD_NOT_INSTANTIATE, className, e ), e ); 164 } catch (RuntimeException x) { 165 throw x; 168 } catch (Exception x) { 169 throw new JAXBException( 174 Messages.format( Messages.COULD_NOT_INSTANTIATE, className, x ), 175 x); 176 } 177 } 178 179 180 183 static JAXBContext newInstance( 184 Class [] classes, 185 Map properties, 186 String className) throws JAXBException { 187 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 188 Class spi; 189 try { 190 logger.fine("Trying to load "+className); 191 if (cl != null) 192 spi = cl.loadClass(className); 193 else 194 spi = Class.forName(className); 195 } catch (ClassNotFoundException e) { 196 throw new JAXBException(e); 197 } 198 199 if(logger.isLoggable(Level.FINE)) { 200 logger.fine("loaded "+className+" from "+which(spi)); 202 } 203 204 Method m; 205 try { 206 m = spi.getMethod("createContext", Class [].class, Map .class); 207 } catch (NoSuchMethodException e) { 208 throw new JAXBException(e); 209 } 210 try { 211 Object context = m.invoke(null, classes, properties); 212 if(!(context instanceof JAXBContext)) { 213 throw handleClassCastException(context.getClass(), JAXBContext.class); 215 } 216 return (JAXBContext)context; 217 } catch (IllegalAccessException e) { 218 throw new JAXBException(e); 219 } catch (InvocationTargetException e) { 220 handleInvocationTargetException(e); 221 222 Throwable x = e; 223 if (e.getTargetException() != null) 224 x = e.getTargetException(); 225 226 throw new JAXBException(x); 227 } 228 } 229 230 231 static JAXBContext find(String factoryId, String contextPath, ClassLoader classLoader, Map properties ) throws JAXBException { 232 233 235 final String jaxbContextFQCN = JAXBContext.class.getName(); 236 237 StringBuilder propFileName; 239 StringTokenizer packages = new StringTokenizer ( contextPath, ":" ); 240 String factoryClassName; 241 242 if(!packages.hasMoreTokens()) 243 throw new JAXBException(Messages.format(Messages.NO_PACKAGE_IN_CONTEXTPATH)); 245 246 247 logger.fine("Searching jaxb.properties"); 248 249 while( packages.hasMoreTokens() ) { 250 String packageName = packages.nextToken(":").replace('.','/'); 251 propFileName = new StringBuilder ().append(packageName).append("/jaxb.properties"); 253 254 Properties props = loadJAXBProperties( classLoader, propFileName.toString() ); 255 if (props != null) { 256 if (props.containsKey(factoryId)) { 257 factoryClassName = props.getProperty(factoryId); 258 return newInstance( contextPath, factoryClassName, classLoader, properties ); 259 } else { 260 throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryId)); 261 } 262 } 263 } 264 265 logger.fine("Searching the system property"); 266 267 factoryClassName = AccessController.doPrivileged(new GetPropertyAction(jaxbContextFQCN)); 269 if( factoryClassName != null ) { 270 return newInstance( contextPath, factoryClassName, classLoader, properties ); 271 } 272 273 logger.fine("Searching META-INF/services"); 274 275 BufferedReader r; 277 try { 278 final StringBuilder resource = new StringBuilder ().append("META-INF/services/").append(jaxbContextFQCN); 279 final InputStream resourceStream = 280 classLoader.getResourceAsStream(resource.toString()); 281 282 if (resourceStream != null) { 283 r = new BufferedReader (new InputStreamReader (resourceStream, "UTF-8")); 284 factoryClassName = r.readLine().trim(); 285 r.close(); 286 return newInstance(contextPath, factoryClassName, classLoader, properties); 287 } else { 288 logger.fine("Unable to load:" + resource.toString()); 289 } 290 } catch (UnsupportedEncodingException e) { 291 throw new JAXBException(e); 293 } catch (IOException e) { 294 throw new JAXBException(e); 295 } 296 297 logger.fine("Trying to create the platform default provider"); 299 return newInstance(contextPath, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties); 300 } 301 302 static JAXBContext find( Class [] classes, Map properties ) throws JAXBException { 304 305 307 final String jaxbContextFQCN = JAXBContext.class.getName(); 308 String factoryClassName; 309 310 for (final Class c : classes) { 312 ClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction <ClassLoader >() { 314 public ClassLoader run() { 315 return c.getClassLoader(); 316 } 317 }); 318 Package pkg = c.getPackage(); 319 if(pkg==null) 320 continue; String packageName = pkg.getName().replace('.', '/'); 322 323 326 329 String resourceName = packageName+"/jaxb.properties"; 331 logger.fine("Trying to locate "+resourceName); 332 Properties props = loadJAXBProperties(classLoader, resourceName); 333 if (props == null) { 334 logger.fine(" not found"); 335 } else { 336 logger.fine(" found"); 337 if (props.containsKey(JAXB_CONTEXT_FACTORY)) { 338 factoryClassName = props.getProperty(JAXB_CONTEXT_FACTORY).trim(); 340 return newInstance(classes, properties, factoryClassName); 341 } else { 342 throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, JAXB_CONTEXT_FACTORY)); 343 } 344 } 345 } 346 347 logger.fine("Checking system property "+jaxbContextFQCN); 349 factoryClassName = AccessController.doPrivileged(new GetPropertyAction(jaxbContextFQCN)); 350 if( factoryClassName != null ) { 351 logger.fine(" found "+factoryClassName); 352 return newInstance( classes, properties, factoryClassName ); 353 } 354 logger.fine(" not found"); 355 356 logger.fine("Checking META-INF/services"); 358 BufferedReader r; 359 try { 360 final String resource = new StringBuilder ("META-INF/services/").append(jaxbContextFQCN).toString(); 361 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 362 URL resourceURL; 363 if(classLoader==null) 364 resourceURL = ClassLoader.getSystemResource(resource); 365 else 366 resourceURL = classLoader.getResource(resource); 367 368 if (resourceURL != null) { 369 logger.fine("Reading "+resourceURL); 370 r = new BufferedReader (new InputStreamReader (resourceURL.openStream(), "UTF-8")); 371 factoryClassName = r.readLine().trim(); 372 return newInstance(classes, properties, factoryClassName); 373 } else { 374 logger.fine("Unable to find: " + resource); 375 } 376 } catch (UnsupportedEncodingException e) { 377 throw new JAXBException(e); 379 } catch (IOException e) { 380 throw new JAXBException(e); 381 } 382 383 logger.fine("Trying to create the platform default provider"); 385 return newInstance(classes, properties, PLATFORM_DEFAULT_FACTORY_CLASS); 386 } 387 388 389 private static Properties loadJAXBProperties( ClassLoader classLoader, 390 String propFileName ) 391 throws JAXBException { 392 393 Properties props = null; 394 395 try { 396 URL url; 397 if(classLoader==null) 398 url = ClassLoader.getSystemResource(propFileName); 399 else 400 url = classLoader.getResource( propFileName ); 401 402 if( url != null ) { 403 logger.fine("loading props from "+url); 404 props = new Properties (); 405 InputStream is = url.openStream(); 406 props.load( is ); 407 is.close(); 408 } 409 } catch( IOException ioe ) { 410 logger.log(Level.FINE,"Unable to load "+propFileName,ioe); 411 throw new JAXBException( ioe.toString(), ioe ); 412 } 413 414 return props; 415 } 416 417 418 430 static URL which(Class clazz, ClassLoader loader) { 431 432 String classnameAsResource = clazz.getName().replace('.', '/') + ".class"; 433 434 if(loader == null) { 435 loader = ClassLoader.getSystemClassLoader(); 436 } 437 438 return loader.getResource(classnameAsResource); 439 } 440 441 453 static URL which(Class clazz) { 454 return which(clazz, clazz.getClassLoader()); 455 } 456 457 470 private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory"; 471 } 472 | Popular Tags |