Package org.glassfish.webservices

Source Code of org.glassfish.webservices.WebServiceReferenceManagerImpl

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2009-2011 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package org.glassfish.webservices;

import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.annotations.Scoped;
import org.jvnet.hk2.component.Singleton;
import com.sun.enterprise.container.common.spi.WebServiceReferenceManager;
import com.sun.enterprise.deployment.ServiceReferenceDescriptor;
import com.sun.enterprise.deployment.InjectionTarget;
import com.sun.enterprise.deployment.ServiceRefPortInfo;
import com.sun.enterprise.deployment.WebServiceEndpoint;
import com.sun.logging.LogDomains;
import com.sun.xml.ws.api.FeatureConstructor;
import com.sun.xml.ws.resources.ModelerMessages;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.InitialContext;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceFactory;
import javax.xml.ws.soap.MTOMFeature;
import javax.xml.ws.soap.AddressingFeature;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.RespectBindingFeature;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.spi.WebServiceFeatureAnnotation;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
import java.lang.annotation.Annotation;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.security.PrivilegedActionException;
import java.net.URL;
import java.io.File;


/**
* This class acts as a service to resolve the
* </code>javax.xml.ws.WebServiceRef</code> references
* and also <code>javax.xml.ws.WebServiceContext</code>
* Whenever a lookup is done from GlassfishNamingManagerImpl
* these methods are invoked to resolve the references
*
* @author Bhakti Mehta
*/

@Service
public class WebServiceReferenceManagerImpl implements WebServiceReferenceManager {

    protected Logger logger = LogDomains.getLogger(this.getClass(),LogDomains.WEBSERVICES_LOGGER);



    public Object getWSContextObject() {
        return new WebServiceContextImpl();
    }

