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: Migration21ClassAdapter.java 2057 2007-11-21 15:35:32Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.enhancer.bean;
025:
026: import org.ow2.easybeans.asm.ClassAdapter;
027: import org.ow2.easybeans.asm.ClassVisitor;
028: import org.ow2.easybeans.asm.Label;
029: import org.ow2.easybeans.asm.MethodVisitor;
030: import org.ow2.easybeans.asm.Opcodes;
031: import org.ow2.easybeans.deployment.annotations.metadata.ClassAnnotationMetadata;
032:
033: /**
034: * This adapter is used to add the EJB 2.1 methods that are required for the
035: * EJBObject or EJBLocalObject interfaces.
036: * @author Florent Benoit
037: */
038: public class Migration21ClassAdapter extends ClassAdapter implements
039: Opcodes {
040:
041: /**
042: * Metadata available by this adapter for a class.
043: */
044: private ClassAnnotationMetadata classAnnotationMetadata = null;
045:
046: /**
047: * Remove method has been implemented ?
048: */
049: private boolean addRemoveMethod = true;
050:
051: /**
052: * Constant = 1.
053: */
054: private static final int ONE = 1;
055:
056: /**
057: * Constant = 2.
058: */
059: private static final int TWO = 2;
060:
061: /**
062: * Constant = 3.
063: */
064: private static final int THREE = 3;
065:
066: /**
067: * Constant = 4.
068: */
069: private static final int FOUR = 4;
070:
071: /**
072: * Constant = 5.
073: */
074: private static final int FIVE = 5;
075:
076: /**
077: * Constructor.
078: * @param classAnnotationMetadata object containing all attributes of the
079: * class
080: * @param cv the class visitor to which this adapter must delegate calls.
081: */
082: public Migration21ClassAdapter(
083: final ClassAnnotationMetadata classAnnotationMetadata,
084: final ClassVisitor cv) {
085: super (cv);
086: this .classAnnotationMetadata = classAnnotationMetadata;
087: }
088:
089: /**
090: * Visits a method of the class. This method <i>must</i> return a new
091: * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is
092: * called, i.e., it should not return a previously returned visitor.
093: * @param access the method's access flags (see {@link Opcodes}). This
094: * parameter also indicates if the method is synthetic and/or
095: * deprecated.
096: * @param name the method's name.
097: * @param desc the method's descriptor (see {@link org.ow2.easybeans.asm.Type Type}).
098: * @param signature the method's signature. May be <tt>null</tt> if the
099: * method parameters, return type and exceptions do not use generic
100: * types.
101: * @param exceptions the internal names of the method's exception classes
102: * (see {@link org.ow2.easybeans.asm.Type#getInternalName() getInternalName}). May be
103: * <tt>null</tt>.
104: * @return an object to visit the byte code of the method, or <tt>null</tt>
105: * if this class visitor is not interested in visiting the code of
106: * this method.
107: */
108: @Override
109: public MethodVisitor visitMethod(final int access,
110: final String name, final String desc,
111: final String signature, final String[] exceptions) {
112:
113: // Check if remove method is implemented by the user or not ?
114: if ("remove".equals(name)) {
115: addRemoveMethod = false;
116: }
117:
118: // go to the default case
119: return super .visitMethod(access, name, desc, signature,
120: exceptions);
121: }
122:
123: /**
124: * Visits the end of the class. This method, which is the last one to be
125: * called, is used to inform the visitor that all the fields and methods of
126: * the class have been visited.
127: */
128: @Override
129: public void visitEnd() {
130: // generate methods that are required for EJBObject/EJBLocalObject.
131: if (addRemoveMethod) {
132: addRemoveMethod();
133: }
134:
135: // Add identical method for both EJBObject and EJBLocalObject
136: addIsIdentitalMethods();
137:
138: // add getHandle method (which can't be use internally)
139: addGetHandleMethod();
140:
141: // add the get primary key method which throw exceptions
142: addGetPrimaryKey();
143:
144: super .visitEnd();
145:
146: }
147:
148: /**
149: * Add en empty remove method. This method has been flagged as a
150: * remove/business method. Then, when this method is called, the bean is
151: * destroyed.
152: */
153: private void addRemoveMethod() {
154: MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "remove", "()V",
155: null, new String[] { "javax/ejb/RemoveException" });
156: mv.visitCode();
157: mv.visitInsn(RETURN);
158: mv.visitMaxs(0, 0);
159: mv.visitEnd();
160: }
161:
162: /**
163: * Add the getPrimaryKey() method. It always throw exceptions as it is
164: * intented to be used by session beans.
165: */
166: private void addGetPrimaryKey() {
167: // Add the following:
168: // public Object getPrimaryKey() {
169: // throw new EJBException("No primary key on session beans");
170: // }
171:
172: MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "getPrimaryKey",
173: "()Ljava/lang/Object;", null, null);
174: mv.visitCode();
175: mv.visitTypeInsn(NEW, "javax/ejb/EJBException");
176: mv.visitInsn(DUP);
177: mv.visitLdcInsn("No primary key on session beans");
178: mv.visitMethodInsn(INVOKESPECIAL, "javax/ejb/EJBException",
179: "<init>", "(Ljava/lang/String;)V");
180: mv.visitInsn(ATHROW);
181: mv.visitMaxs(0, 0);
182: mv.visitEnd();
183: }
184:
185: /**
186: * Add the internal getHandle method. This method do nothing. The proxy
187: * client is handling this method.
188: */
189: private void addGetHandleMethod() {
190: // Add the following:
191: // public Handle getHandle() throws RemoteException {
192: // throw new RemoteException(
193: // "This method should be called on the remote object and not locally.
194: // It is only available as a client view.");
195: // }
196:
197: MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "getHandle",
198: "()Ljavax/ejb/Handle;", null,
199: new String[] { "java/rmi/RemoteException" });
200: mv.visitCode();
201: mv.visitTypeInsn(NEW, "java/rmi/RemoteException");
202: mv.visitInsn(DUP);
203: mv
204: .visitLdcInsn("This method should be called on the remote object and not locally."
205: + "It is only available as a client view.");
206: mv.visitMethodInsn(INVOKESPECIAL, "java/rmi/RemoteException",
207: "<init>", "(Ljava/lang/String;)V");
208: mv.visitInsn(ATHROW);
209: mv.visitMaxs(0, 0);
210: mv.visitEnd();
211:
212: }
213:
214: /**
215: * Add the two methods (one fo EJBObject and the other for EJBLocalObject).
216: * These methods handle the equality of beans.
217: */
218: private void addIsIdentitalMethods() {
219: addIsIdentitalEJBObject();
220: addIsIdentitalEJBLocalObject();
221: }
222:
223: /**
224: * Add the method for EJBLocalObject equality.
225: */
226: private void addIsIdentitalEJBLocalObject() {
227: // add the following code:
228: // public boolean isIdentical(EJBLocalObject obj) throws EJBException {
229: // // false if other object is null
230: // if (obj == null) {
231: // return false;
232: // }
233: //
234: // // Gets the handler
235: // InvocationHandler handler = Proxy.getInvocationHandler(obj);
236: // LocalCallInvocationHandler localHandler = null;
237: // if (handler instanceof LocalCallInvocationHandler) {
238: // localHandler = (LocalCallInvocationHandler) handler;
239: // } else {
240: // return false;
241: // }
242: //
243: // // get the other factory name
244: // String otherFactoryName = localHandler.getFactoryName();
245: //
246: // // for stateless, compare only the class
247: // if (getEasyBeansFactory() instanceof StatelessSessionFactory) {
248: // return getEasyBeansFactory().getClassName()
249: // .equals(otherFactoryName);
250: // } else if (getEasyBeansFactory() instanceof StatefulSessionFactory) {
251: // // compare class and ID
252: // Long otherId = localHandler.getBeanId();
253: // return getEasyBeansFactory().getClassName()
254: // .equals(otherFactoryName)
255: // && getEasyBeansStatefulID().equals(otherId);
256: // } else {
257: // return false;
258: // }
259: // }
260:
261: MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "isIdentical",
262: "(Ljavax/ejb/EJBLocalObject;)Z", null,
263: new String[] { "javax/ejb/EJBException" });
264: mv.visitCode();
265: Label l0 = new Label();
266: mv.visitLabel(l0);
267: mv.visitVarInsn(ALOAD, ONE);
268: Label l1 = new Label();
269: mv.visitJumpInsn(IFNONNULL, l1);
270: Label l2 = new Label();
271: mv.visitLabel(l2);
272: mv.visitInsn(ICONST_0);
273: mv.visitInsn(IRETURN);
274: mv.visitLabel(l1);
275: mv.visitVarInsn(ALOAD, ONE);
276: mv
277: .visitMethodInsn(INVOKESTATIC,
278: "java/lang/reflect/Proxy",
279: "getInvocationHandler",
280: "(Ljava/lang/Object;)Ljava/lang/reflect/InvocationHandler;");
281: mv.visitVarInsn(ASTORE, TWO);
282: Label l3 = new Label();
283: mv.visitLabel(l3);
284: mv.visitInsn(ACONST_NULL);
285: mv.visitVarInsn(ASTORE, THREE);
286: Label l4 = new Label();
287: mv.visitLabel(l4);
288: mv.visitVarInsn(ALOAD, TWO);
289: mv.visitTypeInsn(INSTANCEOF,
290: "org/ow2/easybeans/rpc/LocalCallInvocationHandler");
291: Label l5 = new Label();
292: mv.visitJumpInsn(IFEQ, l5);
293: Label l6 = new Label();
294: mv.visitLabel(l6);
295: mv.visitVarInsn(ALOAD, TWO);
296: mv.visitTypeInsn(CHECKCAST,
297: "org/ow2/easybeans/rpc/LocalCallInvocationHandler");
298: mv.visitVarInsn(ASTORE, THREE);
299: Label l7 = new Label();
300: mv.visitJumpInsn(GOTO, l7);
301: mv.visitLabel(l5);
302: mv.visitInsn(ICONST_0);
303: mv.visitInsn(IRETURN);
304: mv.visitLabel(l7);
305: mv.visitVarInsn(ALOAD, THREE);
306: mv.visitMethodInsn(INVOKEVIRTUAL,
307: "org/ow2/easybeans/rpc/LocalCallInvocationHandler",
308: "getFactoryName", "()Ljava/lang/String;");
309: mv.visitVarInsn(ASTORE, FOUR);
310: Label l8 = new Label();
311: mv.visitLabel(l8);
312: mv.visitVarInsn(ALOAD, 0);
313: mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata
314: .getClassName(), "getEasyBeansFactory",
315: "()Lorg/ow2/easybeans/api/Factory;");
316: mv
317: .visitTypeInsn(INSTANCEOF,
318: "org/ow2/easybeans/container/session/stateless/StatelessSessionFactory");
319: Label l9 = new Label();
320: mv.visitJumpInsn(IFEQ, l9);
321: Label l10 = new Label();
322: mv.visitLabel(l10);
323: mv.visitVarInsn(ALOAD, 0);
324: mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata
325: .getClassName(), "getEasyBeansFactory",
326: "()Lorg/ow2/easybeans/api/Factory;");
327: mv.visitMethodInsn(INVOKEINTERFACE,
328: "org/ow2/easybeans/api/Factory", "getClassName",
329: "()Ljava/lang/String;");
330: Label l11 = new Label();
331: mv.visitLabel(l11);
332: mv.visitVarInsn(ALOAD, FOUR);
333: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals",
334: "(Ljava/lang/Object;)Z");
335: Label l12 = new Label();
336: mv.visitLabel(l12);
337: mv.visitInsn(IRETURN);
338: mv.visitLabel(l9);
339: mv.visitVarInsn(ALOAD, 0);
340: mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata
341: .getClassName(), "getEasyBeansFactory",
342: "()Lorg/ow2/easybeans/api/Factory;");
343: mv
344: .visitTypeInsn(INSTANCEOF,
345: "org/ow2/easybeans/container/session/stateful/StatefulSessionFactory");
346: Label l13 = new Label();
347: mv.visitJumpInsn(IFEQ, l13);
348: Label l14 = new Label();
349: mv.visitLabel(l14);
350: mv.visitVarInsn(ALOAD, THREE);
351: mv.visitMethodInsn(INVOKEVIRTUAL,
352: "org/ow2/easybeans/rpc/LocalCallInvocationHandler",
353: "getBeanId", "()Ljava/lang/Long;");
354: mv.visitVarInsn(ASTORE, FIVE);
355: Label l15 = new Label();
356: mv.visitLabel(l15);
357: mv.visitVarInsn(ALOAD, 0);
358: mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata
359: .getClassName(), "getEasyBeansFactory",
360: "()Lorg/ow2/easybeans/api/Factory;");
361: mv.visitMethodInsn(INVOKEINTERFACE,
362: "org/ow2/easybeans/api/Factory", "getClassName",
363: "()Ljava/lang/String;");
364: Label l16 = new Label();
365: mv.visitLabel(l16);
366: mv.visitVarInsn(ALOAD, FOUR);
367: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals",
368: "(Ljava/lang/Object;)Z");
369: Label l17 = new Label();
370: mv.visitJumpInsn(IFEQ, l17);
371: Label l18 = new Label();
372: mv.visitLabel(l18);
373: mv.visitVarInsn(ALOAD, 0);
374: mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata
375: .getClassName(), "getEasyBeansStatefulID",
376: "()Ljava/lang/Long;");
377: mv.visitVarInsn(ALOAD, FIVE);
378: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "equals",
379: "(Ljava/lang/Object;)Z");
380: mv.visitJumpInsn(IFEQ, l17);
381: mv.visitInsn(ICONST_1);
382: mv.visitInsn(IRETURN);
383: mv.visitLabel(l17);
384: mv.visitInsn(ICONST_0);
385: Label l19 = new Label();
386: mv.visitLabel(l19);
387: mv.visitInsn(IRETURN);
388: mv.visitLabel(l13);
389: mv.visitInsn(ICONST_0);
390: mv.visitInsn(IRETURN);
391: mv.visitMaxs(0, 0);
392: mv.visitEnd();
393: }
394:
395: /**
396: * Add the method for EJBObject equality.
397: */
398: private void addIsIdentitalEJBObject() {
399: // code for EJBObject
400: // public boolean isIdentical(EJBObject obj) throws RemoteException {
401: // // false if other object is null
402: // if (obj == null) {
403: // return false;
404: // }
405: //
406: // // Gets the handler
407: // InvocationHandler handler = Proxy.getInvocationHandler(obj);
408: // ClientRPCInvocationHandler clientHandler = null;
409: // if (handler instanceof ClientRPCInvocationHandler) {
410: // clientHandler = (ClientRPCInvocationHandler) handler;
411: // } else {
412: // return false;
413: // }
414: //
415: // // get the other factory name
416: // String otherFactoryName = clientHandler.getFactoryName();
417: //
418: // // for stateless, compare only the class
419: // if (getEasyBeansFactory() instanceof StatelessSessionFactory) {
420: // return getEasyBeansFactory().getClassName()
421: // .equals(otherFactoryName);
422: // } else if (getEasyBeansFactory() instanceof StatefulSessionFactory) {
423: // // compare class and ID
424: // Long otherId = clientHandler.getBeanId();
425: // return getEasyBeansFactory().getClassName()
426: // .equals(otherFactoryName)
427: // && getEasyBeansStatefulID().equals(otherId);
428: // } else {
429: // return false;
430: // }
431: // }
432:
433: MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "isIdentical",
434: "(Ljavax/ejb/EJBObject;)Z", null,
435: new String[] { "java/rmi/RemoteException" });
436: mv.visitCode();
437: Label l0 = new Label();
438: mv.visitLabel(l0);
439: mv.visitVarInsn(ALOAD, 1);
440: Label l1 = new Label();
441: mv.visitJumpInsn(IFNONNULL, l1);
442: Label l2 = new Label();
443: mv.visitLabel(l2);
444: mv.visitInsn(ICONST_0);
445: mv.visitInsn(IRETURN);
446: mv.visitLabel(l1);
447: mv.visitVarInsn(ALOAD, 1);
448: mv
449: .visitMethodInsn(INVOKESTATIC,
450: "java/lang/reflect/Proxy",
451: "getInvocationHandler",
452: "(Ljava/lang/Object;)Ljava/lang/reflect/InvocationHandler;");
453: mv.visitVarInsn(ASTORE, 2);
454: Label l3 = new Label();
455: mv.visitLabel(l3);
456: mv.visitInsn(ACONST_NULL);
457: mv.visitVarInsn(ASTORE, THREE);
458: Label l4 = new Label();
459: mv.visitLabel(l4);
460: mv.visitVarInsn(ALOAD, TWO);
461: mv.visitTypeInsn(INSTANCEOF,
462: "org/ow2/easybeans/rpc/ClientRPCInvocationHandler");
463: Label l5 = new Label();
464: mv.visitJumpInsn(IFEQ, l5);
465: Label l6 = new Label();
466: mv.visitLabel(l6);
467: mv.visitVarInsn(ALOAD, 2);
468: mv.visitTypeInsn(CHECKCAST,
469: "org/ow2/easybeans/rpc/ClientRPCInvocationHandler");
470: mv.visitVarInsn(ASTORE, THREE);
471: Label l7 = new Label();
472: mv.visitJumpInsn(GOTO, l7);
473: mv.visitLabel(l5);
474: mv.visitInsn(ICONST_0);
475: mv.visitInsn(IRETURN);
476: mv.visitLabel(l7);
477: mv.visitVarInsn(ALOAD, THREE);
478: mv.visitMethodInsn(INVOKEVIRTUAL,
479: "org/ow2/easybeans/rpc/ClientRPCInvocationHandler",
480: "getFactoryName", "()Ljava/lang/String;");
481: mv.visitVarInsn(ASTORE, FOUR);
482: Label l8 = new Label();
483: mv.visitLabel(l8);
484: mv.visitVarInsn(ALOAD, 0);
485: mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata
486: .getClassName(), "getEasyBeansFactory",
487: "()Lorg/ow2/easybeans/api/Factory;");
488: mv
489: .visitTypeInsn(INSTANCEOF,
490: "org/ow2/easybeans/container/session/stateless/StatelessSessionFactory");
491: Label l9 = new Label();
492: mv.visitJumpInsn(IFEQ, l9);
493: Label l10 = new Label();
494: mv.visitLabel(l10);
495: mv.visitVarInsn(ALOAD, 0);
496: mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata
497: .getClassName(), "getEasyBeansFactory",
498: "()Lorg/ow2/easybeans/api/Factory;");
499: mv.visitMethodInsn(INVOKEINTERFACE,
500: "org/ow2/easybeans/api/Factory", "getClassName",
501: "()Ljava/lang/String;");
502: Label l11 = new Label();
503: mv.visitLabel(l11);
504: mv.visitVarInsn(ALOAD, FOUR);
505: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals",
506: "(Ljava/lang/Object;)Z");
507: Label l12 = new Label();
508: mv.visitLabel(l12);
509: mv.visitInsn(IRETURN);
510: mv.visitLabel(l9);
511: mv.visitVarInsn(ALOAD, 0);
512: mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata
513: .getClassName(), "getEasyBeansFactory",
514: "()Lorg/ow2/easybeans/api/Factory;");
515: mv
516: .visitTypeInsn(INSTANCEOF,
517: "org/ow2/easybeans/container/session/stateful/StatefulSessionFactory");
518: Label l13 = new Label();
519: mv.visitJumpInsn(IFEQ, l13);
520: Label l14 = new Label();
521: mv.visitLabel(l14);
522: mv.visitVarInsn(ALOAD, THREE);
523: mv.visitMethodInsn(INVOKEVIRTUAL,
524: "org/ow2/easybeans/rpc/ClientRPCInvocationHandler",
525: "getBeanId", "()Ljava/lang/Long;");
526: mv.visitVarInsn(ASTORE, FIVE);
527: Label l15 = new Label();
528: mv.visitLabel(l15);
529: mv.visitVarInsn(ALOAD, 0);
530: mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata
531: .getClassName(), "getEasyBeansFactory",
532: "()Lorg/ow2/easybeans/api/Factory;");
533: mv.visitMethodInsn(INVOKEINTERFACE,
534: "org/ow2/easybeans/api/Factory", "getClassName",
535: "()Ljava/lang/String;");
536: Label l16 = new Label();
537: mv.visitLabel(l16);
538: mv.visitVarInsn(ALOAD, FOUR);
539: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals",
540: "(Ljava/lang/Object;)Z");
541: Label l17 = new Label();
542: mv.visitJumpInsn(IFEQ, l17);
543: Label l18 = new Label();
544: mv.visitLabel(l18);
545: mv.visitVarInsn(ALOAD, 0);
546: mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata
547: .getClassName(), "getEasyBeansStatefulID",
548: "()Ljava/lang/Long;");
549: mv.visitVarInsn(ALOAD, FIVE);
550: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "equals",
551: "(Ljava/lang/Object;)Z");
552: mv.visitJumpInsn(IFEQ, l17);
553: mv.visitInsn(ICONST_1);
554: mv.visitInsn(IRETURN);
555: mv.visitLabel(l17);
556: mv.visitInsn(ICONST_0);
557: Label l19 = new Label();
558: mv.visitLabel(l19);
559: mv.visitInsn(IRETURN);
560: mv.visitLabel(l13);
561: mv.visitInsn(ICONST_0);
562: mv.visitInsn(IRETURN);
563: mv.visitMaxs(0, 0);
564: mv.visitEnd();
565:
566: }
567:
568: }
|