Save This Page
Home » openejb-3.1.2-src » org.apache » openejb » core » webservices » [javadoc | source]
    1   /**
    2    *
    3    * Licensed to the Apache Software Foundation (ASF) under one or more
    4    * contributor license agreements.  See the NOTICE file distributed with
    5    * this work for additional information regarding copyright ownership.
    6    * The ASF licenses this file to You under the Apache License, Version 2.0
    7    * (the "License"); you may not use this file except in compliance with
    8    * the License.  You may obtain a copy of the License at
    9    *
   10    *     http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    *  Unless required by applicable law or agreed to in writing, software
   13    *  distributed under the License is distributed on an "AS IS" BASIS,
   14    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15    *  See the License for the specific language governing permissions and
   16    *  limitations under the License.
   17    */
   18   package org.apache.openejb.core.webservices;
   19   
   20   import org.apache.openejb.util.Logger;
   21   import org.apache.openejb.util.LogCategory;
   22   import org.w3c.dom.Element;
   23   
   24   import javax.xml.ws.spi.Provider;
   25   import javax.xml.ws.spi.ServiceDelegate;
   26   import javax.xml.ws.Endpoint;
   27   import javax.xml.ws.BindingProvider;
   28   import javax.xml.ws.Dispatch;
   29   import javax.xml.ws.Service;
   30   import javax.xml.ws.WebServiceException;
   31   import javax.xml.ws.EndpointReference;
   32   import javax.xml.ws.WebServiceFeature;
   33   import javax.xml.ws.wsaddressing.W3CEndpointReference;
   34   import javax.xml.ws.soap.SOAPBinding;
   35   import javax.xml.ws.handler.HandlerResolver;
   36   import javax.xml.namespace.QName;
   37   import javax.xml.bind.JAXBContext;
   38   import javax.xml.transform.Source;
   39   import javax.jws.WebService;
   40   import java.net.URL;
   41   import java.util.Iterator;
   42   import java.util.Map;
   43   import java.util.List;
   44   import java.util.Properties;
   45   import java.util.Collections;
   46   import java.util.Enumeration;
   47   import java.util.ArrayList;
   48   import java.util.concurrent.Executor;
   49   import java.io.File;
   50   import java.io.FileInputStream;
   51   import java.io.InputStream;
   52   import java.io.BufferedReader;
   53   import java.io.InputStreamReader;
   54   import java.io.IOException;
   55   import java.io.OutputStream;
   56   import java.io.FileOutputStream;
   57   import java.lang.reflect.Method;
   58   import java.lang.reflect.InvocationTargetException;
   59   
   60   public class ProviderWrapper extends Provider {
   61       public static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_WS, ProviderWrapper.class);
   62   
   63       //
   64       // Magic to get our proider wrapper installed with the PortRefData
   65       //
   66   
   67       private static ThreadLocal<ProviderWrapperData> threadPortRefs = new ThreadLocal<ProviderWrapperData>();
   68   
   69       public static void beforeCreate(List<PortRefData> portRefData) {
   70           // Axis JAXWS api is non compliant and checks system property before classloader
   71           // so we replace system property so this wrapper is selected.  The original value
   72           // is saved into an openejb property so we can load the class in the find method
   73           String oldProperty = System.getProperty(JAXWSPROVIDER_PROPERTY);
   74           if (oldProperty != null && !oldProperty.equals(ProviderWrapper.class.getName())) {
   75               System.setProperty("openejb." + JAXWSPROVIDER_PROPERTY, oldProperty);
   76               System.setProperty(JAXWSPROVIDER_PROPERTY, ProviderWrapper.class.getName());
   77           }
   78   
   79           System.setProperty(JAXWSPROVIDER_PROPERTY, ProviderWrapper.class.getName());
   80           
   81           ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
   82           if (oldClassLoader != null) {
   83               Thread.currentThread().setContextClassLoader(new ProviderClassLoader(oldClassLoader));
   84           } else {
   85               Thread.currentThread().setContextClassLoader(new ProviderClassLoader());
   86           }
   87           threadPortRefs.set(new ProviderWrapperData(portRefData, oldClassLoader));
   88       }
   89   
   90       public static void afterCreate() {
   91           Thread.currentThread().setContextClassLoader(threadPortRefs.get().callerClassLoader);
   92           threadPortRefs.set(null);
   93       }
   94   
   95       private static class ProviderWrapperData {
   96           private final List<PortRefData> portRefData;
   97           private final ClassLoader callerClassLoader;
   98   
   99           public ProviderWrapperData(List<PortRefData> portRefData, ClassLoader callerClassLoader) {
  100               this.portRefData = portRefData;
  101               this.callerClassLoader = callerClassLoader;
  102           }
  103       }
  104   
  105   
  106       //
  107       // Provider wappre implementation
  108       //
  109   
  110       private final Provider delegate;
  111       private final List<PortRefData> portRefs;
  112   
  113       public ProviderWrapper() {
  114           delegate = findProvider();
  115           portRefs = threadPortRefs.get().portRefData;
  116       }
  117   
  118       public Provider getDelegate() {
  119           return delegate;
  120       }
  121   
  122       public ServiceDelegate createServiceDelegate(URL wsdlDocumentLocation, QName serviceName, Class serviceClass) {
  123           ServiceDelegate serviceDelegate = delegate.createServiceDelegate(wsdlDocumentLocation, serviceName, serviceClass);
  124           serviceDelegate = new ServiceDelegateWrapper(serviceDelegate);
  125           return serviceDelegate;
  126       }
  127   
  128       public Endpoint createEndpoint(String bindingId, Object implementor) {
  129           return delegate.createEndpoint(bindingId, implementor);
  130       }
  131   
  132       public Endpoint createAndPublishEndpoint(String address, Object implementor) {
  133           return delegate.createAndPublishEndpoint(address, implementor);
  134       }
  135   
  136       public W3CEndpointReference createW3CEndpointReference(String address,
  137               QName serviceName,
  138               QName portName,
  139               List<Element> metadata,
  140               String wsdlDocumentLocation,
  141               List<Element> referenceParameters) {
  142   
  143           return (W3CEndpointReference) invoke21Delegate(delegate, createW3CEndpointReference,
  144                   address,
  145                   serviceName,
  146                   portName,
  147                   metadata,
  148                   wsdlDocumentLocation,
  149                   referenceParameters);
  150       }
  151   
  152       public EndpointReference readEndpointReference(Source source){
  153           return (EndpointReference) invoke21Delegate(delegate, readEndpointReference, source);
  154       }
  155   
  156       @SuppressWarnings({"unchecked"})
  157       public <T> T getPort(EndpointReference endpointReference, Class<T> serviceEndpointInterface, WebServiceFeature... features) {
  158           return (T) invoke21Delegate(delegate, providerGetPort, endpointReference, serviceEndpointInterface, features);
  159       }
  160   
  161       private class ServiceDelegateWrapper extends ServiceDelegate {
  162           private final ServiceDelegate serviceDelegate;
  163   
  164           public ServiceDelegateWrapper(ServiceDelegate serviceDelegate) {
  165               this.serviceDelegate = serviceDelegate;
  166           }
  167   
  168           public <T> T getPort(QName portName, Class<T> serviceEndpointInterface) {
  169               T t = serviceDelegate.getPort(portName, serviceEndpointInterface);
  170               setProperties((BindingProvider) t, portName);
  171               return t;
  172           }
  173   
  174           public <T> T getPort(Class<T> serviceEndpointInterface) {
  175               T t = serviceDelegate.getPort(serviceEndpointInterface);
  176   
  177               QName qname = null;
  178               if (serviceEndpointInterface.isAnnotationPresent(WebService.class)) {
  179                   WebService webService = serviceEndpointInterface.getAnnotation(WebService.class);
  180                   String targetNamespace = webService.targetNamespace();
  181                   String name = webService.name();
  182                   if (targetNamespace != null && targetNamespace.length() > 0 && name != null && name.length() > 0) {
  183                       qname = new QName(targetNamespace, name);
  184                   }
  185               }
  186   
  187               setProperties((BindingProvider) t, qname);
  188               return t;
  189           }
  190   
  191           public void addPort(QName portName, String bindingId, String endpointAddress) {
  192               serviceDelegate.addPort(portName, bindingId, endpointAddress);
  193           }
  194   
  195           public <T> Dispatch<T> createDispatch(QName portName, Class<T> type, Service.Mode mode) {
  196               Dispatch<T> dispatch = serviceDelegate.createDispatch(portName, type, mode);
  197               setProperties(dispatch, portName);
  198               return dispatch;
  199           }
  200   
  201           public Dispatch<Object> createDispatch(QName portName, JAXBContext context, Service.Mode mode) {
  202               Dispatch<Object> dispatch = serviceDelegate.createDispatch(portName, context, mode);
  203               setProperties(dispatch, portName);
  204               return dispatch;
  205           }
  206   
  207           @SuppressWarnings({"unchecked"})
  208           public <T> Dispatch<T> createDispatch(QName portName, Class<T> type, Service.Mode mode, WebServiceFeature... features) {
  209               return (Dispatch<T>) invoke21Delegate(serviceDelegate, createDispatchInterface,
  210                       portName,
  211                       type,
  212                       mode,
  213                       features);
  214           }
  215   
  216           @SuppressWarnings({"unchecked"})
  217           public Dispatch<java.lang.Object> createDispatch(QName portName, JAXBContext context, Service.Mode mode, WebServiceFeature... features) {
  218               return (Dispatch<Object>) invoke21Delegate(serviceDelegate, createDispatchJaxBContext,
  219                       portName,
  220                       context,
  221                       mode,
  222                       features);
  223           }
  224   
  225           @SuppressWarnings({"unchecked"})
  226           public Dispatch<Object> createDispatch(
  227                   EndpointReference endpointReference,
  228                   JAXBContext context,
  229                   Service.Mode mode,
  230                   WebServiceFeature... features) {
  231               return (Dispatch<Object>) invoke21Delegate(serviceDelegate, createDispatchReferenceJaxB,
  232                       endpointReference,
  233                       context,
  234                       mode,
  235                       features);
  236           }
  237   
  238           @SuppressWarnings({"unchecked"})
  239           public <T> Dispatch<T> createDispatch(EndpointReference endpointReference,
  240                                                  java.lang.Class<T> type,
  241                                                  Service.Mode mode,
  242                                                  WebServiceFeature... features) {
  243               return (Dispatch<T>) invoke21Delegate(serviceDelegate, createDispatchReferenceClass,
  244                       endpointReference,
  245                       type,
  246                       mode,
  247                       features);
  248   
  249           }
  250           @SuppressWarnings({"unchecked"})
  251           public <T> T getPort(QName portName, Class<T> serviceEndpointInterface, WebServiceFeature... features) {
  252               return (T) invoke21Delegate(serviceDelegate, serviceGetPortByQName,
  253                       portName,
  254                       serviceEndpointInterface,
  255                       features);
  256           }
  257   
  258           @SuppressWarnings({"unchecked"})
  259           public <T> T getPort(EndpointReference endpointReference, Class<T> serviceEndpointInterface, WebServiceFeature... features) {
  260               return (T) invoke21Delegate(serviceDelegate, serviceGetPortByEndpointReference,
  261                       endpointReference,
  262                       serviceEndpointInterface,
  263                       features);
  264           }
  265   
  266           @SuppressWarnings({"unchecked"})
  267           public <T> T getPort(Class<T> serviceEndpointInterface, WebServiceFeature... features) {
  268               return (T) invoke21Delegate(serviceDelegate, serviceGetPortByInterface,
  269                       serviceEndpointInterface,
  270                       features);
  271           }
  272   
  273           public QName getServiceName() {
  274               QName qName = serviceDelegate.getServiceName();
  275               return qName;
  276           }
  277   
  278           public Iterator<QName> getPorts() {
  279               Iterator<QName> ports = serviceDelegate.getPorts();
  280               return ports;
  281           }
  282   
  283           public URL getWSDLDocumentLocation() {
  284               URL documentLocation = serviceDelegate.getWSDLDocumentLocation();
  285               return documentLocation;
  286           }
  287   
  288           public HandlerResolver getHandlerResolver() {
  289               HandlerResolver handlerResolver = serviceDelegate.getHandlerResolver();
  290               return handlerResolver;
  291           }
  292   
  293           public void setHandlerResolver(HandlerResolver handlerResolver) {
  294               serviceDelegate.setHandlerResolver(handlerResolver);
  295           }
  296   
  297           public Executor getExecutor() {
  298               Executor executor = serviceDelegate.getExecutor();
  299               return executor;
  300           }
  301   
  302           public void setExecutor(Executor executor) {
  303               serviceDelegate.setExecutor(executor);
  304           }
  305   
  306           private void setProperties(BindingProvider proxy, QName qname) {
  307               for (PortRefData portRef : portRefs) {
  308                   Class intf = null;
  309                   if (portRef.getServiceEndpointInterface() != null) {
  310                       try {
  311                           intf = proxy.getClass().getClassLoader().loadClass(portRef.getServiceEndpointInterface());
  312                       } catch (Exception e) {
  313                       }
  314                   }
  315                   if ((qname != null && qname.equals(portRef.getQName())) || (intf != null && intf.isInstance(proxy))) {
  316                       // set address
  317                       if (!portRef.getAddresses().isEmpty()) {
  318                           proxy.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, portRef.getAddresses().get(0));
  319                       }
  320   
  321                       // set mtom
  322                       boolean enableMTOM = portRef.isEnableMtom();
  323                       if (enableMTOM && proxy.getBinding() instanceof SOAPBinding) {
  324                           ((SOAPBinding)proxy.getBinding()).setMTOMEnabled(enableMTOM);
  325                       }
  326   
  327                       // set properties
  328                       for (Map.Entry<Object, Object> entry : portRef.getProperties().entrySet()) {
  329                           String name = (String) entry.getKey();
  330                           String value = (String) entry.getValue();
  331                           proxy.getRequestContext().put(name, value);
  332                       }
  333   
  334                       return;
  335                   }
  336               }
  337           }
  338       }
  339   
  340       private static Provider findProvider() {
  341           ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  342           if (classLoader == null) classLoader = ClassLoader.getSystemClassLoader();
  343   
  344           // 0. System.getProperty("openejb.javax.xml.ws.spi.Provider")
  345           // This is so those using old axis rules still work as expected
  346           String providerClass = System.getProperty("openejb." + JAXWSPROVIDER_PROPERTY);
  347           Provider provider = createProviderInstance(providerClass, classLoader);
  348           if (provider != null) {
  349               return provider;
  350           }
  351   
  352           // 1. META-INF/services/javax.xml.ws.spi.Provider
  353           try {
  354               for (URL url : Collections.list(classLoader.getResources("META-INF/services/" + JAXWSPROVIDER_PROPERTY))) {
  355                   BufferedReader in = null;
  356                   try {
  357                       in = new BufferedReader(new InputStreamReader(url.openStream()));
  358   
  359                       providerClass = in.readLine();
  360                       provider = createProviderInstance(providerClass, classLoader);
  361                       if (provider != null) {
  362                           return provider;
  363                       }
  364                   } catch (Exception ignored) {
  365                   } finally {
  366                       if (in != null) {
  367                           try {
  368                               in.close();
  369                           } catch (IOException e) {
  370                           }
  371                       }
  372                   }
  373               }
  374           } catch (Exception ingored) {
  375           }
  376   
  377           // 2. $java.home/lib/jaxws.properties
  378           String javaHome = System.getProperty("java.home");
  379           File jaxrpcPropertiesFile = new File(new File(javaHome, "lib"), "jaxrpc.properties");
  380           if (jaxrpcPropertiesFile.exists()) {
  381               InputStream in = null;
  382               try {
  383                   in = new FileInputStream(jaxrpcPropertiesFile);
  384                   Properties properties = new Properties();
  385                   properties.load(in);
  386   
  387                   providerClass = properties.getProperty(JAXWSPROVIDER_PROPERTY);
  388                   provider = createProviderInstance(providerClass, classLoader);
  389                   if (provider != null) {
  390                       return provider;
  391                   }
  392               } catch(Exception ignored) {
  393               } finally {
  394                   if (in != null) {
  395                       try {
  396                           in.close();
  397                       } catch (IOException e) {
  398                       }
  399                   }
  400               }
  401           }
  402   
  403           // 3. System.getProperty("javax.xml.ws.spi.Provider")
  404           providerClass = System.getProperty(JAXWSPROVIDER_PROPERTY);
  405           provider = createProviderInstance(providerClass, classLoader);
  406           if (provider != null) {
  407               return provider;
  408           }
  409   
  410   
  411           // 4. Use javax.xml.ws.spi.Provider default
  412           try {
  413               System.getProperties().remove(JAXWSPROVIDER_PROPERTY);
  414               provider = Provider.provider();
  415               if (provider != null && !provider.getClass().getName().equals(ProviderWrapper.class.getName())) {
  416                   return provider;
  417               }
  418           } finally {
  419               // restore original jax provider property
  420               System.setProperty(JAXWSPROVIDER_PROPERTY, providerClass);
  421           }
  422   
  423           throw new WebServiceException("No " + JAXWSPROVIDER_PROPERTY + " implementation found");
  424       }
  425   
  426       private static Provider createProviderInstance(String providerClass, ClassLoader classLoader) {
  427           if (providerClass != null && providerClass.length() > 0 && !providerClass.equals(ProviderWrapper.class.getName())) {
  428               try {
  429                   Class<? extends Provider> clazz = classLoader.loadClass(providerClass).asSubclass(Provider.class);
  430                   return clazz.newInstance();
  431               } catch (Throwable e) {
  432                   logger.warning("Unable to construct provider implementation " + providerClass, e);
  433               }
  434           }
  435           return null;
  436       }
  437   
  438       private static class ProviderClassLoader extends ClassLoader {
  439           private static final String PROVIDER_RESOURCE = "META-INF/services/" + JAXWSPROVIDER_PROPERTY;
  440           private static final URL PROVIDER_URL;
  441           static {
  442               try {
  443                   File tempFile = File.createTempFile("openejb-jaxws-provider", "tmp");
  444                   tempFile.deleteOnExit();
  445                   OutputStream out = new FileOutputStream(tempFile);
  446                   out.write(ProviderWrapper.class.getName().getBytes());
  447                   out.close();
  448                   PROVIDER_URL = tempFile.toURL();
  449               } catch (IOException e) {
  450                   throw new RuntimeException("Cound not create openejb-jaxws-provider file");
  451               }
  452           }
  453   
  454           public ProviderClassLoader() {
  455           }
  456   
  457           public ProviderClassLoader(ClassLoader parent) {
  458               super(parent);
  459           }
  460   
  461           public Enumeration<URL> getResources(String name) throws IOException {
  462               Enumeration<URL> resources = super.getResources(name);
  463               if (PROVIDER_RESOURCE.equals(name)) {
  464                   ArrayList<URL> list = new ArrayList<URL>();
  465                   list.add(PROVIDER_URL);
  466                   list.addAll(Collections.list(resources));
  467                   resources = Collections.enumeration(list);
  468               }
  469               return resources;
  470           }
  471   
  472   
  473           public URL getResource(String name) {
  474               if (PROVIDER_RESOURCE.equals(name)) {
  475                   return PROVIDER_URL;
  476               }
  477               return super.getResource(name);
  478           }
  479       }
  480   
  481   
  482       //
  483       // Delegate methods for JaxWS 2.1
  484       //
  485   
  486       private static Object invoke21Delegate(Object delegate, Method method, Object... args) {
  487           if (method == null) {
  488               throw new UnsupportedOperationException("JaxWS 2.1 APIs are not supported");
  489           }
  490           try {
  491               return method.invoke(delegate,args);
  492           } catch (IllegalAccessException e) {
  493               throw new WebServiceException(e);
  494           } catch (InvocationTargetException e) {
  495               if (e.getCause() != null) {
  496                   throw new WebServiceException(e.getCause());
  497               }
  498               throw new WebServiceException(e);
  499           }
  500       }
  501   
  502       // Provider methods
  503       private static final Method createW3CEndpointReference;
  504       private static final Method providerGetPort;
  505       private static final Method readEndpointReference;
  506   
  507       // ServiceDelegate methods
  508       private static final Method createDispatchReferenceJaxB;
  509       private static final Method createDispatchReferenceClass;
  510       private static final Method createDispatchInterface;
  511       private static final Method createDispatchJaxBContext;
  512       private static final Method serviceGetPortByEndpointReference;
  513       private static final Method serviceGetPortByQName;
  514       private static final Method serviceGetPortByInterface;
  515   
  516       static {
  517           Method method = null;
  518           try {
  519               method = Provider.class.getMethod("createW3CEndpointReference",
  520                       String.class,
  521                       QName.class,
  522                       QName.class,
  523                       List.class,
  524                       String.class,
  525                       List.class);
  526           } catch (NoSuchMethodException e) {
  527           }
  528           createW3CEndpointReference = method;
  529   
  530           method = null;
  531           try {
  532               method = Provider.class.getMethod("getPort",
  533                       EndpointReference.class,
  534                       Class.class,
  535                       WebServiceFeature[].class);
  536           } catch (NoSuchMethodException e) {
  537           }
  538           providerGetPort = method;
  539   
  540           method = null;
  541           try {
  542               method = Provider.class.getMethod("readEndpointReference", Source.class);
  543           } catch (NoSuchMethodException e) {
  544           }
  545           readEndpointReference = method;
  546   
  547   
  548           method = null;
  549           try {
  550               method = ServiceDelegate.class.getMethod("createDispatch",
  551                       EndpointReference.class,
  552                       JAXBContext.class,
  553                       Service.Mode.class,
  554                       WebServiceFeature[].class);
  555           } catch (NoSuchMethodException e) {
  556           }
  557           createDispatchReferenceJaxB = method;
  558   
  559           method = null;
  560           try {
  561               method = ServiceDelegate.class.getMethod("createDispatch",
  562                       EndpointReference.class,
  563                       Class.class,
  564                       Service.Mode.class,
  565                       WebServiceFeature[].class);
  566           } catch (NoSuchMethodException e) {
  567           }
  568           createDispatchReferenceClass = method;
  569   
  570           method = null;
  571           try {
  572               method = ServiceDelegate.class.getMethod("createDispatch",
  573                       QName.class,
  574                       JAXBContext.class,
  575                       Service.Mode.class,
  576                       WebServiceFeature[].class);
  577           } catch (NoSuchMethodException e) {
  578           }
  579           createDispatchJaxBContext = method;
  580   
  581           method = null;
  582           try {
  583               method = ServiceDelegate.class.getMethod("createDispatch",
  584                       QName.class,
  585                       Class.class,
  586                       Service.Mode.class,
  587                       WebServiceFeature[].class);
  588           } catch (NoSuchMethodException e) {
  589           }
  590           createDispatchInterface = method;
  591   
  592           method = null;
  593           try {
  594               method = ServiceDelegate.class.getMethod("getPort",
  595                       EndpointReference.class,
  596                       Class.class,
  597                       WebServiceFeature[].class);
  598           } catch (NoSuchMethodException e) {
  599           }
  600           serviceGetPortByEndpointReference = method;
  601   
  602           method = null;
  603           try {
  604               method = ServiceDelegate.class.getMethod("getPort",
  605                       QName.class,
  606                       Class.class,
  607                       WebServiceFeature[].class);
  608           } catch (NoSuchMethodException e) {
  609           }
  610           serviceGetPortByQName = method;
  611   
  612           method = null;
  613           try {
  614               method = ServiceDelegate.class.getMethod("getPort",
  615                       Class.class,
  616                       WebServiceFeature[].class);
  617           } catch (NoSuchMethodException e) {
  618           }
  619           serviceGetPortByInterface = method;
  620   
  621       }
  622   }

Save This Page
Home » openejb-3.1.2-src » org.apache » openejb » core » webservices » [javadoc | source]