/**
* EasyBeans
* Copyright (C) 2006-2009 Bull S.A.S.
* Contact: easybeans@ow2.org
*
* 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* --------------------------------------------------------------------------
* $Id: EJBLocalHomeInvocationHandler.java 5369 2010-02-24 14:58:19Z benoitf $
* --------------------------------------------------------------------------
*/
package org.ow2.easybeans.proxy.client;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.ejb.EJBException;
import javax.ejb.RemoveException;
import org.ow2.easybeans.asm.Type;
import org.ow2.easybeans.rpc.util.Hash;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;
/**
* Object acting as the proxy for EJB Local Home calls.
* @author Florent Benoit
*/
public class EJBLocalHomeInvocationHandler extends LocalCallInvocationHandler {
/**
* UID for serialization.
*/
private static final long serialVersionUID = -7113041945135321801L;
/**
* UID for serialization.
*/
private static Log logger = LogFactory.getLog(EJBLocalHomeInvocationHandler.class);
/**
* Build a new Invocation handler.
* @param embeddedID the Embedded server ID.
* @param containerId the id of the container that will be called on the
* remote side.
* @param factoryName the name of the remote factory.
* @param useID true if all instance build with this ref are unique
* (stateful), false if it references the same object (stateless)
*/
public EJBLocalHomeInvocationHandler(final Integer embeddedID, final String containerId, final String factoryName,
final boolean useID) {
super(embeddedID, containerId, factoryName, useID);
}
/**
* Default constructor (used for serialization).
*/
public EJBLocalHomeInvocationHandler() {
super();
}
/**
* Processes a method invocation on a proxy instance and returns the result.
* This method will be invoked on an invocation handler when a method is
* invoked on a proxy instance that it is associated with.
* @param proxy the proxy instance that the method was invoked on
* @param method the <code>Method</code> instance corresponding to the
* interface method invoked on the proxy instance. The declaring
* class of the <code>Method</code> object will be the interface
* that the method was declared in, which may be a superinterface of
* the proxy interface that the proxy class inherits the method
* through.
* @param args an array of objects containing the values of the arguments
* passed in the method invocation on the proxy instance, or
* <code>null</code> if interface method takes no arguments.
* Arguments of primitive types are wrapped in instances of the
* appropriate primitive wrapper class, such as
* <code>java.lang.Integer</code> or <code>java.lang.Boolean</code>.
* @return the value to return from the method invocation on the proxy
* instance.
* @throws Exception the exception to throw from the method invocation on
* the proxy instance.
*/
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Exception {
// Create ?
if (method != null) {
if (method.getName().startsWith("create")) {
// Return class (interface)
Class<?> itfClass = method.getReturnType();
// Build handler
LocalCallInvocationHandler handler = new LocalCallInvocationHandler(getEmbeddedID(), getContainerId(),
getFactoryName(), isUsingID());
// set the interface class
handler.setInterfaceClass(itfClass);
// Disable interface classname for businessinvokedinterface as it is a component interface
handler.setInterfaceClassName(null);
// Get current classloader
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Return proxy
Object beanProxy = Proxy.newProxyInstance(classLoader, new Class[] {itfClass}, handler);
// create the id for stateful bean
beanProxy.toString();
// Bean class not available on the client side, get ejbCreate
// method from the interface
// Store the current bean id value
Long beanId = getBeanId();
try {
Class<?> ejbHomeClass = classLoader.loadClass(getInterfaceClassName());
Method ejbCreateMethod = ejbHomeClass.getMethod("create", method.getParameterTypes());
// Void method descriptor
Type[] argumentTypes = Type.getArgumentTypes(ejbCreateMethod);
String methodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, argumentTypes);
// Get hash
long hashCode = Hash.hashMethod("ejbCreate", methodDescriptor);
// The current bean id must correspond to the handler bean
// id
setBeanId(handler.getBeanId());
// Call the ejbCreate method using the bean proxy
super.invoke(beanProxy, ejbCreateMethod, args, Long.valueOf(hashCode));
} catch (NoSuchMethodException e) {
// Nothing to do
logger.debug("No create method found", e);
} catch (EJBException e) {
// Method may not exists
Throwable t = e.getCause();
if (t != null && t instanceof NoSuchMethodException) {
logger.debug("Unable to call the ejbCreate method as it is not present on the bean.", e);
} else {
// else, rethrow exception
throw e;
}
} finally {
// Set to previous value
setBeanId(beanId);
}
// return the proxy built
return beanProxy;
}
}
// remove method ?
if (method != null && "remove".equals(method.getName())) {
throw new RemoveException("Only 2.1 entity beans can use the remove(primary key) method.");
}
return super.invoke(proxy, method, args);
}
}