Author: alessio.soldano(a)jboss.com
Date: 2011-02-20 08:30:05 -0500 (Sun, 20 Feb 2011)
New Revision: 13773
Modified:
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/ProviderImpl.java
Log:
[JBWS-3223] Modify TCCL to ensure it can see the javax.xml.ws.spi.Provider implementation
(as well as the rest of the integration implementation classes)
Modified:
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/ProviderImpl.java
===================================================================
---
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/ProviderImpl.java 2011-02-18
13:48:46 UTC (rev 13772)
+++
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/ProviderImpl.java 2011-02-20
13:30:05 UTC (rev 13773)
@@ -21,7 +21,15 @@
*/
package org.jboss.wsf.stack.cxf.client;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.SecureClassLoader;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
import javax.xml.namespace.QName;
import javax.xml.ws.WebServiceFeature;
@@ -34,8 +42,12 @@
/**
* A custom javax.xml.ws.spi.Provider implementation
- * extending the CXF one while adding few customizations
+ * extending the CXF one while adding few customizations.
*
+ * This also ensures a proper context classloader is set
+ * (required on JBoss AS 7, as the TCCL does not include
+ * implementation classes by default)
+ *
* @author alessio.soldano(a)jboss.com
* @since 27-Aug-2010
*
@@ -46,29 +58,49 @@
protected org.apache.cxf.jaxws.EndpointImpl createEndpointImpl(Bus bus, String
bindingId, Object implementor,
WebServiceFeature... features)
{
- Boolean db = (Boolean)bus.getProperty(Constants.DEPLOYMENT_BUS);
- if (db != null && db)
+ ClassLoader origClassLoader = null;
+ try
{
- Logger.getLogger(ProviderImpl.class).info(
- "Cannot use the bus associated to the current deployment for starting
a new endpoint, creating a new bus...");
- bus = BusFactory.newInstance().createBus();
+ origClassLoader = checkAndFixContextClassLoader();
+ Boolean db = (Boolean)bus.getProperty(Constants.DEPLOYMENT_BUS);
+ if (db != null && db)
+ {
+ Logger.getLogger(ProviderImpl.class).info(
+ "Cannot use the bus associated to the current deployment for
starting a new endpoint, creating a new bus...");
+ bus = BusFactory.newInstance().createBus();
+ }
+ return super.createEndpointImpl(bus, bindingId, implementor, features);
}
- return super.createEndpointImpl(bus, bindingId, implementor, features);
+ finally
+ {
+ if (origClassLoader != null)
+ setContextClassLoader(origClassLoader);
+ }
}
@SuppressWarnings("rawtypes")
@Override
public ServiceDelegate createServiceDelegate(URL url, QName qname, Class cls)
{
- //we override this method to prevent using the default bus when the current
- //thread is not already associated to a bus. In those situations we create
- //a new bus from scratch instead and link that to the thread.
- Bus bus = BusFactory.getThreadDefaultBus(false);
- if (bus == null)
+ ClassLoader origClassLoader = null;
+ try
{
- bus = BusFactory.newInstance().createBus(); //this also set thread local bus
internally as it's not set yet
+ origClassLoader = checkAndFixContextClassLoader();
+ //we override this method to prevent using the default bus when the current
+ //thread is not already associated to a bus. In those situations we create
+ //a new bus from scratch instead and link that to the thread.
+ Bus bus = BusFactory.getThreadDefaultBus(false);
+ if (bus == null)
+ {
+ bus = BusFactory.newInstance().createBus(); //this also set thread local bus
internally as it's not set yet
+ }
+ return new ServiceImpl(bus, url, qname, cls);
}
- return new ServiceImpl(bus, url, qname, cls);
+ finally
+ {
+ if (origClassLoader != null)
+ setContextClassLoader(origClassLoader);
+ }
}
@SuppressWarnings("rawtypes")
@@ -76,14 +108,198 @@
public ServiceDelegate createServiceDelegate(URL wsdlDocumentLocation, QName
serviceName, Class serviceClass,
WebServiceFeature... features)
{
- //we override this method to prevent using the default bus when the current
- //thread is not already associated to a bus. In those situations we create
- //a new bus from scratch instead and link that to the thread.
- Bus bus = BusFactory.getThreadDefaultBus(false);
- if (bus == null)
+ ClassLoader origClassLoader = null;
+ try
{
- bus = BusFactory.newInstance().createBus(); //this also set thread local bus
internally as it's not set yet
+ origClassLoader = checkAndFixContextClassLoader();
+ //we override this method to prevent using the default bus when the current
+ //thread is not already associated to a bus. In those situations we create
+ //a new bus from scratch instead and link that to the thread.
+ Bus bus = BusFactory.getThreadDefaultBus(false);
+ if (bus == null)
+ {
+ bus = BusFactory.newInstance().createBus(); //this also set thread local bus
internally as it's not set yet
+ }
+ return super.createServiceDelegate(wsdlDocumentLocation, serviceName,
serviceClass, features);
}
- return super.createServiceDelegate(wsdlDocumentLocation, serviceName, serviceClass,
features);
+ finally
+ {
+ if (origClassLoader != null)
+ setContextClassLoader(origClassLoader);
+ }
}
+
+ /**
+ * Ensure the current context classloader can load this ProviderImpl class.
+ *
+ * @return The original classloader or null if it's not been changed
+ */
+ private static ClassLoader checkAndFixContextClassLoader()
+ {
+ ClassLoader origClassLoader = getContextClassLoader();
+ try
+ {
+ origClassLoader.loadClass(ProviderImpl.class.getName());
+ }
+ catch (Exception e)
+ {
+ setContextClassLoader(new
DelegateClassLoader(ProviderImpl.class.getClassLoader(), origClassLoader));
+ return origClassLoader;
+ }
+ return null;
+ }
+
+ /**
+ * Get context classloader.
+ *
+ * @return the current context classloader
+ */
+ static ClassLoader getContextClassLoader()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null)
+ {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ else
+ {
+ return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
+ {
+ public ClassLoader run()
+ {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ }
+ }
+
+ /**
+ * Set context classloader.
+ *
+ * @param classLoader the classloader
+ */
+ static void setContextClassLoader(final ClassLoader classLoader)
+ {
+ if (System.getSecurityManager() == null)
+ {
+ Thread.currentThread().setContextClassLoader(classLoader);
+ }
+ else
+ {
+ AccessController.doPrivileged(new PrivilegedAction<Object>()
+ {
+ public Object run()
+ {
+ Thread.currentThread().setContextClassLoader(classLoader);
+ return null;
+ }
+ });
+ }
+ }
+
+ private static final class DelegateClassLoader extends SecureClassLoader
+ {
+ private ClassLoader delegate;
+
+ private ClassLoader parent;
+
+ public DelegateClassLoader(final ClassLoader delegate, final ClassLoader parent)
+ {
+ super(parent);
+ this.delegate = delegate;
+ this.parent = parent;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Class<?> loadClass(final String className) throws
ClassNotFoundException
+ {
+ if (parent != null)
+ {
+ try
+ {
+ return parent.loadClass(className);
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ //NOOP, use delegate
+ }
+ }
+ return delegate.loadClass(className);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public URL getResource(final String name)
+ {
+ URL url = null;
+ if (parent != null)
+ {
+ url = parent.getResource(name);
+ }
+ return (url == null) ? delegate.getResource(name) : url;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Enumeration<URL> getResources(final String name) throws IOException
+ {
+ final ArrayList<Enumeration<URL>> foundResources = new
ArrayList<Enumeration<URL>>();
+
+ foundResources.add(delegate.getResources(name));
+ foundResources.add(parent.getResources(name));
+
+ return new Enumeration<URL>()
+ {
+ private int position = foundResources.size() - 1;
+
+ public boolean hasMoreElements()
+ {
+ while (position >= 0)
+ {
+ if (foundResources.get(position).hasMoreElements())
+ {
+ return true;
+ }
+ position--;
+ }
+ return false;
+ }
+
+ public URL nextElement()
+ {
+ while (position >= 0)
+ {
+ try
+ {
+ return (foundResources.get(position)).nextElement();
+ }
+ catch (NoSuchElementException e)
+ {
+ }
+ position--;
+ }
+ throw new NoSuchElementException();
+ }
+ };
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public InputStream getResourceAsStream(final String name)
+ {
+ URL foundResource = getResource(name);
+ if (foundResource != null)
+ {
+ try
+ {
+ return foundResource.openStream();
+ }
+ catch (IOException e)
+ {
+ }
+ }
+ return null;
+ }
+ };
}
Show replies by date