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: InterceptorManagerGenerator.java 2057 2007-11-21 15:35:32Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.enhancer.interceptors;
025:
026: import java.util.List;
027:
028: import org.ow2.easybeans.asm.ClassWriter;
029: import org.ow2.easybeans.asm.MethodVisitor;
030: import org.ow2.easybeans.asm.Type;
031: import org.ow2.easybeans.api.Factory;
032: import org.ow2.easybeans.api.container.EZBEJBContext;
033: import org.ow2.easybeans.deployment.annotations.metadata.EjbJarAnnotationMetadata;
034: import org.ow2.easybeans.enhancer.CommonClassGenerator;
035:
036: /**
037: * This generates a class that manage the interceptor of a given bean. It
038: * manages the lifecycle of the interceptors and allow to inject resources
039: * (dependency injection).
040: * @author Florent Benoit
041: */
042: public class InterceptorManagerGenerator extends CommonClassGenerator {
043:
044: /**
045: * Metadata to retrieve info on interceptors.
046: */
047: private EjbJarAnnotationMetadata ejbJarAnnotationMetadata = null;
048:
049: /**
050: * Name of the class to generate.
051: */
052: private String generatedClassName = null;
053:
054: /**
055: * List of interceptors classes that are managed.
056: */
057: private List<String> allInterceptors = null;
058:
059: /**
060: * Interface of this invocation context.
061: */
062: public static final String[] INTERFACES = new String[] { "org/ow2/easybeans/api/injection/EasyBeansInjection" };
063:
064: /**
065: * EZBEJBContext type descriptor.
066: */
067: private static final String EZB_EJBCONTEXT_DESC = Type
068: .getDescriptor(EZBEJBContext.class);
069:
070: /**
071: * Constructor.
072: * @param ejbJarAnnotationMetadata the metadata to search interceptor class metadata.
073: * @param generatedClassName the name of the class to generate.
074: * @param allInterceptors interceptors that needs to be managed.
075: */
076: public InterceptorManagerGenerator(
077: final EjbJarAnnotationMetadata ejbJarAnnotationMetadata,
078: final String generatedClassName,
079: final List<String> allInterceptors) {
080: super (new ClassWriter(ClassWriter.COMPUTE_MAXS));
081: this .ejbJarAnnotationMetadata = ejbJarAnnotationMetadata;
082: this .generatedClassName = generatedClassName;
083: this .allInterceptors = allInterceptors;
084: }
085:
086: /**
087: * Generates the class. It call sub methods for being more clear for read
088: * the code
089: */
090: public void generate() {
091: addClassDeclaration();
092: addAttributes();
093: addConstructor();
094: addMethods();
095: endClass();
096: }
097:
098: /**
099: * Creates the declaration of the class with the given interfaces.
100: */
101: private void addClassDeclaration() {
102: // create class
103: getCW().visit(GENERATED_CLASS_VERSION, ACC_PUBLIC + ACC_SUPER,
104: generatedClassName, null, "java/lang/Object",
105: INTERFACES);
106: }
107:
108: /**
109: * Add attributes of the class. Attributes are interceptors names. ie :
110: * private Interceptor interceptor;
111: */
112: private void addAttributes() {
113: for (String interceptor : allInterceptors) {
114: String fieldName = getField(interceptor);
115: addAttribute(ACC_PRIVATE, fieldName,
116: encodeClassDesc(interceptor));
117: }
118: }
119:
120: /**
121: * Gets the field name for a given interceptor.
122: * @param interceptorClass the given interceptor.
123: * @return a field name.
124: */
125: private static String getField(final String interceptorClass) {
126: return interceptorClass.replace("/", "");
127: }
128:
129: /**
130: * Gets the getter method name for a given interceptor.
131: * @param interceptorClass the given interceptor.
132: * @return a getter method name.
133: */
134: private static String getMethod(final String interceptorClass) {
135: return "get" + interceptorClass.replace("/", "");
136: }
137:
138: /**
139: * Creates the constructor which should look like.
140: *
141: * <pre>
142: * public XXXInterceptorManager() {
143: * this.interceptor = new Interceptor();
144: * this.interceptor2 = new Interceptor2();
145: * }
146: * </pre>
147: */
148: private void addConstructor() {
149: // Generate constructor
150: MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC, "<init>",
151: "()V", null, null);
152: mv.visitCode();
153:
154: // Call super constructor
155: mv.visitVarInsn(ALOAD, 0);
156: mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>",
157: "()V");
158:
159: // Build instance of interceptors
160: for (String interceptor : allInterceptors) {
161: mv.visitVarInsn(ALOAD, 0);
162: mv.visitTypeInsn(NEW, interceptor);
163: mv.visitInsn(DUP);
164: mv.visitMethodInsn(INVOKESPECIAL, interceptor, "<init>",
165: "()V");
166: mv
167: .visitFieldInsn(PUTFIELD, generatedClassName,
168: getField(interceptor),
169: encodeClassDesc(interceptor));
170: }
171:
172: // need to add return instruction
173: mv.visitInsn(RETURN);
174:
175: // visit max compute automatically
176: mv.visitMaxs(0, 0);
177: mv.visitEnd();
178: }
179:
180: /**
181: * Add methods of the class.
182: */
183: private void addMethods() {
184: addGetterMethods();
185: addInjectedMethod();
186: addDefaultMethods();
187: }
188:
189: /**
190: * Generated methods allowing to set a context and a factory. This allows to
191: * set on injectors the bean's session context and its factory.
192: */
193: private void addDefaultMethods() {
194: // Adds the factory attribute and its getter/setter.
195: CommonClassGenerator.addFieldGettersSetters(getCW(),
196: generatedClassName, "easyBeansFactory", Factory.class);
197:
198: // Adds the sessionContext attribute and its getter/setter.
199: CommonClassGenerator.addFieldGettersSetters(getCW(),
200: generatedClassName, "easyBeansContext",
201: EZBEJBContext.class);
202: }
203:
204: /**
205: * Generates a getter method for each interceptor. ie :
206: *
207: * <pre>
208: * public Interceptor getInterceptor() {
209: * return interceptor;
210: * }
211: * </pre>
212: */
213: private void addGetterMethods() {
214: for (String interceptor : allInterceptors) {
215: MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC,
216: getMethod(interceptor),
217: "()" + encodeClassDesc(interceptor), null, null);
218: mv.visitCode();
219: mv.visitVarInsn(ALOAD, 0);
220: mv
221: .visitFieldInsn(GETFIELD, generatedClassName,
222: getField(interceptor),
223: encodeClassDesc(interceptor));
224: mv.visitInsn(ARETURN);
225: mv.visitMaxs(0, 0);
226: mv.visitEnd();
227: }
228: }
229:
230: /**
231: * For each interceptor, call injectedByEasyBeans on it (only if these
232: * interceptors have been analyzed).
233: *
234: * <pre>
235: * public void injectedByEasyBeans() {
236: * interceptorXX.setEasyBeansContext(easyBeansContext);
237: * interceptorXX.injectedByEasyBeans();
238: * interceptorXX.injectedByEasyBeans();
239: * }
240: * </pre>
241: */
242: private void addInjectedMethod() {
243: MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC,
244: "injectedByEasyBeans", "()V", null, null);
245: mv.visitCode();
246:
247: for (String interceptor : allInterceptors) {
248: // if interceptor has been analyzed, call injectedByEasyBeans method
249: // Set also the bean's context and its factory.
250: if (ejbJarAnnotationMetadata
251: .getClassAnnotationMetadata(interceptor) != null) {
252: String fieldName = getField(interceptor);
253:
254: // interceptor.setEasyBeansContext(easyBeansContext);
255: mv.visitVarInsn(ALOAD, 0);
256: mv.visitFieldInsn(GETFIELD, generatedClassName,
257: fieldName, encodeClassDesc(interceptor));
258: mv.visitVarInsn(ALOAD, 0);
259: mv.visitFieldInsn(GETFIELD, generatedClassName,
260: "easyBeansContext", EZB_EJBCONTEXT_DESC);
261: mv.visitMethodInsn(INVOKEVIRTUAL, interceptor,
262: "setEasyBeansContext", "("
263: + EZB_EJBCONTEXT_DESC + ")V");
264:
265: // interceptorXX.injectedByEasyBeans();
266: mv.visitVarInsn(ALOAD, 0);
267: mv.visitFieldInsn(GETFIELD, generatedClassName,
268: fieldName, encodeClassDesc(interceptor));
269: mv.visitMethodInsn(INVOKEVIRTUAL, interceptor,
270: "injectedByEasyBeans", "()V");
271: }
272: }
273: mv.visitInsn(RETURN);
274: mv.visitMaxs(0, 0);
275: mv.visitEnd();
276: }
277:
278: /**
279: * Called when the generated class is done.
280: */
281: private void endClass() {
282: getCW().visitEnd();
283: }
284:
285: /**
286: * @return the bytecode of the generated class.
287: */
288: public byte[] getBytes() {
289: return getCW().toByteArray();
290: }
291:
292: }
|