/**
* 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: EJB21Finder.java 5369 2010-02-24 14:58:19Z benoitf $
* --------------------------------------------------------------------------
*/
package org.ow2.easybeans.deployment.annotations.helper.bean;
import java.util.ArrayList;
import java.util.List;
import org.ow2.easybeans.asm.Opcodes;
import org.ow2.easybeans.asm.Type;
import org.ow2.easybeans.deployment.metadata.ejbjar.EasyBeansEjbJarClassMetadata;
import org.ow2.easybeans.deployment.metadata.ejbjar.EasyBeansEjbJarMethodMetadata;
import org.ow2.easybeans.deployment.metadata.ejbjar.EjbJarArchiveMetadata;
import org.ow2.util.ee.metadata.ejbjar.impl.struct.JRemove;
import org.ow2.util.scan.api.metadata.structures.JMethod;
/**
* This class finds the business interface that are used as return type in the
* Home or LocalHome interface of the Bean.
* @author Florent Benoit
*/
public final class EJB21Finder {
/**
* Signature of the remove method.
*/
private static final JMethod REMOVE_METHOD = new JMethod(Opcodes.ACC_PUBLIC, "remove", "()V", null,
new String[] {"javax/ejb/RemoveException"});
/**
* Signature of the isIdentical(EJBObject) method.
*/
private static final JMethod ISIDENTICAL_METHOD = new JMethod(Opcodes.ACC_PUBLIC, "isIdentical", "(Ljavax/ejb/EJBObject;)Z",
null, new String[] {"java/rmi/RemoteException"});
/**
* Signature of the isIdentical(EJBLocalObject) method.
*/
private static final JMethod ISIDENTICAL_LOCAL_METHOD = new JMethod(Opcodes.ACC_PUBLIC, "isIdentical",
"(Ljavax/ejb/EJBLocalObject;)Z", null, new String[] {"javax/ejb/EJBException"});
/**
* Signature of the getHandle method.
*/
private static final JMethod GETHANDLE_METHOD = new JMethod(Opcodes.ACC_PUBLIC, "getHandle", "()Ljavax/ejb/Handle;", null,
new String[] {"java/rmi/RemoteException"});
/**
* Signature of the getHandle method.
*/
private static final JMethod GETPRIMARYKEY_METHOD = new JMethod(Opcodes.ACC_PUBLIC, "getPrimaryKey", "()Ljava/lang/Object;",
null, null);
/**
* Helper class, no public constructor.
*/
private EJB21Finder() {
}
/**
* Finds business method in a session bean.
* @param bean the bean to analyze
*/
public static void resolve(final EasyBeansEjbJarClassMetadata bean) {
// Home and RemoteHome on the bean ?
String remoteHome = bean.getRemoteHome();
String localHome = bean.getLocalHome();
// First, check if there is a home or local home interface (else do
// nothing)
if (remoteHome == null && localHome == null) {
return;
}
// EJB-JAR
EjbJarArchiveMetadata ejbJarAnnotationMetadata = bean.getEjbJarDeployableMetadata();
// List of interfaces found in remote home interfaces.
List<String> interfacesList = new ArrayList<String>();
// Get List of Interfaces from remote home
if (remoteHome != null) {
getInterfacesFromHome(remoteHome, interfacesList, ejbJarAnnotationMetadata);
}
// Get List of Interfaces from Local home
if (localHome != null) {
getInterfacesFromHome(localHome, interfacesList, ejbJarAnnotationMetadata);
}
// And then, set business method found in the createXXX() methods in
// home interfaces
for (String itf : interfacesList) {
// Get metadata of this interface
EasyBeansEjbJarClassMetadata interfaceUsed = bean.getLinkedClassMetadata(itf);
if (interfaceUsed == null) {
throw new IllegalStateException("Cannot find the metadata for the class '" + itf
+ "' referenced in the home/localhome of the bean '" + bean.getClassName() + "'.");
}
// Get all methods
for (EasyBeansEjbJarMethodMetadata methodData : interfaceUsed.getMethodMetadataCollection()) {
JMethod itfMethod = methodData.getJMethod();
// Ignore class init method
if (itfMethod.getName().equals(BusinessMethodResolver.CLASS_INIT)
|| itfMethod.getName().equals(BusinessMethodResolver.CONST_INIT)) {
continue;
}
// take the method from the bean class
EasyBeansEjbJarMethodMetadata beanMethod = bean.getMethodMetadata(itfMethod);
if (beanMethod == null) {
throw new IllegalStateException("No method was found for method " + itfMethod + " in class "
+ bean.getClassName());
}
beanMethod.setBusinessMethod(true);
}
}
// Add remove method
EasyBeansEjbJarMethodMetadata metadataRemove = bean.getMethodMetadata(REMOVE_METHOD);
// not present ? add it
if (metadataRemove == null) {
metadataRemove = new EasyBeansEjbJarMethodMetadata(REMOVE_METHOD, bean);
bean.addStandardMethodMetadata(metadataRemove);
}
// flag method as a remove method
metadataRemove.setRemove(new JRemove());
metadataRemove.setBusinessMethod(true);
// Flag ejbXXX() method as business method (so interceptors are invoked)
for (EasyBeansEjbJarMethodMetadata methodData : bean.getMethodMetadataCollection()) {
JMethod method = methodData.getJMethod();
if (method.getName().startsWith("ejbActivate") || method.getName().startsWith("ejbCreate")) {
if ("()V".equals(method.getDescriptor())) {
methodData.setBusinessMethod(true);
}
}
}
// Add isIdentical on EJBObject and EJBLocalObject
bean.addStandardMethodMetadata(new EasyBeansEjbJarMethodMetadata(ISIDENTICAL_METHOD, bean));
bean.addStandardMethodMetadata(new EasyBeansEjbJarMethodMetadata(ISIDENTICAL_LOCAL_METHOD, bean));
// GetHandle
bean.addStandardMethodMetadata(new EasyBeansEjbJarMethodMetadata(GETHANDLE_METHOD, bean));
// GetPrimaryKey
bean.addStandardMethodMetadata(new EasyBeansEjbJarMethodMetadata(GETPRIMARYKEY_METHOD, bean));
}
/**
* Found interfaces specified on return type of the createXXX() method and
* add them in the given list.
* @param home the name of the class to analyze.
* @param interfacesList the given list where to add interfaces found
* @param ejbJarAnnotationMetadata the metatada where to get metadata
*/
private static void getInterfacesFromHome(final String home, final List<String> interfacesList,
final EjbJarArchiveMetadata ejbJarAnnotationMetadata) {
String encodedname = home.replace(".", "/");
// Get metadata of the given home interface
EasyBeansEjbJarClassMetadata homeMetadata = ejbJarAnnotationMetadata.getScannedClassMetadata(encodedname);
if (homeMetadata == null) {
throw new IllegalStateException("Cannot find the class '" + home
+ "' referenced as an home/localhome interface");
}
// Get methods
for (EasyBeansEjbJarMethodMetadata method : homeMetadata.getMethodMetadataCollection()) {
// if method name begins with "create", it's matching
if (method.getMethodName().startsWith("create")) {
// Get return type
JMethod jMethod = method.getJMethod();
Type returnType = Type.getReturnType(jMethod.getDescriptor());
String returnTypeClassname = returnType.getClassName();
// Not yet present in the list ? add it
if (!interfacesList.contains(returnTypeClassname)) {
interfacesList.add(returnTypeClassname.replace(".", "/"));
}
}
}
// Parent is not EJBHome or EJBLocalHome then loop again on the super
// name
String[] interfaces = homeMetadata.getInterfaces();
if (interfaces != null) {
for (String itf : interfaces) {
if (!"javax/ejb/EJBHome".equals(itf) && !"javax/ejb/EJBLocalHome".equals(itf)) {
getInterfacesFromHome(itf, interfacesList, ejbJarAnnotationMetadata);
}
}
}
}
}