alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (ServiceInvocationHandler.java)

This example Glassfish source code file (ServiceInvocationHandler.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

call, class, class, exception, integer, integer, method, method, net, network, object, object, qname, reflection, service, servicerefportinfo, set, util

The Glassfish ServiceInvocationHandler.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 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 java.net.URL;

import java.util.HashSet;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;

import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.HandlerRegistry;
import javax.xml.rpc.Stub;
import javax.xml.rpc.Call;


import com.sun.enterprise.deployment.ServiceReferenceDescriptor;
import com.sun.enterprise.deployment.ServiceRefPortInfo;
import com.sun.enterprise.deployment.NameValuePairDescriptor;
import com.sun.enterprise.deployment.runtime.common.MessageSecurityBindingDescriptor;
import org.glassfish.internal.api.Globals;



/**
 * InvocationHandler used to intercept calls to concrete JAXRPC 
 * Service implementation.  
 *
 * NOTE : This class makes no distinction between "partial" WSDL and
 * "full" WSDL.  If a service-ref's packaged WSDL is "partial", the
 * deployer is required to specify a wsdl-override in the runtime info
 * that points to a final WSDL.  In such a case, the behavior for each
 * method listed in the table in section 4.2.2.7 of the spec is the
 * same as Full WSDL.
 *
 * @author Kenneth Saks
 */
public class ServiceInvocationHandler implements InvocationHandler {

    private ServiceReferenceDescriptor serviceRef;

    // real service instance
    private Service serviceDelegate;

    // used in full wsdl case for DII methods. Lazily instantiated.
    private Service configuredServiceDelegate;

    private ClassLoader classLoader;

    private Method getClientManagedPortMethod;

    // location of full wsdl associated with service-ref
    private URL wsdlLocation;

    private boolean fullWsdl = false;
    private boolean noWsdl = false;

    private WsUtil wsUtil = new WsUtil();
    private org.glassfish.webservices.SecurityService  secServ;

    // Service method types
    private static final int CREATE_CALL_NO_ARGS = 1;
    private static final int CREATE_CALL_PORT = 2;
    private static final int CREATE_CALL_OPERATION_QNAME = 3;
    private static final int CREATE_CALL_OPERATION_STRING = 4;
    private static final int GET_CALLS = 5;
    private static final int GET_HANDLER_REGISTRY = 6;
    private static final int GET_PORT_CONTAINER_MANAGED = 7;
    private static final int GET_PORT_CLIENT_MANAGED = 8;
    private static final int GET_PORTS = 9;
    private static final int GET_SERVICE_NAME = 10;
    private static final int GET_TYPE_MAPPING_REGISTRY = 11;
    private static final int GET_WSDL_LOCATION = 12;
    private static final int GENERATED_SERVICE_METHOD = 13;

    private static Map serviceMethodTypes;
    private static Set fullWsdlIllegalMethods;
    private static Set noWsdlIllegalMethods;

    static {
        Init();
    }

    public ServiceInvocationHandler(ServiceReferenceDescriptor descriptor,
                                    Service delegate, ClassLoader loader)
            throws Exception {

        serviceRef = descriptor;
        serviceDelegate = delegate;
        classLoader = loader;

        if( serviceRef.hasWsdlFile() ) {
            wsdlLocation = wsUtil.privilegedGetServiceRefWsdl(serviceRef);
            fullWsdl = true;
        } else {
            noWsdl = true;
        }

        getClientManagedPortMethod = javax.xml.rpc.Service.class.getMethod
                ("getPort", new Class[] { QName.class, Class.class } );

        if (Globals.getDefaultHabitat() != null) {
            secServ = Globals.get(org.glassfish.webservices.SecurityService.class);
        }
        addMessageSecurityHandler(delegate);
    }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {

        // NOTE : be careful with "args" parameter.  It is null
        //        if method signature has 0 arguments.

        if( method.getDeclaringClass() == java.lang.Object.class )  {
            return invokeJavaObjectMethod(this, method, args);
        }

        int methodType = getMethodType(method);

        checkUnsupportedMethods(methodType);

        Object returnValue = null;

        try {

            // Initialize method info for invocation based on arguments.
            // Some/All of this might be overridden below.
            Object serviceToInvoke = serviceDelegate;
            Method methodToInvoke  = method;
            int methodTypeToInvoke = methodType;
            Object[] argsForInvoke = args;

            switch(methodType) {

                case GET_PORT_CONTAINER_MANAGED :
                    Class serviceEndpointInterfaceClass = (Class) args[0];
                    String serviceEndpointInterface =
                            serviceEndpointInterfaceClass.getName();
                    ServiceRefPortInfo portInfo =
                            serviceRef.getPortInfo(serviceEndpointInterface);

                    // If we have a port, use it to call getPort(QName, SEI) instead
                    if( (portInfo != null) && portInfo.hasWsdlPort() ) {
                        methodToInvoke = getClientManagedPortMethod;
                        methodTypeToInvoke = GET_PORT_CLIENT_MANAGED;
                        argsForInvoke  = new Object[] { portInfo.getWsdlPort(),
                                args[0] };
                    } else {
                        // This means the deployer did not resolve the port to
                        // which this SEI is mapped.  Just call getPort(SEI)
                        // method on delegate. This is not guaranteed to work.
                    }
                    break;

                case GET_WSDL_LOCATION :
                    return wsdlLocation;

                case CREATE_CALL_PORT :
                case CREATE_CALL_OPERATION_QNAME :
                case CREATE_CALL_OPERATION_STRING :
                case GET_CALLS :
                case GET_PORTS :

                    serviceToInvoke = getConfiguredServiceDelegate();
                    break;

            } // End switch (methodType)

            returnValue = methodToInvoke.invoke(serviceToInvoke, argsForInvoke);

            if( returnValue instanceof Stub ) {
                Stub stub = (Stub) returnValue;
                setStubProperties(stub, methodTypeToInvoke, methodToInvoke,
                        argsForInvoke);
            } else if( returnValue instanceof Call ) {
                Call[] calls = new Call[1];
                calls[0] = (Call) returnValue;
                setCallProperties(calls, methodTypeToInvoke, argsForInvoke);
            } else if( methodType == GET_CALLS ) {
                Call[] calls = (Call[]) returnValue;
                setCallProperties(calls, methodTypeToInvoke, argsForInvoke);
            }

        } catch(InvocationTargetException ite) {
            throw ite.getCause();
        }

        return returnValue;
    }

    public HandlerInfo getMessageSecurityHandlerInfo(QName port) throws Exception
    {
        HandlerInfo rvalue = null;

        MessageSecurityBindingDescriptor binding = null;
        ServiceRefPortInfo portInfo = serviceRef.getPortInfoByPort(port);
        if (portInfo != null) {
            binding = portInfo.getMessageSecurityBinding();
        }
        if (secServ != null) {
           rvalue = secServ.getMessageSecurityHandler(binding, serviceRef.getServiceName());
        }
        return rvalue;
    }

    private boolean addMessageSecurityHandler(Service service) throws Exception
    {
        HandlerRegistry registry = service.getHandlerRegistry();
        Iterator ports = null;
        try {
            ports = service.getPorts();
        } catch (Exception e) {
            // FIXME: should make sure that the exception was thrown because
            // the service is not fully defined; but for now just return.
            ports = null;
        }

        while(ports != null && ports.hasNext()) {

            QName nextPort = (QName) ports.next();

            List handlerChain = registry.getHandlerChain(nextPort);

            // append security handler to the end of every handler chain
            // ASSUMPTION 1: that registry.getHandlerChain() never returns null.
            // ASSUMPTION 2: that handlers from ServiceRef have already been added

            HandlerInfo handlerInfo = getMessageSecurityHandlerInfo(nextPort);

            if (handlerInfo != null) {
                handlerChain.add(handlerInfo);
            }
        }

        return ports == null ? false : true;
    }

    private Service getConfiguredServiceDelegate() throws Exception {
        synchronized(this) {
            if( configuredServiceDelegate == null ) {
                // We need a ConfiguredService to handle these
                // invocations, since the JAXRPC RI Generated Service impl 
                // does not.  Configured service is potentially 
                // a heavy-weight object so we lazily instantiate it to
                // take advantage of the likelihood that 
                // GeneratedService service-refs won't be used for DII.
                Service configuredService =
                        wsUtil.createConfiguredService(serviceRef);
                wsUtil.configureHandlerChain(serviceRef, configuredService,
                        configuredService.getPorts(), classLoader);
                configuredServiceDelegate = configuredService;

                addMessageSecurityHandler(configuredService);
            }
        }
        return configuredServiceDelegate;
    }

    private int getMethodType(Method method) {
        Integer methodType = (Integer) serviceMethodTypes.get(method);
        return (methodType != null) ?
                methodType.intValue() : GENERATED_SERVICE_METHOD;
    }

    /**
     * Convert invocation method to a constant for easier processing.
     */
    private static void Init() {

        serviceMethodTypes     = new HashMap();
        fullWsdlIllegalMethods = new HashSet();
        noWsdlIllegalMethods   = new HashSet();

        try {

            Class noParams[]   = new Class[0];
            String createCall  = "createCall";
            Class serviceClass = javax.xml.rpc.Service.class;

            //
            // Map Service method to method type.
            //

            Method createCallNoArgs =
                    serviceClass.getDeclaredMethod(createCall, noParams);
            serviceMethodTypes.put(createCallNoArgs,
                    new Integer(CREATE_CALL_NO_ARGS));

            Method createCallPort =
                    serviceClass.getDeclaredMethod(createCall,
                            new Class[] { QName.class });
            serviceMethodTypes.put(createCallPort,
                    new Integer(CREATE_CALL_PORT));

            Method createCallOperationQName =
                    serviceClass.getDeclaredMethod
                            (createCall, new Class[] { QName.class, QName.class });
            serviceMethodTypes.put(createCallOperationQName,
                    new Integer(CREATE_CALL_OPERATION_QNAME));

            Method createCallOperationString =
                    serviceClass.getDeclaredMethod
                            (createCall, new Class[] { QName.class, String.class });
            serviceMethodTypes.put(createCallOperationString,
                    new Integer(CREATE_CALL_OPERATION_STRING));

            Method getCalls = serviceClass.getDeclaredMethod
                    ("getCalls", new Class[] { QName.class });
            serviceMethodTypes.put(getCalls, new Integer(GET_CALLS));

            Method getHandlerRegistry = serviceClass.getDeclaredMethod
                    ("getHandlerRegistry", noParams);
            serviceMethodTypes.put(getHandlerRegistry,
                    new Integer(GET_HANDLER_REGISTRY));

            Method getPortContainerManaged = serviceClass.getDeclaredMethod
                    ("getPort", new Class[] { Class.class });
            serviceMethodTypes.put(getPortContainerManaged,
                    new Integer(GET_PORT_CONTAINER_MANAGED));

            Method getPortClientManaged = serviceClass.getDeclaredMethod
                    ("getPort", new Class[] { QName.class, Class.class });
            serviceMethodTypes.put(getPortClientManaged,
                    new Integer(GET_PORT_CLIENT_MANAGED));

            Method getPorts = serviceClass.getDeclaredMethod
                    ("getPorts", noParams);
            serviceMethodTypes.put(getPorts, new Integer(GET_PORTS));

            Method getServiceName = serviceClass.getDeclaredMethod
                    ("getServiceName", noParams);
            serviceMethodTypes.put(getServiceName,
                    new Integer(GET_SERVICE_NAME));

            Method getTypeMappingRegistry = serviceClass.getDeclaredMethod
                    ("getTypeMappingRegistry", noParams);
            serviceMethodTypes.put(getTypeMappingRegistry,
                    new Integer(GET_TYPE_MAPPING_REGISTRY));

            Method getWsdlLocation = serviceClass.getDeclaredMethod
                    ("getWSDLDocumentLocation", noParams);
            serviceMethodTypes.put(getWsdlLocation,
                    new Integer(GET_WSDL_LOCATION));
        } catch(NoSuchMethodException nsme) {}

        // Implementation of table 4.2.2.7.  All "No WSDL" column cells
        // with value Unspecified throw UnsupportedOperationException

        fullWsdlIllegalMethods.add(new Integer(GET_HANDLER_REGISTRY));
        fullWsdlIllegalMethods.add(new Integer(GET_TYPE_MAPPING_REGISTRY));

        noWsdlIllegalMethods.add(new Integer(CREATE_CALL_PORT));
        noWsdlIllegalMethods.add(new Integer(CREATE_CALL_OPERATION_QNAME));
        noWsdlIllegalMethods.add(new Integer(CREATE_CALL_OPERATION_STRING));
        noWsdlIllegalMethods.add(new Integer(GET_CALLS));
        noWsdlIllegalMethods.add(new Integer(GET_HANDLER_REGISTRY));
        noWsdlIllegalMethods.add(new Integer(GET_PORT_CONTAINER_MANAGED));
        noWsdlIllegalMethods.add(new Integer(GET_PORT_CLIENT_MANAGED));
        noWsdlIllegalMethods.add(new Integer(GET_PORTS));
        noWsdlIllegalMethods.add(new Integer(GET_SERVICE_NAME));
        noWsdlIllegalMethods.add(new Integer(GET_TYPE_MAPPING_REGISTRY));
        noWsdlIllegalMethods.add(new Integer(GET_WSDL_LOCATION));

        // This case shouldn't happen since if service-ref has generated
        // service and no WSDL it won't get past deployment, but it's here
        // for completeness.
        noWsdlIllegalMethods.add(new Integer(GENERATED_SERVICE_METHOD));
    }

    private void checkUnsupportedMethods(int methodType)
            throws UnsupportedOperationException {

        Set illegalMethods = fullWsdl ?
                fullWsdlIllegalMethods : noWsdlIllegalMethods;

        if( illegalMethods.contains(new Integer(methodType)) ) {
            throw new UnsupportedOperationException();
        }

        return;
    }

    private void setStubProperties(Stub stub, int methodType, Method method,
                                   Object[] args) {

        // Port info lookup will be based on SEI or port.
        QName port = null;
        String serviceEndpointInterface = null;

        switch(methodType) {
            case GET_PORT_CONTAINER_MANAGED :

                serviceEndpointInterface = ((Class) args[0]).getName();
                break;

            case GET_PORT_CLIENT_MANAGED :

                port = (QName) args[0];
                serviceEndpointInterface = ((Class) args[1]).getName();
                break;

            case GENERATED_SERVICE_METHOD :

                // java.rmi.Remote get<Name_of_wsdl:port>()
                String portLocalPart = method.getName().startsWith("get") ?
                        method.getName().substring(3) : null;
                if( portLocalPart != null ) {
                    QName serviceName = serviceRef.getServiceName();
                    port = new QName(serviceName.getNamespaceURI(), portLocalPart);
                }
                serviceEndpointInterface = method.getReturnType().getName();

                break;

            default :
                return;
        }

        ServiceRefPortInfo portInfo = null;

        // If port is known, it takes precedence in lookup.
        if( port != null ) {
            portInfo = serviceRef.getPortInfoByPort(port);
        }
        if( portInfo == null ) {
            portInfo = serviceRef.getPortInfoBySEI(serviceEndpointInterface);
        }

        if( portInfo != null ) {
            Set properties = portInfo.getStubProperties();

            for(Iterator iter = properties.iterator(); iter.hasNext();) {
                NameValuePairDescriptor next = (NameValuePairDescriptor)
                        iter.next();
                if( next.getName().equals
                        (WsUtil.CLIENT_TRANSPORT_LOG_PROPERTY) ) {
                    // value is a URL
                    wsUtil.setClientTransportLog(serviceRef, stub,
                            next.getValue());
                } else if(next.getName().equals(ServiceEngineUtil.JBI_ENABLED)){
                    setJBIProperties(stub, portInfo);
                } else {
                    stub._setProperty(next.getName(), next.getValue());
                }
            }

            // If this port has a resolved target endpoint address due to a
            // port-component-link, set it on stub.  However, if the runtime
            // info has an entry for target endpoint address, that takes 
            // precedence.
            if( portInfo.hasTargetEndpointAddress() ) {
                if(!portInfo.hasStubProperty(Stub.ENDPOINT_ADDRESS_PROPERTY)) {
                    stub._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY,
                            portInfo.getTargetEndpointAddress());
                }
            }
        }
    }

    private void setCallProperties(Call[] calls, int methodType, Object[] args){

        Set callProperties = getPropertiesForCall(methodType, args);

        if( callProperties != null ) {
            for(int callIndex = 0; callIndex < calls.length; callIndex++) {
                setCallProperties(calls[callIndex], callProperties);
            }
        }
    }

    private Set getPropertiesForCall(int methodType, Object args[]) {

        Set callProperties = null;
        switch(methodType) {

            case CREATE_CALL_PORT :
            case CREATE_CALL_OPERATION_QNAME :
            case CREATE_CALL_OPERATION_STRING :
            case GET_CALLS :

                // Each of these methods has port as first argument.
                QName port = (QName) args[0];

                // Check if call properties are set at the port level.
                ServiceRefPortInfo portInfo =
                        serviceRef.getPortInfoByPort(port);
                if( portInfo != null ) {
                    callProperties = portInfo.getCallProperties();
                }

                break;

            case CREATE_CALL_NO_ARGS :

                callProperties = serviceRef.getCallProperties();
                break;

        }

        return callProperties;
    }

    private void setCallProperties(Call call, Set callProperties) {
        for(Iterator iter = callProperties.iterator(); iter.hasNext();) {
            NameValuePairDescriptor next = (NameValuePairDescriptor)
                    iter.next();
            call.setProperty(next.getName(), next.getValue());
        }
    }

    private Object invokeJavaObjectMethod(InvocationHandler handler,
                                          Method method, Object[] args)
            throws Throwable {

        Object returnValue = null;

        // Can only be one of : 
        //     boolean java.lang.Object.equals(Object)
        //     int     java.lang.Object.hashCode()
        //     String  java.lang.Object.toString()
        //
        // Optimize by comparing as few characters as possible.

        switch( method.getName().charAt(0) ) {
            case 'e' :
                Object other = Proxy.isProxyClass(args[0].getClass()) ?
                        Proxy.getInvocationHandler(args[0]) : args[0];
                returnValue = new Boolean(handler.equals(other));
                break;
            case 'h' :
                returnValue = new Integer(handler.hashCode());
                break;
            case 't' :
                returnValue = handler.toString();
                break;
            default :
                throw new Throwable("Object method " + method.getName() +
                        "not found");
        }

        return returnValue;
    }

    private void setJBIProperties(Object stubOrCall, ServiceRefPortInfo portInfo) {
        // Check if the target service is a JBI service, and get its QName
        QName svcQName = serviceRef.getServiceName();
        if ( svcQName == null )
            return;

        if ( stubOrCall instanceof Stub ) {
            com.sun.xml.rpc.spi.runtime.StubBase stub =
                    (com.sun.xml.rpc.spi.runtime.StubBase)stubOrCall;

            try {
                // This statement is getting executed only
                //because jbi-enabled property on the stub is set to true
                /**TODO BM fix this later
                 ServiceEngineUtil.setJBITransportFactory(portInfo, stub, true);
                 */
            } catch(Throwable e) {
                // Do nothing
                //logger.severe("Exception raised while setting transport " +
                //      "factory to NMR : " + e.getMessage());
            }
            return;
        }
    }
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish ServiceInvocationHandler.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.