001: /**
002: * EasyBeans
003: * Copyright (C) 2006 Bull S.A.S.
004: * Contact: easybeans@ow2.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: EJB21Finder.java 2057 2007-11-21 15:35:32Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.deployment.annotations.helper.bean;
025:
026: import java.util.ArrayList;
027: import java.util.List;
028:
029: import org.ow2.easybeans.asm.Opcodes;
030: import org.ow2.easybeans.asm.Type;
031: import org.ow2.easybeans.deployment.annotations.JMethod;
032: import org.ow2.easybeans.deployment.annotations.impl.JRemove;
033: import org.ow2.easybeans.deployment.annotations.metadata.ClassAnnotationMetadata;
034: import org.ow2.easybeans.deployment.annotations.metadata.EjbJarAnnotationMetadata;
035: import org.ow2.easybeans.deployment.annotations.metadata.MethodAnnotationMetadata;
036:
037: /**
038: * This class finds the business interface that are used as return type in the
039: * Home or LocalHome interface of the Bean.
040: * @author Florent Benoit
041: */
042: public final class EJB21Finder {
043:
044: /**
045: * Signature of the remove method.
046: */
047: private static final JMethod REMOVE_METHOD = new JMethod(
048: Opcodes.ACC_PUBLIC, "remove", "()V", null,
049: new String[] { "javax/ejb/RemoveException" });
050:
051: /**
052: * Signature of the isIdentical(EJBObject) method.
053: */
054: private static final JMethod ISIDENTICAL_METHOD = new JMethod(
055: Opcodes.ACC_PUBLIC, "isIdentical",
056: "(Ljavax/ejb/EJBObject;)Z", null,
057: new String[] { "java/rmi/RemoteException" });
058:
059: /**
060: * Signature of the isIdentical(EJBLocalObject) method.
061: */
062: private static final JMethod ISIDENTICAL_LOCAL_METHOD = new JMethod(
063: Opcodes.ACC_PUBLIC, "isIdentical",
064: "(Ljavax/ejb/EJBLocalObject;)Z", null,
065: new String[] { "javax/ejb/EJBException" });
066:
067: /**
068: * Signature of the getHandle method.
069: */
070: private static final JMethod GETHANDLE_METHOD = new JMethod(
071: Opcodes.ACC_PUBLIC, "getHandle", "()Ljavax/ejb/Handle;",
072: null, new String[] { "java/rmi/RemoteException" });
073:
074: /**
075: * Signature of the getHandle method.
076: */
077: private static final JMethod GETPRIMARYKEY_METHOD = new JMethod(
078: Opcodes.ACC_PUBLIC, "getPrimaryKey",
079: "()Ljava/lang/Object;", null, null);
080:
081: /**
082: * Helper class, no public constructor.
083: */
084: private EJB21Finder() {
085: }
086:
087: /**
088: * Finds business method in a session bean.
089: * @param bean the bean to analyze
090: */
091: public static void resolve(final ClassAnnotationMetadata bean) {
092: // Home and RemoteHome on the bean ?
093: String remoteHome = bean.getRemoteHome();
094: String localHome = bean.getLocalHome();
095:
096: // First, check if there is a home or local home interface (else do
097: // nothing)
098: if (remoteHome == null && localHome == null) {
099: return;
100: }
101:
102: // EJB-JAR
103: EjbJarAnnotationMetadata ejbJarAnnotationMetadata = bean
104: .getEjbJarAnnotationMetadata();
105: // List of interfaces found in remote home interfaces.
106: List<String> interfacesList = new ArrayList<String>();
107:
108: // Get List of Interfaces from remote home
109: if (remoteHome != null) {
110: getInterfacesFromHome(remoteHome, interfacesList,
111: ejbJarAnnotationMetadata);
112: }
113:
114: // Get List of Interfaces from Local home
115: if (localHome != null) {
116: getInterfacesFromHome(localHome, interfacesList,
117: ejbJarAnnotationMetadata);
118: }
119:
120: // And then, set business method found in the createXXX() methods in
121: // home interfaces
122: for (String itf : interfacesList) {
123: // Get metadata of this interface
124: ClassAnnotationMetadata interfaceUsed = ejbJarAnnotationMetadata
125: .getClassAnnotationMetadata(itf);
126: if (interfaceUsed == null) {
127: throw new IllegalStateException(
128: "Cannot find the metadata for the class '"
129: + itf
130: + "' referenced in the home/localhome of the bean '"
131: + bean.getClassName() + "'.");
132: }
133:
134: // Get all methods
135: for (MethodAnnotationMetadata methodData : interfaceUsed
136: .getMethodAnnotationMetadataCollection()) {
137: JMethod itfMethod = methodData.getJMethod();
138:
139: // Ignore class init method
140: if (itfMethod.getName().equals(
141: BusinessMethodResolver.CLASS_INIT)
142: || itfMethod.getName().equals(
143: BusinessMethodResolver.CONST_INIT)) {
144: continue;
145: }
146:
147: // take the method from the bean class
148: MethodAnnotationMetadata beanMethod = bean
149: .getMethodAnnotationMetadata(itfMethod);
150: if (beanMethod == null) {
151: throw new IllegalStateException(
152: "No method was found for method "
153: + itfMethod + " in class "
154: + bean.getClassName());
155: }
156: beanMethod.setBusinessMethod(true);
157: }
158:
159: }
160:
161: // Add remove method
162: MethodAnnotationMetadata metadataRemove = bean
163: .getMethodAnnotationMetadata(REMOVE_METHOD);
164: // not present ? add it
165: if (metadataRemove == null) {
166: metadataRemove = new MethodAnnotationMetadata(
167: REMOVE_METHOD, bean);
168: bean.addMethodAnnotationMetadata(metadataRemove);
169: }
170:
171: // flag method as a remove method
172: metadataRemove.setRemove(new JRemove());
173: metadataRemove.setBusinessMethod(true);
174:
175: // Add isIdentical on EJBObject and EJBLocalObject
176: bean.addMethodAnnotationMetadata(new MethodAnnotationMetadata(
177: ISIDENTICAL_METHOD, bean));
178: bean.addMethodAnnotationMetadata(new MethodAnnotationMetadata(
179: ISIDENTICAL_LOCAL_METHOD, bean));
180:
181: // GetHandle
182: bean.addMethodAnnotationMetadata(new MethodAnnotationMetadata(
183: GETHANDLE_METHOD, bean));
184:
185: // GetPrimaryKey
186: bean.addMethodAnnotationMetadata(new MethodAnnotationMetadata(
187: GETPRIMARYKEY_METHOD, bean));
188:
189: }
190:
191: /**
192: * Found interfaces specified on return type of the createXXX() method and
193: * add them in the given list.
194: * @param home the name of the class to analyze.
195: * @param interfacesList the given list where to add interfaces found
196: * @param ejbJarAnnotationMetadata the metatada where to get metadata
197: */
198: private static void getInterfacesFromHome(final String home,
199: final List<String> interfacesList,
200: final EjbJarAnnotationMetadata ejbJarAnnotationMetadata) {
201:
202: String encodedname = home.replace(".", "/");
203:
204: // Get metadata of the given home interface
205: ClassAnnotationMetadata homeMetadata = ejbJarAnnotationMetadata
206: .getClassAnnotationMetadata(encodedname);
207: if (homeMetadata == null) {
208: throw new IllegalStateException("Cannot find the class '"
209: + home
210: + "' referenced as an home/localhome interface");
211: }
212:
213: // Get methods
214: for (MethodAnnotationMetadata method : homeMetadata
215: .getMethodAnnotationMetadataCollection()) {
216: // if method name begins with "create", it's matching
217: if (method.getMethodName().startsWith("create")) {
218: // Get return type
219: JMethod jMethod = method.getJMethod();
220: Type returnType = Type.getReturnType(jMethod
221: .getDescriptor());
222: String returnTypeClassname = returnType.getClassName();
223: // Not yet present in the list ? add it
224: if (!interfacesList.contains(returnTypeClassname)) {
225: interfacesList.add(returnTypeClassname.replace(".",
226: "/"));
227: }
228: }
229: }
230:
231: // Parent is not EJBHome or EJBLocalHome then loop again on the super
232: // name
233: String[] interfaces = homeMetadata.getInterfaces();
234: if (interfaces != null) {
235: for (String itf : interfaces) {
236: if (!"javax/ejb/EJBHome".equals(itf)
237: && !"javax/ejb/EJBLocalHome".equals(itf)) {
238: getInterfacesFromHome(itf, interfacesList,
239: ejbJarAnnotationMetadata);
240: }
241: }
242: }
243: }
244: }
|