# HG changeset patch # User mkos # Date 1454069455 -3600 # Node ID 56a695bbebe8a5ed8965db7026ef180a6a53309f # Parent c159d1130ec7a6f2f0b4c05675a6746e73feba5c 8145104: NPE is thrown when JAXBContextFactory implementation is specified in system property, 8145112: newInstance(String,ClassLoader): java.lang.JAXBException should not be wrapped as expected according to spec Reviewed-by: lancea diff -r c159d1130ec7 -r 56a695bbebe8 jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java --- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java Thu Jan 28 09:43:05 2016 -0800 +++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java Fri Jan 29 13:10:55 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,11 +29,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; @@ -105,9 +106,9 @@ /** * If the {@link InvocationTargetException} wraps an exception that shouldn't be wrapped, - * throw the wrapped exception. + * throw the wrapped exception. Otherwise returns exception to be wrapped for further processing. */ - private static void handleInvocationTargetException(InvocationTargetException x) throws JAXBException { + private static Throwable handleInvocationTargetException(InvocationTargetException x) throws JAXBException { Throwable t = x.getTargetException(); if (t != null) { if (t instanceof JAXBException) @@ -118,7 +119,9 @@ throw (RuntimeException) t; if (t instanceof Error) throw (Error) t; + return t; } + return x; } @@ -157,9 +160,10 @@ } catch (ClassNotFoundException x) { throw new JAXBException(Messages.format(Messages.PROVIDER_NOT_FOUND, className), x); - } catch (RuntimeException x) { + } catch (RuntimeException | JAXBException x) { // avoid wrapping RuntimeException to JAXBException, // because it indicates a bug in this code. + // JAXBException re-thrown as is throw x; } catch (Exception x) { // can't catch JAXBException because the method is hidden behind @@ -189,8 +193,9 @@ try { Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class, Map.class); // any failure in invoking this method would be considered fatal - context = m.invoke(null, contextPath, classLoader, properties); - } catch (NoSuchMethodException e) { + Object obj = instantiateProviderIfNecessary(m); + context = m.invoke(obj, contextPath, classLoader, properties); + } catch (NoSuchMethodException ignored) { // it's not an error for the provider not to have this method. } @@ -198,8 +203,9 @@ // try the old method that doesn't take properties. compatible with 1.0. // it is an error for an implementation not to have both forms of the createContext method. Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class); + Object obj = instantiateProviderIfNecessary(m); // any failure in invoking this method would be considered fatal - context = m.invoke(null, contextPath, classLoader); + context = m.invoke(obj, contextPath, classLoader); } if (!(context instanceof JAXBContext)) { @@ -208,18 +214,11 @@ } return (JAXBContext) context; } catch (InvocationTargetException x) { - handleInvocationTargetException(x); - // for other exceptions, wrap the internal target exception - // with a JAXBException - Throwable e = x; - if (x.getTargetException() != null) - e = x.getTargetException(); + // throw if it is exception not to be wrapped + // otherwise, wrap with a JAXBException + Throwable e = handleInvocationTargetException(x); + throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, spFactory, e), e); - throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, spFactory, e), e); - } catch (RuntimeException x) { - // avoid wrapping RuntimeException to JAXBException, - // because it indicates a bug in this code. - throw x; } catch (Exception x) { // can't catch JAXBException because the method is hidden behind // reflection. Root element collisions detected in the call to @@ -229,6 +228,23 @@ } } + private static Object instantiateProviderIfNecessary(Method m) throws JAXBException { + Class declaringClass = m.getDeclaringClass(); + try { + if (JAXBContextFactory.class.isAssignableFrom(declaringClass)) { + return AccessController.doPrivileged(new PrivilegedExceptionAction() { + @Override + public Object run() throws Exception { + return declaringClass.newInstance(); + } + }); + } + return null; + } catch (PrivilegedActionException e) { + throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, declaringClass, e), e); + } + } + /** * Create an instance of a class using the thread context ClassLoader */ @@ -255,7 +271,8 @@ try { Method m = spFactory.getMethod("createContext", Class[].class, Map.class); - Object context = m.invoke(null, classes, properties); + Object obj = instantiateProviderIfNecessary(m); + Object context = m.invoke(obj, classes, properties); if (!(context instanceof JAXBContext)) { // the cast would fail, so generate an exception with a nice message throw handleClassCastException(context.getClass(), JAXBContext.class); @@ -264,13 +281,10 @@ } catch (NoSuchMethodException | IllegalAccessException e) { throw new JAXBException(e); - } catch (InvocationTargetException e) { - handleInvocationTargetException(e); - - Throwable x = e; - if (e.getTargetException() != null) - x = e.getTargetException(); + // throw if it is exception not to be wrapped + // otherwise, wrap with a JAXBException + Throwable x = handleInvocationTargetException(e); throw new JAXBException(x); }