001: /**
002: * Copyright (C) 2001-2005 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.generation.enhancer.pc;
018:
019: import org.objectweb.asm.ClassVisitor;
020: import org.objectweb.asm.CodeVisitor;
021: import org.objectweb.asm.Label;
022: import org.objectweb.asm.Type;
023: import org.objectweb.jorm.type.api.PType;
024: import org.objectweb.speedo.api.SpeedoException;
025: import org.objectweb.speedo.generation.api.SpeedoCompilerParameter;
026: import org.objectweb.speedo.generation.generator.lib.AbstractSpeedoGenerator;
027: import org.objectweb.speedo.lib.Personality;
028: import org.objectweb.speedo.metadata.SpeedoClass;
029: import org.objectweb.speedo.mim.api.PersistentObjectItf;
030: import org.objectweb.speedo.mim.lib.SpeedoPOSerializer;
031: import org.objectweb.speedo.naming.api.NamingManager;
032: import org.objectweb.util.monolog.api.Logger;
033:
034: /**
035: * Is an ASM visitor adding the implementation of the PersistenceCapable
036: * interface.
037: *
038: * @author S.Chassande-Barrioz
039: */
040: public class POAdder extends AbstractPCModifier implements
041: POVariableNames {
042:
043: public POAdder(ClassVisitor classVisitor, Logger logger,
044: SpeedoClass sc, SpeedoCompilerParameter cp, Personality p) {
045: super (classVisitor, logger, sc, cp, p);
046: }
047:
048: public void visit(final int version, final int access,
049: final String name, final String super Name,
050: final String[] interfaces, final String sourceFile) {
051: //indicate the number of new interface to add
052: String[] itfs;
053: if (interfaces != null && interfaces.length > 0) {
054: itfs = new String[interfaces.length + 1];
055: System.arraycopy(interfaces, 0, itfs, 1, interfaces.length);
056: } else {
057: itfs = new String[1];
058: }
059: itfs[0] = Type.getInternalName(PersistentObjectItf.class);
060: cv.visit(version, access, name, super Name, itfs, sourceFile);
061: }
062:
063: public void visitEnd() {
064: if (speedoClass.getSuper() == null) {
065: generateFields();
066: generateSpeedoIsActiveMethod();
067: generateSpeedoIsActiveZMethod();
068: generateSpeedoGetHomeMethod();
069: generateSpeedoGetReferenceStateMethod();
070: generateSpeedoSetReferenceStateMethod();
071: generateSpeedoGetStateMethod();
072: generateSpeedoCopyStateMethod();
073: generateSpeedoReadIntentionMethod();
074: generateSpeedoWriteIntentionMethod();
075: generateSpeedoGetEncodedPNameMethod();
076: generateSpeedoSetEncodedPNameMethod();
077: generateSpeedoGetPNameHintsMethod();
078: generateSpeedoGetPOManagerMethod();
079: generateSpeedoIsPersistentMethod();
080: }
081: generateSpeedoCreateStateMethod();
082: final int nbfields = speedoClass.computeFieldNumbers();
083: if (speedoClass.isSerializable) {
084: generateReadObjectMethod(nbfields);
085: generateWriteObjectMethod(nbfields);
086: }
087: super .visitEnd();
088: }
089:
090: private void generateFields() {
091: //transient protected boolean speedoIsActive = false;
092: cv.visitField(ACC_TRANSIENT + ACC_PROTECTED,
093: ISACTIVE_FIELD_NAME, Type.BOOLEAN_TYPE.getDescriptor(),
094: null, null);
095: //transient protected $classNameFields speedoReferenceState = null;
096: cv.visitField(ACC_TRANSIENT + ACC_PROTECTED,
097: REFSTATE_FIELD_NAME, xfieldsJT, null, null);
098: //protected Object encodedPName = null;
099: cv.visitField(ACC_PROTECTED, ENCODEDPNAME_FIELD_NAME,
100: "Ljava/lang/Object;", null, null);
101: }
102:
103: private void generateSpeedoIsActiveMethod() {
104: CodeVisitor mv;
105: mv = cv.visitMethod(ACC_PUBLIC, ISACTIVE_FIELD_NAME, "()Z",
106: null, null);
107: mv.visitVarInsn(ALOAD, 0);
108: mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME,
109: "Z");
110: mv.visitInsn(IRETURN);
111: mv.visitMaxs(0, 0);
112: }
113:
114: private void generateSpeedoIsActiveZMethod() {
115: CodeVisitor mv;
116: mv = cv.visitMethod(ACC_PUBLIC, ISACTIVE_FIELD_NAME, "(Z)V",
117: null, null);
118: mv.visitVarInsn(ALOAD, 0);
119: mv.visitVarInsn(ILOAD, 1);
120: mv.visitFieldInsn(PUTFIELD, classToWrite, ISACTIVE_FIELD_NAME,
121: "Z");
122: mv.visitInsn(RETURN);
123: mv.visitMaxs(0, 0);
124: }
125:
126: private void generateSpeedoGetHomeMethod() {
127: CodeVisitor mv;
128: mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_GET_HOME, "()"
129: + JT_HOME, null, null);
130: mv.visitVarInsn(ALOAD, 0);
131: //return (HomeItf) getPClassMapping();
132: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
133: "getPClassMapping",
134: "()Lorg/objectweb/jorm/api/PClassMapping;");
135: mv.visitTypeInsn(CHECKCAST, JCN_HOME);
136: mv.visitInsn(ARETURN);
137: mv.visitMaxs(0, 0);
138: }
139:
140: private void generateSpeedoGetReferenceStateMethod() {
141: CodeVisitor mv;
142: mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_GET_REF_STATE, "()"
143: + JT_STATE, null, null);
144: //return speedoReferenceState
145: generateGetRefState(mv, false);
146: mv.visitInsn(ARETURN);
147: mv.visitMaxs(0, 0);
148: }
149:
150: private void generateSpeedoGetStateMethod() {
151: CodeVisitor mv;
152: mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_GET_STATE, "()"
153: + JT_STATE, null, null);
154: //if (!speedoIsActive) {
155: // return speedoReferenceState;
156: //}
157: mv.visitVarInsn(ALOAD, 0);
158: mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME,
159: "Z");
160: Label l1 = new Label();
161: mv.visitJumpInsn(IFNE, l1);
162: generateGetRefState(mv, false);
163: mv.visitInsn(ARETURN);
164: mv.visitLabel(l1);
165:
166: //return speedoGetHome().getSpeedoAccessor(this);
167: mv.visitVarInsn(ALOAD, 0);
168: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
169: M_SPEEDO_GET_HOME, "()" + JT_HOME);
170: mv.visitVarInsn(ALOAD, 0);
171: mv.visitMethodInsn(INVOKEINTERFACE, JCN_HOME, "getState", "("
172: + JT_PO + ")" + JT_STATE);
173: mv.visitInsn(ARETURN);
174: mv.visitMaxs(0, 0);
175: }
176:
177: private void generateSpeedoReadIntentionMethod() {
178: CodeVisitor mv;
179: mv = cv.visitMethod(ACC_PUBLIC, "speedoReadIntention", "([J)"
180: + JT_STATE, null, null);
181: //if (!speedoIsActive) {
182: mv.visitVarInsn(ALOAD, 0);
183: mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME,
184: "Z");
185: Label l1 = new Label();
186: mv.visitJumpInsn(IFNE, l1);
187: {
188: //if (speedoReferenceState == null) {
189: generateGetRefState(mv, false);
190: Label l3 = new Label();
191: mv.visitJumpInsn(IFNONNULL, l3);
192: {
193: //speedoSetReferenceState(speedoCreateState());
194: mv.visitVarInsn(ALOAD, 0);
195: mv.visitVarInsn(ALOAD, 0);
196: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
197: M_SPEEDO_CREATE_STATE, "()" + JT_STATE);
198: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
199: M_SPEEDO_SET_REF_STATE, "(" + JT_STATE + ")V");
200: }
201: //return speedoReferenceState;
202: mv.visitLabel(l3);
203: generateGetRefState(mv, false);
204: mv.visitInsn(ARETURN);
205: }
206:
207: //return speedoGetHome().readIntention(this, fields);
208: mv.visitLabel(l1);
209: mv.visitVarInsn(ALOAD, 0);
210: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
211: M_SPEEDO_GET_HOME, "()" + JT_HOME);
212: mv.visitVarInsn(ALOAD, 0);
213: mv.visitVarInsn(ALOAD, 1);
214: mv.visitMethodInsn(INVOKEINTERFACE, JCN_HOME, "readIntention",
215: "(" + JT_PO + "[J)" + JT_STATE);
216: mv.visitInsn(ARETURN);
217: mv.visitMaxs(0, 0);
218: }
219:
220: private void generateSpeedoWriteIntentionMethod() {
221: CodeVisitor mv;
222: mv = cv.visitMethod(ACC_PUBLIC, "speedoWriteIntention", "([J)"
223: + JT_STATE, null, null);
224: //if (!speedoIsActive) {
225: mv.visitVarInsn(ALOAD, 0);
226: mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME,
227: "Z");
228: Label l1 = new Label();
229: mv.visitJumpInsn(IFNE, l1);
230: {
231: //if (speedoReferenceState == null) {
232: generateGetRefState(mv, false);
233: Label l3 = new Label();
234: mv.visitJumpInsn(IFNONNULL, l3);
235: {
236: //speedoSetReferenceState(speedoCreateState());
237: mv.visitVarInsn(ALOAD, 0);
238: mv.visitVarInsn(ALOAD, 0);
239: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
240: M_SPEEDO_CREATE_STATE, "()" + JT_STATE);
241: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
242: M_SPEEDO_SET_REF_STATE, "(" + JT_STATE + ")V");
243: }
244: //if(speedoReferenceState.getDetachedStatus() == DetachedLifeCycle.DETACHED_CLEAN){
245: mv.visitLabel(l3);
246: generateGetRefState(mv, false);
247: mv.visitMethodInsn(INVOKEVIRTUAL, xfieldsAncestorJCN,
248: "getDetachedStatus", "()B");
249: mv.visitInsn(ICONST_1);
250: Label l5 = new Label();
251: mv.visitJumpInsn(IF_ICMPNE, l5);
252: {
253: //speedoReferenceState.setDetachedStatus(DetachedLifeCycle.DETACHED_DIRTY);
254: generateGetRefState(mv, false);
255: mv.visitInsn(ICONST_2);
256: mv.visitMethodInsn(INVOKEVIRTUAL, xfieldsAncestorJCN,
257: "setDetachedStatus", "(B)V");
258: }
259: //return speedoReferenceState;
260: mv.visitLabel(l5);
261: generateGetRefState(mv, false);
262: mv.visitInsn(ARETURN);
263: }
264: //return speedoGetHome().writeIntention(this, fields);
265: mv.visitLabel(l1);
266: mv.visitVarInsn(ALOAD, 0);
267: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
268: M_SPEEDO_GET_HOME, "()" + JT_HOME);
269: mv.visitVarInsn(ALOAD, 0);
270: mv.visitVarInsn(ALOAD, 1);
271: mv.visitMethodInsn(INVOKEINTERFACE, JCN_HOME, "writeIntention",
272: "(" + JT_PO + "[J)" + JT_STATE);
273: mv.visitInsn(ARETURN);
274: mv.visitMaxs(0, 0);
275: }
276:
277: private void generateSpeedoGetEncodedPNameMethod() {
278: CodeVisitor mv;
279: mv = cv.visitMethod(ACC_PUBLIC, "speedoGetEncodedPName",
280: "()Ljava/lang/Object;", null, null);
281: mv.visitVarInsn(ALOAD, 0);
282: mv.visitFieldInsn(GETFIELD, classToWrite,
283: ENCODEDPNAME_FIELD_NAME, "Ljava/lang/Object;");
284: mv.visitInsn(ARETURN);
285: mv.visitMaxs(0, 0);
286: }
287:
288: private void generateSpeedoSetEncodedPNameMethod() {
289: CodeVisitor mv;
290: mv = cv.visitMethod(ACC_PUBLIC, "speedoSetEncodedPName",
291: "(Ljava/lang/Object;)V", null, null);
292: mv.visitVarInsn(ALOAD, 0);
293: mv.visitVarInsn(ALOAD, 1);
294: mv.visitFieldInsn(PUTFIELD, classToWrite,
295: ENCODEDPNAME_FIELD_NAME, "Ljava/lang/Object;");
296: mv.visitInsn(RETURN);
297: mv.visitMaxs(0, 0);
298: }
299:
300: private void generateSpeedoGetPNameHintsMethod() {
301: CodeVisitor mv;
302: mv = cv.visitMethod(ACC_PUBLIC, "speedoGetPNameHints",
303: "()Ljava/lang/Object;", null, null);
304: final Object[] actions;
305: try {
306: actions = scp.nmf.getNamingManager(speedoClass)
307: .getPNameHints2(
308: speedoClass,
309: AbstractSpeedoGenerator.getClassNameDef(
310: speedoClass.jormclass, scp));
311: } catch (SpeedoException e) {
312: throw personality.newRuntimeException(e.getMessage(), e);
313: }
314: if (actions == null || actions.length == 0) {
315: mv.visitInsn(ACONST_NULL);
316: } else if (actions[0].equals(NamingManager.PNH_NULL_VALUE)) {
317: mv.visitInsn(ACONST_NULL);
318:
319: } else if (actions[0].equals(NamingManager.PNH_REF_STATE)) {
320: generateGetRefState(mv, false);
321:
322: } else if (actions[0].equals(NamingManager.PNH_PFIELD)) {
323: final PType pt = (PType) actions[2];
324: final String fieldName = (String) actions[1];
325: final String jvmFieldType = getJVMType(pt);
326: final String wrapper = getJavaWrapper(pt);
327: if (wrapper != null) {
328: mv.visitTypeInsn(NEW, wrapper);
329: mv.visitInsn(DUP);
330: }
331: generateGetRefState(mv, true);
332: mv.visitFieldInsn(GETFIELD, xfieldsJCN, fieldName,
333: jvmFieldType);
334: if (wrapper != null) {
335: mv.visitMethodInsn(INVOKESPECIAL, wrapper, "<init>",
336: "(" + jvmFieldType + ")V");
337: }
338: }
339:
340: mv.visitInsn(ARETURN);
341: mv.visitMaxs(0, 0);
342: }
343:
344: private void generateSpeedoGetPOManagerMethod() {
345: CodeVisitor mv = cv.visitMethod(ACC_PUBLIC,
346: "speedoGetPOManager",
347: "()Lorg/objectweb/speedo/pm/api/POManagerItf;", null,
348: null);
349: //return (speedoIsActive
350: //? speedoGetHome().getPOManagerFactory().lookup()
351: //: null);
352: mv.visitVarInsn(ALOAD, 0);
353: mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME,
354: "Z");
355: Label l1 = new Label();
356: mv.visitJumpInsn(IFEQ, l1);
357: mv.visitVarInsn(ALOAD, 0);
358: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
359: "speedoGetHome", "()" + JT_HOME);
360: mv.visitMethodInsn(INVOKEINTERFACE, JCN_HOME,
361: "getPOManagerFactory", "()" + JT_POMF);
362: mv.visitMethodInsn(INVOKEINTERFACE, JCN_POMF, "lookup", "()"
363: + JT_POM);
364: Label l2 = new Label();
365: mv.visitJumpInsn(GOTO, l2);
366: mv.visitLabel(l1);
367: mv.visitInsn(ACONST_NULL);
368: mv.visitLabel(l2);
369: mv.visitInsn(ARETURN);
370: mv.visitMaxs(0, 0);
371: }
372:
373: private String getJavaWrapper(PType pt) {
374: switch (pt.getTypeCode()) {
375: case PType.TYPECODE_BOOLEAN:
376: return getJVMClassName(Boolean.class);
377: case PType.TYPECODE_CHAR:
378: return getJVMClassName(Character.class);
379: case PType.TYPECODE_BYTE:
380: return getJVMClassName(Byte.class);
381: case PType.TYPECODE_SHORT:
382: return getJVMClassName(Short.class);
383: case PType.TYPECODE_INT:
384: return getJVMClassName(Integer.class);
385: case PType.TYPECODE_LONG:
386: return getJVMClassName(Long.class);
387: case PType.TYPECODE_FLOAT:
388: return getJVMClassName(Float.class);
389: case PType.TYPECODE_DOUBLE:
390: return getJVMClassName(Double.class);
391: default:
392: return null;
393: }
394: }
395:
396: private void generateSpeedoCreateStateMethod() {
397: CodeVisitor mv;
398: mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_CREATE_STATE, "()"
399: + JT_STATE, null, null);
400: //return new $classNameFields(this);
401: mv.visitTypeInsn(NEW, xfieldsJCN);
402: mv.visitInsn(DUP);
403: mv.visitVarInsn(ALOAD, 0);
404: mv.visitMethodInsn(INVOKESPECIAL, xfieldsJCN, "<init>", "("
405: + JT_PO + ")V");
406: mv.visitInsn(ARETURN);
407: mv.visitMaxs(0, 0);
408: }
409:
410: private void generateSpeedoSetReferenceStateMethod() {
411: CodeVisitor mv;
412: mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_SET_REF_STATE, "("
413: + JT_STATE + ")V", null, null);
414: //speedoReferenceState = ($classNameFields) refAcc;
415: mv.visitVarInsn(ALOAD, 0);
416: mv.visitVarInsn(ALOAD, 1);
417: mv.visitTypeInsn(CHECKCAST, xfieldsAncestorJCN);
418: mv.visitFieldInsn(PUTFIELD, ancestorJCN, REFSTATE_FIELD_NAME,
419: xfieldsAncestorJT);
420: mv.visitInsn(RETURN);
421: mv.visitMaxs(0, 0);
422: }
423:
424: private void generateSpeedoCopyStateMethod() {
425: CodeVisitor mv;
426: mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_COPY_STATE, "("
427: + JT_STATE + JT_STATE + ")V", null, null);
428: //(($classNameFields) src).speedoCopyState(src, dest);
429: mv.visitVarInsn(ALOAD, 1);
430: mv.visitTypeInsn(CHECKCAST, xfieldsJCN);
431: mv.visitVarInsn(ALOAD, 1);
432: mv.visitVarInsn(ALOAD, 2);
433: mv.visitMethodInsn(INVOKEVIRTUAL, xfieldsJCN,
434: M_SPEEDO_COPY_STATE, "(" + JT_STATE + JT_STATE + ")V");
435: mv.visitInsn(RETURN);
436: mv.visitMaxs(0, 0);
437: }
438:
439: private void generateReadObjectMethod(int nbField) {
440: CodeVisitor mv;
441: mv = cv.visitMethod(ACC_PRIVATE, "readObject",
442: "(Ljava/io/ObjectInputStream;)V", new String[] {
443: "java/io/IOException",
444: "java/lang/ClassNotFoundException" }, null);
445: mv.visitVarInsn(ALOAD, 1); //param
446: mv.visitVarInsn(ALOAD, 0); //this
447: mv.visitMethodInsn(INVOKESTATIC,
448: getJVMClassName(SpeedoPOSerializer.class),
449: "readObject", "(Ljava/io/ObjectInputStream;" + JT_PO
450: + ")V");
451: mv.visitInsn(RETURN);
452: mv.visitMaxs(0, 0);
453: }
454:
455: private void generateWriteObjectMethod(int nbField) {
456: CodeVisitor mv;
457: mv = cv.visitMethod(ACC_PRIVATE, "writeObject",
458: "(Ljava/io/ObjectOutputStream;)V",
459: new String[] { "java/io/IOException" }, null);
460: mv.visitVarInsn(ALOAD, 1); //param
461: mv.visitVarInsn(ALOAD, 0); //this
462: // new long[]{0xffffffffffffffffL, ..., 0xffffffffffffffffL}
463: generateFieldIdAsLongArray(null, nbField, mv);
464: mv.visitMethodInsn(INVOKESTATIC,
465: getJVMClassName(SpeedoPOSerializer.class),
466: "writeObject", "(Ljava/io/ObjectOutputStream;" + JT_PO
467: + "[J)V");
468: mv.visitInsn(RETURN);
469: mv.visitMaxs(0, 0);
470: }
471:
472: private void generateSpeedoIsPersistentMethod() {
473: CodeVisitor mv;
474: mv = cv.visitMethod(ACC_PUBLIC, "speedoIsPersistent", "()Z",
475: null, null);
476:
477: //if (!speedoIsActive) {
478: // return false;
479: //}
480: mv.visitVarInsn(ALOAD, 0);
481: mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME,
482: "Z");
483: Label l1 = new Label();
484: mv.visitJumpInsn(IFNE, l1);
485: mv.visitInsn(ICONST_0);
486: mv.visitInsn(IRETURN);
487: mv.visitLabel(l1);
488:
489: //StateItf sa = speedoGetState();
490: mv.visitVarInsn(ALOAD, 0);
491: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
492: M_SPEEDO_GET_STATE, "()" + JT_STATE);
493: mv.visitVarInsn(ASTORE, 1);
494:
495: //return sa == null || LifeCycle.isPersistent(sa.speedoGetStatus());
496: mv.visitVarInsn(ALOAD, 1);
497: Label l4 = new Label();
498: mv.visitJumpInsn(IFNULL, l4);
499: mv.visitVarInsn(ALOAD, 1);
500: mv.visitMethodInsn(INVOKEINTERFACE, JCN_STATE,
501: M_SPEEDO_GET_STATUS, "()B");
502: mv.visitMethodInsn(INVOKESTATIC, JCN_LIFE_CYCLE,
503: "isPersistent", "(B)Z");
504: Label l5 = new Label();
505: mv.visitJumpInsn(IFEQ, l5);
506: mv.visitLabel(l4);
507: mv.visitInsn(ICONST_1);
508: Label l6 = new Label();
509: mv.visitJumpInsn(GOTO, l6);
510:
511: mv.visitLabel(l5);
512: mv.visitInsn(ICONST_0);
513:
514: mv.visitLabel(l6);
515: mv.visitInsn(IRETURN);
516: mv.visitMaxs(0, 0);
517: }
518:
519: }
|