    public Object resolveWSReference(ServiceReferenceDescriptor desc, Context context)
            throws NamingException {


        //Taken from NamingManagerImpl.getClientServiceObject
        Class serviceInterfaceClass = null;
        Object returnObj = null;
        WsUtil wsUtil = new WsUtil();

        //Implementation for new lookup element in WebserviceRef
        InitialContext iContext = new InitialContext();
        if( desc.hasLookupName()) {
            return iContext.lookup(desc.getLookupName());

        }

        try {

            WSContainerResolver.set(desc);

            ClassLoader cl = Thread.currentThread().getContextClassLoader();

            serviceInterfaceClass = cl.loadClass(desc.getServiceInterface());

            resolvePortComponentLinks(desc);

            javax.xml.rpc.Service serviceDelegate = null;
            javax.xml.ws.Service jaxwsDelegate = null;
            Object injValue = null;

            if( desc.hasGeneratedServiceInterface() || desc.hasWsdlFile() ) {

                String serviceImplName  = desc.getServiceImplClassName();
                if(serviceImplName != null) {
                    Class serviceImplClass  = cl.loadClass(serviceImplName);
                    serviceDelegate = (javax.xml.rpc.Service) serviceImplClass.newInstance();
                } else {

                    // The target is probably a post JAXRPC-1.1- based service;
                    // If Service Interface class is set, check if it is indeed a subclass of Service
                    // initiateInstance should not be called if the user has given javax.xml.ws.Service itself
                    // as the interface through DD
                    if(javax.xml.ws.Service.class.isAssignableFrom(serviceInterfaceClass) &&
                            !javax.xml.ws.Service.class.equals(serviceInterfaceClass) ) {
                        // OK - the interface class is indeed the generated service class; get an instance
                        injValue = initiateInstance(serviceInterfaceClass, desc);
                    } else {
                        // First try failed; Try to get the Service class type from injected field name
                        // and from there try to get an instance of the service class

                        // I assume the at all inejction target are expecting the SAME service
                        // interface, therefore I take the first one.
                        if (desc.isInjectable()) {

                            InjectionTarget target = desc.getInjectionTargets().iterator().next();
                            Class serviceType = null;
                            if (target.isFieldInjectable()) {
                                java.lang.reflect.Field f = target.getField();
                                if(f == null) {
                                    String fName = target.getFieldName();
                                    Class targetClass = cl.loadClass(target.getClassName());
                                    try {
                                        f = targetClass.getDeclaredField(target.getFieldName());
                                    } catch(java.lang.NoSuchFieldException nsfe) {}// ignoring exception
                                }
                                serviceType = f.getType();
                            }
                            if (target.isMethodInjectable()) {
                                Method m = target.getMethod();
                                if(m == null) {
                                    String mName = target.getMethodName();
                                    Class targetClass = cl.loadClass(target.getClassName());
                                    try {
                                        m = targetClass.getDeclaredMethod(target.getMethodName());
                                    } catch(java.lang.NoSuchMethodException nsfe) {}// ignoring exception
                                }
                                if (m.getParameterTypes().length==1) {
                                    serviceType = m.getParameterTypes()[0];
                                }
                            }
                            if (serviceType!=null){
                                Class loadedSvcClass = cl.loadClass(serviceType.getCanonicalName());
                                injValue = initiateInstance(loadedSvcClass, desc);
                            }
                        }
                    }
                    // Unable to get hold of generated service class -> try the Service.create avenue to get a Service
                    if(injValue == null) {
                        // Here create the service with WSDL (overridden wsdl if wsdl-override is present)
                        // so that JAXWS runtime uses this wsdl @ runtime
                        javax.xml.ws.Service svc =
                                javax.xml.ws.Service.create((new WsUtil()).privilegedGetServiceRefWsdl(desc),
                                        desc.getServiceName());
                        jaxwsDelegate = new JAXWSServiceDelegate(desc, svc, cl);
                    }
                }

                if( desc.hasHandlers() ) {
                    // We need the service's ports to configure the
                    // handler chain (since service-ref handler chain can
                    // optionally specify handler-port association)
                    // so create a configured service and call getPorts

                    javax.xml.rpc.Service configuredService =
                            wsUtil.createConfiguredService(desc);
                    Iterator ports = configuredService.getPorts();
                    wsUtil.configureHandlerChain
                            (desc, serviceDelegate, ports, cl);
                }

                // check if this is a post 1.1 web service
                if(javax.xml.ws.Service.class.isAssignableFrom(serviceInterfaceClass)) {
                    // This is a JAXWS based webservice client;
                    // process handlers and mtom setting
                    // moved test for handlers into wsUtil, in case
                    // we have to add system handler

                    javax.xml.ws.Service service =
                            (injValue != null ?
                                    (javax.xml.ws.Service) injValue : jaxwsDelegate);

                    if (service != null) {
                        // Now configure client side handlers
                        wsUtil.configureJAXWSClientHandlers(service, desc);
                    }
                    // the requested resource is not the service but one of its port.
                    if (injValue!=null && desc.getInjectionTargetType()!=null) {
                        Class requestedPortType = service.getClass().getClassLoader().loadClass(desc.getInjectionTargetType());
                        ArrayList<WebServiceFeature> wsFeatures = getWebServiceFeatures(desc);
                        if (wsFeatures.size() >0) {
                             injValue = service.getPort(requestedPortType,wsFeatures.toArray(new WebServiceFeature[0]));
                        }   else {
                            injValue = service.getPort(requestedPortType);
                        }
                    }

                }

            } else {
                // Generic service interface / no WSDL
                QName serviceName = desc.getServiceName();
                if( serviceName == null ) {
                    // ServiceFactory API requires a service-name.
                    // However, 109 does not allow getServiceName() to be
                    // called, so it's ok to use a dummy value.
                    serviceName = new QName("urn:noservice", "servicename");
                }
                ServiceFactory serviceFac = ServiceFactory.newInstance();
                serviceDelegate = serviceFac.createService(serviceName);
            }

            // Create a proxy for the service object.
            // Get a proxy only in jaxrpc case because in jaxws the service class is not
            // an interface any more
            InvocationHandler handler = null;
            if(serviceDelegate != null) {

                handler = new ServiceInvocationHandler(desc, serviceDelegate, cl);
                returnObj = Proxy.newProxyInstance
                        (cl, new Class[] { serviceInterfaceClass }, handler);
            } else if(jaxwsDelegate != null) {
                returnObj = jaxwsDelegate;
            } else if(injValue != null) {
                returnObj = injValue;
            }
        } catch(PrivilegedActionException pae) {
            logger.log(Level.WARNING, "", pae);
            NamingException ne = new NamingException();
            ne.initCause(pae.getCause());
            throw ne;
        } catch(Exception e) {
            logger.log(Level.WARNING, "", e);
            NamingException ne = new NamingException();
            ne.initCause(e);
            throw ne;
        } finally {
            WSContainerResolver.unset();
        }

        return returnObj;
    }

    private Object initiateInstance(Class svcClass, ServiceReferenceDescriptor desc)
            throws Exception {


        //TODO BM if JBI needs this reenable it
        /*com.sun.enterprise.webservice.ServiceRefDescUtil descUtil =
           new com.sun.enterprise.webservice.ServiceRefDescUtil();
        descUtil.preServiceCreate(desc);*/
        WsUtil wsu = new WsUtil();
        URL wsdlFile = wsu.privilegedGetServiceRefWsdl(desc);
        // Check if there is a catalog for this web service client
        // If so resolve the catalog entry
        String genXmlDir;
        if(desc.getBundleDescriptor().getApplication() != null) {
            genXmlDir = desc.getBundleDescriptor().getApplication().getGeneratedXMLDirectory();
            if(!desc.getBundleDescriptor().getApplication().isVirtual()) {
                String subDirName = desc.getBundleDescriptor().getModuleDescriptor().getArchiveUri();
                genXmlDir += (File.separator+subDirName.replaceAll("\\.""_"));
            }
        } else {
            // this is the case of an appclient being run as class file from command line
            genXmlDir = desc.getBundleDescriptor().getModuleDescriptor().getArchiveUri();
        }
        /* TODO BM resolve catalog
        File catalogFile = new File(genXmlDir,
                desc.getBundleDescriptor().getDeploymentDescriptorDir() +
                    File.separator + "jax-ws-catalog.xml");

        if(catalogFile.exists()) {
            wsdlFile = wsu.resolveCatalog(catalogFile, desc.getWsdlFileUri(), null);
        }   */


        Object obj = null ;

        java.lang.reflect.Constructor cons = svcClass.getConstructor
                (new Class[]{java.net.URL.class,
                        javax.xml.namespace.QName.class});
        obj =
                cons.newInstance(wsdlFile, desc.getServiceName());


        /*TODO BM if jbi needs this reenable it
        descUtil.postServiceCreate();
        */
        return obj;

    }

