org.ow2.cmi.rpc.CMIProxyFactory Maven / Gradle / Ivy
The newest version!
/**
* CMI : Cluster Method Invocation
* Copyright (C) 2007,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: CMIProxyFactory.java 2438 2010-02-24 16:20:30Z benoitf $
* --------------------------------------------------------------------------
*/
package org.ow2.cmi.rpc;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import javax.ejb.EJBHome;
import net.jcip.annotations.ThreadSafe;
import org.ow2.cmi.controller.common.ClusterViewManager;
import org.ow2.cmi.ejb2_1.pool.EJBObjectFactory;
import org.ow2.cmi.ejb2_1.rpc.EJBHomeInvocationHandler;
import org.ow2.cmi.ejb2_1.rpc.ha.HAEJBHomeInvocationHandler;
import org.ow2.cmi.pool.StubOrProxyFactory;
import org.ow2.cmi.reference.CMIReference;
import org.ow2.cmi.reference.CMIReferenceable;
import org.ow2.cmi.reference.ObjectNotFoundException;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;
import org.ow2.util.pool.api.IPoolConfiguration;
import org.ow2.util.pool.api.Pool;
import org.ow2.util.pool.impl.JPool;
/**
* Factory of CMI proxy which intercepts the remote method invocation on clustered objects.
* @author The new CMI team
*/
@ThreadSafe
public final class CMIProxyFactory {
/**
* Logger.
*/
private static final Log LOGGER = LogFactory.getLog(CMIProxyFactory.class);
/**
* Utility class, so not public constructor.
*/
private CMIProxyFactory() {}
/**
* Returns a new CMI proxy.
* @param clusterViewManager a manager of the cluster view
* @param objectName a name of object
* @param protocolName a name of protocol
* @return a new CMI proxy
* @throws CMIProxyFactoryException if we get interface for the given object
* @throws ObjectNotFoundException if none object has the given name
*/
@SuppressWarnings("unchecked")
public static CMIProxy newCMIProxy(
final ClusterViewManager clusterViewManager, final String objectName, final String protocolName)
throws CMIProxyFactoryException, ObjectNotFoundException {
// Keep the current classloader: it can be a smart classloader
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class> itfClass = clusterViewManager.getInterface(objectName);
InvocationHandler invocationHandler;
// Construct the invocation handler
// Has it a state ?
// NB: A bean can be stateless but "replicated", ie managed by the replication manager
if(!clusterViewManager.hasState(objectName) && !clusterViewManager.isReplicated(objectName)) {
// The object is an EJB2 or not ?
if(Arrays.asList(itfClass.getInterfaces()).contains(EJBHome.class)) {
// EJB2
LOGGER.debug("Object with name {0} is a stateless ejb2");
synchronized(clusterViewManager){
// The first time, create a pool to share stubs for EJBObject
if(clusterViewManager.getPool(objectName) == null) {
LOGGER.debug("First lookup on {0}: creation of the pool for its stubs for EJBObject", objectName);
Pool, CMIReference> pool =
new JPool, CMIReference>(
new EJBObjectFactory(clusterViewManager));
IPoolConfiguration poolConfiguration = clusterViewManager.getPoolConfiguration(objectName);
if(poolConfiguration != null) {
pool.setPoolConfiguration(poolConfiguration);
}
clusterViewManager.setPool(objectName, pool);
}
}
// Use the handler dedicated to the ejb2
invocationHandler =
new EJBHomeInvocationHandler(
classLoader, clusterViewManager, objectName, protocolName,
(Class extends EJBHome>) itfClass);
} else {
// POJO without state: each stub or proxy are equivalent
synchronized(clusterViewManager){
// The first time, create a pool to share mandatories (stub or proxy)
if(clusterViewManager.getPool(objectName) == null) {
LOGGER.debug("First lookup on {0}: creation of the pool for its mandatories", objectName);
Pool, CMIReference> pool =
new JPool, CMIReference>(
new StubOrProxyFactory(clusterViewManager));
IPoolConfiguration poolConfiguration = clusterViewManager.getPoolConfiguration(objectName);
if(poolConfiguration != null) {
pool.setPoolConfiguration(poolConfiguration);
}
clusterViewManager.setPool(objectName, pool);
}
}
// Use the standard handler
invocationHandler =
new POJOInvocationHandler(classLoader, clusterViewManager, objectName, protocolName, itfClass);
}
} else {
// With state or without state but handled by a replication managed
// The object is an EJB2 or not ?
if(Arrays.asList(itfClass.getInterfaces()).contains(EJBHome.class)) {
// EJB2
LOGGER.debug("Object with name {0} is a stateful ejb2 or an entity bean: the HA module will be used");
synchronized(clusterViewManager){
// The first time, create a pool to share stubs for EJBHome
if(clusterViewManager.getPool(objectName) == null) {
LOGGER.debug("First lookup on {0}: creation of the pool for its stubs for EJBHome", objectName);
Pool, CMIReference> pool =
new JPool, CMIReference>(
new StubOrProxyFactory(clusterViewManager));
IPoolConfiguration poolConfiguration = clusterViewManager.getPoolConfiguration(objectName);
if(poolConfiguration != null) {
pool.setPoolConfiguration(poolConfiguration);
}
clusterViewManager.setPool(objectName, pool);
}
}
// Use the HA EJB2 handler
invocationHandler = new HAEJBHomeInvocationHandler(
classLoader, clusterViewManager, objectName, protocolName, (Class extends EJBHome>) itfClass);
} else {
// POJO with state: each stub or proxy are different
// So a pool cannot be used :-( Good-Bye optimizations...
LOGGER.debug("Object with name {0} is a stateful POJO", objectName);
invocationHandler = new StatefulPOJOInvocationHandler(
classLoader, clusterViewManager, objectName, protocolName, itfClass,
clusterViewManager.getSessionId());
}
}
// Construct a proxy to enable the invocation handling
Object cmiProxy = Proxy.newProxyInstance(classLoader, new Class[] {itfClass, CMIProxy.class}, invocationHandler);
return (CMIProxy) cmiProxy;
}
}