All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.carol.cmi.rpc.StatefulPOJOInvocationHandler Maven / Gradle / Ivy

The newest version!
/**
 * CMI : Cluster Method Invocation
 * Copyright (C) 2008 Bull S.A.S.
 * Contact: [email protected]
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 * --------------------------------------------------------------------------
 * $Id: StatefulPOJOInvocationHandler.java 1578 2008-01-20 15:34:28Z loris $
 * --------------------------------------------------------------------------
 */

package org.ow2.carol.cmi.rpc;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

import org.ow2.carol.cmi.controller.common.ClusterViewManager;
import org.ow2.carol.cmi.reference.CMIProxyHandle;
import org.ow2.carol.cmi.reference.CMIProxyHandleImpl;
import org.ow2.carol.cmi.reference.CMIReference;
import org.ow2.carol.cmi.reference.CMIReferenceable;
import org.ow2.carol.cmi.reference.CMIReferenceableWrapper;
import org.ow2.carol.cmi.reference.ServerRef;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;

/**
 * This is the {@link InvocationHandler} for stateful POJOs.
 * @author Loris Bouzonnet
 */
public class StatefulPOJOInvocationHandler extends CMIInvocationHandler {

    /**
     * Id for serializable class.
     */
    private static final long serialVersionUID = -5482752408858461947L;

    /**
     * Logger.
     */
    private static final Log LOGGER = LogFactory.getLog(StatefulPOJOInvocationHandler.class);

    /**
     * The classloader to use.
     * When the smart factory is used, it is the smart classloader.
     */
    private transient ClassLoader classLoader;

    /**
     * @param classLoader
     * @param clusterViewManager
     * @param objectName
     * @param protocolName
     * @param itf
     */
    protected StatefulPOJOInvocationHandler(
            final ClassLoader classLoader,
            final ClusterViewManager clusterViewManager,
            final String objectName,
            final String protocolName,
            final Class itf) {
        super(clusterViewManager, objectName, protocolName, true, itf);
        this.classLoader = classLoader;
    }

    /**
     * Handles remote methods.
     **/
    @Override
    protected Object invokeRemoteMethod(
            final Object proxy, final Method method, final Object... args) throws Throwable {

        // Use the same classloader that during the creation of this object
        ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(classLoader);
        setClassLoader(oldClassLoader);
        try {
            return super.invokeRemoteMethod(proxy, method, args);
        } finally {
            Thread.currentThread().setContextClassLoader(oldClassLoader);
        }
    }


    @Override
    protected void checkInitialized() throws CMIInvocationHandlerException {
        if(classLoader == null) {
            try {
                classLoader = Thread.currentThread().getContextClassLoader();
            } catch(Exception e) {
                throw new POJOInvocationHandlerException(
                        "Cannot retrieve the classloader for object with name " + objectName, e);
            }
        }
    }

    @Override
    protected CMIProxyHandle getHandle(final CMIProxy cmiProxy) {
        if(cmiProxyHandle == null) {
            cmiProxyHandle = new CMIProxyHandleImpl(objectName, itf.getName(), cmiProxy);
        }
        return cmiProxyHandle;
    }

    @Override
    protected CMIReferenceable getCMIReferenceable(
            final CMIReference cmiReference) throws Exception {
        ServerRef serverRef = cmiReference.getServerRef();
        String protocol = serverRef.getProtocol();
        // Get a context to perform a lookup
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, clusterViewManager.getInitialContextFactoryName(protocol));
        env.put(Context.PROVIDER_URL, serverRef.getProviderURL());
        Context chosenContext;
        try{
            chosenContext = new InitialContext(env);
        } catch (NamingException e) {
            LOGGER.error("Cannot get a real context", e);
            throw new POJOInvocationHandlerException("Cannot get a real context", e);
        }
        if(chosenContext == null) {
            LOGGER.error("Cannot get a real context");
            throw new POJOInvocationHandlerException("Cannot get a real context");
        }

        // Get a JNDI name to perform a lookup
        String bindName = cmiReference.getObjectName();
        Class interfaceClass;
        try {
            interfaceClass = clusterViewManager.getInterface(bindName);
        } catch (Exception e) {
            LOGGER.error("Cannot get interface for name {0}", bindName, e);
            throw new POJOInvocationHandlerException("Cannot get interface for name "+bindName, e);
        }

        // Lookup...
        Object object = null;
        try {
            LOGGER.debug("Lookup {0} on {1}", bindName, serverRef.getProviderURL());
            object = PortableRemoteObject.narrow(chosenContext.lookup(bindName), interfaceClass);
        } catch (NamingException e) {
            LOGGER.info("No ClientClusterViewProvider is bound with the name {0} at the url {1}",
                    bindName, serverRef.getProviderURL(), e);
            throw new POJOInvocationHandlerException(
                    "No ClientClusterViewProvider is bound with the name "+bindName
                    +" at the url "+serverRef.getProviderURL(), e);
        }

        // Construct a CMIReferenceable with the given CMIReference and the retrieved object
        return new CMIReferenceableWrapper(cmiReference, object);
    }

    @Override
    protected void onExceptionHook(
            final String objectName, final CMIReferenceable cmiReferenceable)
            throws Throwable {
        // Do nothing
    }

    @Override
    protected void onFinallyHook(
            final String objectName, final CMIReferenceable cmiReferenceable) {
        // Do nothing
    }

}