    private ArrayList<WebServiceFeature> getWebServiceFeatures(ServiceReferenceDescriptor desc) {
         /**
         * JAXWS 2.2 enables @MTOM, @Addressing @RespectBinding
         * on WebServiceRef
         * If these are present use the
         * Service(url,wsdl,features) constructor
         */
        ArrayList<WebServiceFeature> wsFeatures = new ArrayList<WebServiceFeature>();
        if (desc.isMtomEnabled()) {
            wsFeatures.add( new MTOMFeature(true,desc.getMtomThreshold()))   ;
        }
        com.sun.enterprise.deployment.Addressing add = desc.getAddressing();
        if (add != null) {
            wsFeatures.add( new AddressingFeature(
                    add.isEnabled(),add.isRequired(),getResponse(add.getResponses())))   ;
        }
        com.sun.enterprise.deployment.RespectBinding rb = desc.getRespectBinding();
        if (rb != null) {
            wsFeatures.add( new RespectBindingFeature(rb.isEnabled()))   ;
        }
        Map<Class<? extends Annotation>, Annotation> otherAnnotations =
            desc.getOtherAnnotations();
        Iterator it = otherAnnotations.values().iterator();
        while(it.hasNext()){
            wsFeatures.add(getWebServiceFeatureBean((Annotation)it.next()));
        }
       
        return wsFeatures;
    }

    private AddressingFeature.Responses getResponse(String s) {
       if (s != null) {
            return AddressingFeature.Responses.valueOf(AddressingFeature.Responses.class,s);
        } else return AddressingFeature.Responses.ALL;
       
    }

    private void resolvePortComponentLinks(ServiceReferenceDescriptor desc)
            throws Exception {

        // Resolve port component links to target endpoint address.
        // We can't assume web service client is running in same VM
        // as endpoint in the intra-app case because of app clients.
        //
        // Also set port-qname based on linked port's qname if not
        // already set.
        for(Iterator iter = desc.getPortsInfo().iterator(); iter.hasNext();) {
            ServiceRefPortInfo portInfo = (ServiceRefPortInfo) iter.next();

            if( portInfo.isLinkedToPortComponent() ) {
                WebServiceEndpoint linkedPortComponent =
                        portInfo.getPortComponentLink();

                // XXX-JD we could at this point try to figure out the
                // endpoint-address from the ejb wsdl file but it is a
                // little complicated so I will leave it for post Beta2
                if( !(portInfo.hasWsdlPort()) ) {
                    portInfo.setWsdlPort(linkedPortComponent.getWsdlPort());
                }
            }
        }
    }

    private  WebServiceFeature getWebServiceFeatureBean(Annotation a) {
        WebServiceFeatureAnnotation wsfa = a.annotationType().getAnnotation(WebServiceFeatureAnnotation.class);

        Class<? extends WebServiceFeature> beanClass = wsfa.bean();
        WebServiceFeature bean;

        Constructor ftrCtr = null;
        String[] paramNames = null;
        for (Constructor con : beanClass.getConstructors()) {
            FeatureConstructor ftrCtrAnn = (FeatureConstructor) con.getAnnotation(FeatureConstructor.class);
            if (ftrCtrAnn != null) {
                if (ftrCtr == null) {
                    ftrCtr = con;
                    paramNames = ftrCtrAnn.value();
                } else {
                    throw new WebServiceException(ModelerMessages.RUNTIME_MODELER_WSFEATURE_MORETHANONE_FTRCONSTRUCTOR(a, beanClass));
                }
            }
        }
        if (ftrCtr == null) {
            throw new WebServiceException(ModelerMessages.RUNTIME_MODELER_WSFEATURE_NO_FTRCONSTRUCTOR(a, beanClass));
        }
        if (ftrCtr.getParameterTypes().length != paramNames.length) {
            throw new WebServiceException(ModelerMessages.RUNTIME_MODELER_WSFEATURE_ILLEGAL_FTRCONSTRUCTOR(a, beanClass));
        }

        try {
            Object[] params = new Object[paramNames.length];
            for (int i = 0; i < paramNames.length; i++) {
                Method m = a.annotationType().getDeclaredMethod(paramNames[i]);
                params[i] = m.invoke(a);
            }
            bean = (WebServiceFeature) ftrCtr.newInstance(params);
        } catch (Exception e) {
            throw new WebServiceException(e);
        }

        return bean;
    }


}
TOP

Related Classes of org.glassfish.webservices.WebServiceReferenceManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.