1/*
2 * Copyright (c) 2003, 2017, 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
26package javax.xml.bind;
27
28import java.io.BufferedReader;
29import java.io.IOException;
30import java.io.InputStream;
31import java.io.InputStreamReader;
32import java.lang.reflect.InvocationTargetException;
33import java.lang.reflect.Method;
34import java.net.URL;
35import java.security.AccessController;
36import java.security.PrivilegedActionException;
37import java.security.PrivilegedExceptionAction;
38import java.util.Map;
39import java.util.Properties;
40import java.util.StringTokenizer;
41import java.util.logging.ConsoleHandler;
42import java.util.logging.Level;
43import java.util.logging.Logger;
44
45
46/**
47 * This class is package private and therefore is not exposed as part of the
48 * JAXB API.
49 *
50 * This code is designed to implement the JAXB 1.0 spec pluggability feature
51 *
52 * @author <ul><li>Ryan Shoemaker, Sun Microsystems, Inc.</li></ul>
53 * @see JAXBContext
54 */
55class ContextFinder {
56
57    /**
58     * When JAXB is in J2SE, rt.jar has to have a JAXB implementation.
59     * However, rt.jar cannot have META-INF/services/javax.xml.bind.JAXBContext
60     * because if it has, it will take precedence over any file that applications have
61     * in their jar files.
62     *
63     * <p>
64     * When the user bundles his own JAXB implementation, we'd like to use it, and we
65     * want the platform default to be used only when there's no other JAXB provider.
66     *
67     * <p>
68     * For this reason, we have to hard-code the class name into the API.
69     */
70    private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";
71
72    // previous value of JAXBContext.JAXB_CONTEXT_FACTORY, using also this to ensure backwards compatibility
73    private static final String JAXB_CONTEXT_FACTORY_DEPRECATED = "javax.xml.bind.context.factory";
74
75    private static final Logger logger;
76
77    static {
78        logger = Logger.getLogger("javax.xml.bind");
79        try {
80            if (AccessController.doPrivileged(new GetPropertyAction("jaxb.debug")) != null) {
81                // disconnect the logger from a bigger framework (if any)
82                // and take the matters into our own hands
83                logger.setUseParentHandlers(false);
84                logger.setLevel(Level.ALL);
85                ConsoleHandler handler = new ConsoleHandler();
86                handler.setLevel(Level.ALL);
87                logger.addHandler(handler);
88            } else {
89                // don't change the setting of this logger
90                // to honor what other frameworks
91                // have done on configurations.
92            }
93        } catch (Throwable t) {
94            // just to be extra safe. in particular System.getProperty may throw
95            // SecurityException.
96        }
97    }
98
99    private static ServiceLoaderUtil.ExceptionHandler<JAXBException> EXCEPTION_HANDLER =
100            new ServiceLoaderUtil.ExceptionHandler<JAXBException>() {
101                @Override
102                public JAXBException createException(Throwable throwable, String message) {
103                    return new JAXBException(message, throwable);
104                }
105            };
106
107    /**
108     * If the {@link InvocationTargetException} wraps an exception that shouldn't be wrapped,
109     * throw the wrapped exception. Otherwise returns exception to be wrapped for further processing.
110     */
111    private static Throwable handleInvocationTargetException(InvocationTargetException x) throws JAXBException {
112        Throwable t = x.getTargetException();
113        if (t != null) {
114            if (t instanceof JAXBException)
115                // one of our exceptions, just re-throw
116                throw (JAXBException) t;
117            if (t instanceof RuntimeException)
118                // avoid wrapping exceptions unnecessarily
119                throw (RuntimeException) t;
120            if (t instanceof Error)
121                throw (Error) t;
122            return t;
123        }
124        return x;
125    }
126
127
128    /**
129     * Determine if two types (JAXBContext in this case) will generate a ClassCastException.
130     *
131     * For example, (targetType)originalType
132     *
133     * @param originalType
134     *          The Class object of the type being cast
135     * @param targetType
136     *          The Class object of the type that is being cast to
137     * @return JAXBException to be thrown.
138     */
139    private static JAXBException handleClassCastException(Class originalType, Class targetType) {
140        final URL targetTypeURL = which(targetType);
141
142        return new JAXBException(Messages.format(Messages.ILLEGAL_CAST,
143                // we don't care where the impl class is, we want to know where JAXBContext lives in the impl
144                // class' ClassLoader
145                getClassClassLoader(originalType).getResource("javax/xml/bind/JAXBContext.class"),
146                targetTypeURL));
147    }
148
149    /**
150     * Create an instance of a class using the specified ClassLoader
151     */
152    static JAXBContext newInstance(String contextPath,
153                                   Class[] contextPathClasses,
154                                   String className,
155                                   ClassLoader classLoader,
156                                   Map properties) throws JAXBException {
157
158        try {
159            Class spFactory = ServiceLoaderUtil.safeLoadClass(className, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader);
160            return newInstance(contextPath, contextPathClasses, spFactory, classLoader, properties);
161        } catch (ClassNotFoundException x) {
162            throw new JAXBException(Messages.format(Messages.DEFAULT_PROVIDER_NOT_FOUND), x);
163
164        } catch (RuntimeException | JAXBException x) {
165            // avoid wrapping RuntimeException to JAXBException,
166            // because it indicates a bug in this code.
167            // JAXBException re-thrown as is
168            throw x;
169        } catch (Exception x) {
170            // can't catch JAXBException because the method is hidden behind
171            // reflection.  Root element collisions detected in the call to
172            // createContext() are reported as JAXBExceptions - just re-throw it
173            // some other type of exception - just wrap it
174            throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, className, x), x);
175        }
176    }
177
178    static JAXBContext newInstance(String contextPath,
179                                   Class[] contextPathClasses,
180                                   Class spFactory,
181                                   ClassLoader classLoader,
182                                   Map properties) throws JAXBException {
183
184        try {
185            /*
186             * javax.xml.bind.context.factory points to a class which has a
187             * static method called 'createContext' that
188             * returns a javax.xml.JAXBContext.
189             */
190
191            Object context = null;
192
193            // first check the method that takes Map as the third parameter.
194            // this is added in 2.0.
195            try {
196                Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class, Map.class);
197                // any failure in invoking this method would be considered fatal
198                Object obj = instantiateProviderIfNecessary(spFactory);
199                context = m.invoke(obj, contextPath, classLoader, properties);
200            } catch (NoSuchMethodException ignored) {
201                // it's not an error for the provider not to have this method.
202            }
203
204            if (context == null) {
205                // try the old method that doesn't take properties. compatible with 1.0.
206                // it is an error for an implementation not to have both forms of the createContext method.
207                Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class);
208                Object obj = instantiateProviderIfNecessary(spFactory);
209                // any failure in invoking this method would be considered fatal
210                context = m.invoke(obj, contextPath, classLoader);
211            }
212
213            if (!(context instanceof JAXBContext)) {
214                // the cast would fail, so generate an exception with a nice message
215                throw handleClassCastException(context.getClass(), JAXBContext.class);
216            }
217
218            ModuleUtil.delegateAddOpensToImplModule(contextPathClasses, spFactory);
219
220            return (JAXBContext) context;
221        } catch (InvocationTargetException x) {
222            // throw if it is exception not to be wrapped
223            // otherwise, wrap with a JAXBException
224            Throwable e = handleInvocationTargetException(x);
225            throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, spFactory, e), e);
226
227        } catch (Exception x) {
228            // can't catch JAXBException because the method is hidden behind
229            // reflection.  Root element collisions detected in the call to
230            // createContext() are reported as JAXBExceptions - just re-throw it
231            // some other type of exception - just wrap it
232            throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, spFactory, x), x);
233        }
234    }
235
236    private static Object instantiateProviderIfNecessary(final Class<?> implClass) throws JAXBException {
237        try {
238            if (JAXBContextFactory.class.isAssignableFrom(implClass)) {
239                return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
240                    @Override
241                    public Object run() throws Exception {
242                        return implClass.newInstance();
243                    }
244                });
245            }
246            return null;
247        } catch (PrivilegedActionException x) {
248            Throwable e = (x.getCause() == null) ? x : x.getCause();
249            throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, implClass, e), e);
250        }
251    }
252
253    /**
254     * Create an instance of a class using the thread context ClassLoader
255     */
256    static JAXBContext newInstance(Class[] classes, Map properties, String className) throws JAXBException {
257
258        Class spi;
259        try {
260            spi = ServiceLoaderUtil.safeLoadClass(className, PLATFORM_DEFAULT_FACTORY_CLASS, getContextClassLoader());
261        } catch (ClassNotFoundException e) {
262            throw new JAXBException(Messages.format(Messages.DEFAULT_PROVIDER_NOT_FOUND), e);
263        }
264
265        if (logger.isLoggable(Level.FINE)) {
266            // extra check to avoid costly which operation if not logged
267            logger.log(Level.FINE, "loaded {0} from {1}", new Object[]{className, which(spi)});
268        }
269
270        return newInstance(classes, properties, spi);
271    }
272
273    static JAXBContext newInstance(Class[] classes,
274                                   Map properties,
275                                   Class spFactory) throws JAXBException {
276        try {
277
278            Method m = spFactory.getMethod("createContext", Class[].class, Map.class);
279            Object obj = instantiateProviderIfNecessary(spFactory);
280            Object context = m.invoke(obj, classes, properties);
281            if (!(context instanceof JAXBContext)) {
282                // the cast would fail, so generate an exception with a nice message
283                throw handleClassCastException(context.getClass(), JAXBContext.class);
284            }
285            ModuleUtil.delegateAddOpensToImplModule(classes,  spFactory);
286            return (JAXBContext) context;
287
288        } catch (NoSuchMethodException | IllegalAccessException e) {
289            throw new JAXBException(e);
290        } catch (InvocationTargetException e) {
291            // throw if it is exception not to be wrapped
292            // otherwise, wrap with a JAXBException
293            Throwable x = handleInvocationTargetException(e);
294
295            throw new JAXBException(x);
296        }
297    }
298
299    static JAXBContext find(String factoryId,
300                            String contextPath,
301                            ClassLoader classLoader,
302                            Map properties) throws JAXBException {
303
304        if (contextPath == null || contextPath.isEmpty()) {
305            // no context is specified
306            throw new JAXBException(Messages.format(Messages.NO_PACKAGE_IN_CONTEXTPATH));
307        }
308
309        //ModuleUtil is mr-jar class, scans context path for jaxb classes on jdk9 and higher
310        Class[] contextPathClasses = ModuleUtil.getClassesFromContextPath(contextPath, classLoader);
311
312        //first try with classloader#getResource
313        String factoryClassName = jaxbProperties(contextPath, classLoader, factoryId);
314        if (factoryClassName == null && contextPathClasses != null) {
315            //try with class#getResource
316            factoryClassName = jaxbProperties(contextPathClasses, factoryId);
317        }
318
319        if (factoryClassName != null) {
320            return newInstance(contextPath, contextPathClasses, factoryClassName, classLoader, properties);
321        }
322
323
324        String factoryName = classNameFromSystemProperties();
325        if (factoryName != null) return newInstance(contextPath, contextPathClasses, factoryName, classLoader, properties);
326
327        JAXBContextFactory obj = ServiceLoaderUtil.firstByServiceLoader(
328                JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
329
330        if (obj != null) {
331            JAXBContext context = obj.createContext(contextPath, classLoader, properties);
332            ModuleUtil.delegateAddOpensToImplModule(contextPathClasses, obj.getClass());
333            return context;
334        }
335
336        // to ensure backwards compatibility
337        factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader);
338        if (factoryName != null) return newInstance(contextPath, contextPathClasses, factoryName, classLoader, properties);
339
340        Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader(
341                "javax.xml.bind.JAXBContext", logger);
342
343        if (ctxFactory != null) {
344            return newInstance(contextPath, contextPathClasses, ctxFactory, classLoader, properties);
345        }
346
347        // else no provider found
348        logger.fine("Trying to create the platform default provider");
349        return newInstance(contextPath, contextPathClasses, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties);
350    }
351
352    static JAXBContext find(Class<?>[] classes, Map<String, ?> properties) throws JAXBException {
353
354        // search for jaxb.properties in the class loader of each class first
355        logger.fine("Searching jaxb.properties");
356        for (final Class c : classes) {
357            // this classloader is used only to load jaxb.properties, so doing this should be safe.
358            // this is possible for primitives, arrays, and classes that are
359            // loaded by poorly implemented ClassLoaders
360            if (c.getPackage() == null) continue;
361
362            // TODO: do we want to optimize away searching the same package?  org.Foo, org.Bar, com.Baz
363            // classes from the same package might come from different class loades, so it might be a bad idea
364            // TODO: it's easier to look things up from the class
365            // c.getResourceAsStream("jaxb.properties");
366
367            URL jaxbPropertiesUrl = getResourceUrl(c, "jaxb.properties");
368
369            if (jaxbPropertiesUrl != null) {
370
371                String factoryClassName =
372                        classNameFromPackageProperties(
373                                jaxbPropertiesUrl,
374                                JAXBContext.JAXB_CONTEXT_FACTORY, JAXB_CONTEXT_FACTORY_DEPRECATED);
375
376                return newInstance(classes, properties, factoryClassName);
377            }
378
379        }
380
381        String factoryClassName = classNameFromSystemProperties();
382        if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
383
384        JAXBContextFactory factory =
385                ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
386
387        if (factory != null) {
388            JAXBContext context = factory.createContext(classes, properties);
389            ModuleUtil.delegateAddOpensToImplModule(classes, factory.getClass());
390            return context;
391        }
392
393        // to ensure backwards compatibility
394        String className = firstByServiceLoaderDeprecated(JAXBContext.class, getContextClassLoader());
395        if (className != null) return newInstance(classes, properties, className);
396
397        logger.fine("Trying to create the platform default provider");
398        Class ctxFactoryClass =
399                (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
400
401        if (ctxFactoryClass != null) {
402            return newInstance(classes, properties, ctxFactoryClass);
403        }
404
405        // else no provider found
406        logger.fine("Trying to create the platform default provider");
407        return newInstance(classes, properties, PLATFORM_DEFAULT_FACTORY_CLASS);
408    }
409
410
411    /**
412     * first factoryId should be the preferred one,
413     * more of those can be provided to support backwards compatibility
414     */
415    private static String classNameFromPackageProperties(URL packagePropertiesUrl,
416                                                         String ... factoryIds) throws JAXBException {
417
418        logger.log(Level.FINE, "Trying to locate {0}", packagePropertiesUrl.toString());
419        Properties props = loadJAXBProperties(packagePropertiesUrl);
420        for(String factoryId : factoryIds) {
421            if (props.containsKey(factoryId)) {
422                return props.getProperty(factoryId);
423            }
424        }
425        //Factory key not found
426        String propertiesUrl = packagePropertiesUrl.toExternalForm();
427        String packageName = propertiesUrl.substring(0, propertiesUrl.indexOf("/jaxb.properties"));
428        throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryIds[0]));
429    }
430
431    private static String classNameFromSystemProperties() throws JAXBException {
432
433        String factoryClassName = getSystemProperty(JAXBContext.JAXB_CONTEXT_FACTORY);
434        if (factoryClassName != null) {
435            return factoryClassName;
436        }
437        // leave this here to assure compatibility
438        factoryClassName = getDeprecatedSystemProperty(JAXB_CONTEXT_FACTORY_DEPRECATED);
439        if (factoryClassName != null) {
440            return factoryClassName;
441        }
442        // leave this here to assure compatibility
443        factoryClassName = getDeprecatedSystemProperty(JAXBContext.class.getName());
444        if (factoryClassName != null) {
445            return factoryClassName;
446        }
447        return null;
448    }
449
450    private static String getDeprecatedSystemProperty(String property) {
451        String value = getSystemProperty(property);
452        if (value != null) {
453            logger.log(Level.WARNING, "Using non-standard property: {0}. Property {1} should be used instead.",
454                    new Object[] {property, JAXBContext.JAXB_CONTEXT_FACTORY});
455        }
456        return value;
457    }
458
459    private static String getSystemProperty(String property) {
460        logger.log(Level.FINE, "Checking system property {0}", property);
461        String value = AccessController.doPrivileged(new GetPropertyAction(property));
462        if (value != null) {
463            logger.log(Level.FINE, "  found {0}", value);
464        } else {
465            logger.log(Level.FINE, "  not found");
466        }
467        return value;
468    }
469
470    private static Properties loadJAXBProperties(URL url) throws JAXBException {
471
472        try {
473            Properties props;
474            logger.log(Level.FINE, "loading props from {0}", url);
475            props = new Properties();
476            InputStream is = url.openStream();
477            props.load(is);
478            is.close();
479            return props;
480        } catch (IOException ioe) {
481            logger.log(Level.FINE, "Unable to load " + url.toString(), ioe);
482            throw new JAXBException(ioe.toString(), ioe);
483        }
484    }
485
486    /**
487     * If run on JPMS package containing resource must be open unconditionally.
488     *
489     * @param classLoader classloader to load resource with
490     * @param resourceName qualified name of the resource
491     * @return resource url if found
492     */
493    private static URL getResourceUrl(ClassLoader classLoader, String resourceName) {
494        URL url;
495        if (classLoader == null)
496            url = ClassLoader.getSystemResource(resourceName);
497        else
498            url = classLoader.getResource(resourceName);
499        return url;
500    }
501
502    private static URL getResourceUrl(Class<?> clazz, String resourceName) {
503        return clazz.getResource(resourceName);
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    @SuppressWarnings("unchecked")
547    private static ClassLoader getContextClassLoader() {
548        if (System.getSecurityManager() == null) {
549            return Thread.currentThread().getContextClassLoader();
550        } else {
551            return (ClassLoader) java.security.AccessController.doPrivileged(
552                    new java.security.PrivilegedAction() {
553                        @Override
554                        public java.lang.Object run() {
555                            return Thread.currentThread().getContextClassLoader();
556                        }
557                    });
558        }
559    }
560
561    @SuppressWarnings("unchecked")
562    private static ClassLoader getClassClassLoader(final Class c) {
563        if (System.getSecurityManager() == null) {
564            return c.getClassLoader();
565        } else {
566            return (ClassLoader) java.security.AccessController.doPrivileged(
567                    new java.security.PrivilegedAction() {
568                        @Override
569                        public java.lang.Object run() {
570                            return c.getClassLoader();
571                        }
572                    });
573        }
574    }
575
576    private static ClassLoader getSystemClassLoader() {
577        if (System.getSecurityManager() == null) {
578            return ClassLoader.getSystemClassLoader();
579        } else {
580            return (ClassLoader) java.security.AccessController.doPrivileged(
581                    new java.security.PrivilegedAction() {
582                        @Override
583                        public java.lang.Object run() {
584                            return ClassLoader.getSystemClassLoader();
585                        }
586                    });
587        }
588    }
589
590    // ServiceLoaderUtil.firstByServiceLoaderDeprecated should be used instead.
591    @Deprecated
592    static String firstByServiceLoaderDeprecated(Class spiClass,
593                                                 ClassLoader classLoader) throws JAXBException {
594
595        final String jaxbContextFQCN = spiClass.getName();
596
597        logger.fine("Searching META-INF/services");
598
599        // search META-INF services next
600        BufferedReader r = null;
601        final String resource = "META-INF/services/" + jaxbContextFQCN;
602        try {
603            final InputStream resourceStream =
604                    (classLoader == null) ?
605                            ClassLoader.getSystemResourceAsStream(resource) :
606                            classLoader.getResourceAsStream(resource);
607
608            if (resourceStream != null) {
609                r = new BufferedReader(new InputStreamReader(resourceStream, "UTF-8"));
610                String factoryClassName = r.readLine();
611                if (factoryClassName != null) {
612                    factoryClassName = factoryClassName.trim();
613                }
614                r.close();
615                logger.log(Level.FINE, "Configured factorty class:{0}", factoryClassName);
616                return factoryClassName;
617            } else {
618                logger.log(Level.FINE, "Unable to load:{0}", resource);
619                return null;
620            }
621        } catch (IOException e) {
622            throw new JAXBException(e);
623        } finally {
624            try {
625                if (r != null) {
626                    r.close();
627                }
628            } catch (IOException ex) {
629                logger.log(Level.SEVERE, "Unable to close resource: " + resource, ex);
630            }
631        }
632    }
633
634    private static String jaxbProperties(String contextPath, ClassLoader classLoader, String factoryId) throws JAXBException {
635        String[] packages = contextPath.split(":");
636
637        for (String pkg : packages) {
638            String pkgUrl = pkg.replace('.', '/');
639            URL jaxbPropertiesUrl = getResourceUrl(classLoader, pkgUrl + "/jaxb.properties");
640            if (jaxbPropertiesUrl != null) {
641                return classNameFromPackageProperties(jaxbPropertiesUrl,
642                                                      factoryId, JAXB_CONTEXT_FACTORY_DEPRECATED);
643            }
644        }
645        return null;
646    }
647
648    private static String jaxbProperties(Class[] classesFromContextPath, String factoryId) throws JAXBException {
649        for (Class c : classesFromContextPath) {
650            URL jaxbPropertiesUrl = getResourceUrl(c, "jaxb.properties");
651            if (jaxbPropertiesUrl != null) {
652                return classNameFromPackageProperties(jaxbPropertiesUrl, factoryId, JAXB_CONTEXT_FACTORY_DEPRECATED);
653            }
654        }
655        return null;
656    }
657
658}
659