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