/**
* Copyright (C) 2001-2005 France Telecom R&D
*
* 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 of the License, or (at your option) 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
*/
package org.objectweb.speedo.generation.enhancer.pc.jdo;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.speedo.generation.api.SpeedoCompilerParameter;
import org.objectweb.speedo.generation.enhancer.pc.AbstractPCModifier;
import org.objectweb.speedo.generation.enhancer.pc.POVariableNames;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.speedo.mim.jdo.api.JDOPersistentObjectItf;
import org.objectweb.util.monolog.api.Logger;
import javax.jdo.spi.PersistenceCapable;
/**
* Is an ASM visitor adding the implementation of the PersistenceCapable
* interface.
*
* @author S.Chassande-Barrioz
*/
public class JDOPersistenceCapableAdder extends AbstractPCModifier
implements POVariableNames {
public JDOPersistenceCapableAdder(ClassVisitor classVisitor,
Logger logger,
SpeedoClass sc,
SpeedoCompilerParameter cp,
Personality p) {
super(classVisitor, logger, sc, cp, p);
}
public void visit(final int version,
final int access,
final String name,
final String superName,
final String[] interfaces,
final String sourceFile) {
String[] itfs;
if (interfaces != null && interfaces.length > 0) {
itfs = new String[interfaces.length + 2];
System.arraycopy(interfaces, 0, itfs, 2, interfaces.length);
} else {
itfs = new String[2];
}
itfs[0] = Type.getInternalName(PersistenceCapable.class);
itfs[1] = Type.getInternalName(JDOPersistentObjectItf.class);
cv.visit(version, access, name, superName, itfs, sourceFile);
}
public void visitEnd() {
generateJdoGetPersistenceManagerMethod();
generateJdoReplaceFlagsMethod();
generateJdoNewInstanceSMMethod();
generateJdoNewInstanceSMOMethod();
generateJdoNewObjectIdInstanceMethod();
generateJdoGetObjectIdMethod();
generateJdoGetTransactionalObjectIdMethod();
generateJdoReplaceFieldIMethod();
generateJdoReplaceFieldAIMethod();
generateJdoProvideFieldIMethod();
generateJdoProvideFieldAIMethod();
generateJdoCopyFieldsMethod();
generateJdoCopyKeyFieldsToObjectIdOIFMMethod();
generateJdoCopyKeyFieldsToObjectIdOMethod();
generateJdoCopyKeyFieldsToObjectIdOIFSMethod();
generateJdoCopyKeyFieldsFromObjectIdMethod();
generateJdoMakeDirtyMethod();
generateJdoIsDirtyMethod();
generateJdoIsTransactionalMethod();
generateJdoIsPersistentMethod();
generateJdoIsNewMethod();
generateJdoIsDeletedMethod();
generateJdoIsDetachedMethod();
generateJdoReplaceObjectIdMethod();
generateJdoReplaceStateManagerMethod();
super.visitEnd();
}
private void generateReturnFalseIfNotIsActive(CodeVisitor mv) {
//if (!speedoIsActive) {
// return false;
//}
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME, "Z");
Label l1 = new Label();
mv.visitJumpInsn(IFNE, l1);
mv.visitInsn(ICONST_0);
mv.visitInsn(IRETURN);
mv.visitLabel(l1);
}
private void generateThrowJDOUnsupportedOptionException(CodeVisitor mv) {
mv.visitTypeInsn(NEW, "javax/jdo/JDOUnsupportedOptionException");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL,
"javax/jdo/JDOUnsupportedOptionException", "<init>", "()V");
mv.visitInsn(ATHROW);
}
private void generateJdoGetPersistenceManagerMethod() {
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "jdoGetPersistenceManager",
"()Ljavax/jdo/PersistenceManager;", null, null);
//return (speedoIsActive
//? speedoGetHome().getPOManagerFactory().lookup()
//: null);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME, "Z");
Label l1 = new Label();
mv.visitJumpInsn(IFEQ, l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, "speedoGetHome",
"()" + JT_HOME);
mv.visitMethodInsn(INVOKEINTERFACE, JCN_HOME, "getPOManagerFactory",
"()" + JT_POMF);
mv.visitMethodInsn(INVOKEINTERFACE, JCN_POMF, "lookup", "()" + JT_POM);
Label l2 = new Label();
mv.visitJumpInsn(GOTO, l2);
mv.visitLabel(l1);
mv.visitInsn(ACONST_NULL);
mv.visitLabel(l2);
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoReplaceFlagsMethod() {
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "jdoReplaceFlags",
"()V", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoNewInstanceSMMethod() {
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "jdoNewInstance",
"(Ljavax/jdo/spi/StateManager;)" +
"Ljavax/jdo/spi/PersistenceCapable;", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoNewInstanceSMOMethod() {
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "jdoNewInstance",
"(Ljavax/jdo/spi/StateManager;Ljava/lang/Object;)"
+ "Ljavax/jdo/spi/PersistenceCapable;", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoNewObjectIdInstanceMethod() {
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "jdoNewObjectIdInstance",
"()Ljava/lang/Object;", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoGetObjectIdMethod() {
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "jdoGetObjectId",
"()Ljava/lang/Object;", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
"getPName", "()Lorg/objectweb/jorm/naming/api/PName;");
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoGetTransactionalObjectIdMethod() {
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "jdoGetTransactionalObjectId",
"()Ljava/lang/Object;", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, "getPName",
"()Lorg/objectweb/jorm/naming/api/PName;");
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoReplaceFieldIMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoReplaceField", "(I)V", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoReplaceFieldAIMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoReplaceField", "([I)V", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoProvideFieldIMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoProvideField", "(I)V", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoProvideFieldAIMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoProvideField", "([I)V", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoCopyFieldsMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoCopyFields",
"(Ljava/lang/Object;[I)V", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoCopyKeyFieldsToObjectIdOIFMMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoCopyKeyFieldsToObjectId",
"(Ljavax/jdo/spi/PersistenceCapable$ObjectIdFieldManager;Ljava/lang/Object;)V", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoCopyKeyFieldsToObjectIdOMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoCopyKeyFieldsToObjectId",
"(Ljava/lang/Object;)V", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoCopyKeyFieldsToObjectIdOIFSMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoCopyKeyFieldsToObjectId",
"(Ljavax/jdo/spi/PersistenceCapable$ObjectIdFieldSupplier;Ljava/lang/Object;)V", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoCopyKeyFieldsFromObjectIdMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoCopyKeyFieldsFromObjectId",
"(Ljavax/jdo/spi/PersistenceCapable$ObjectIdFieldConsumer;Ljava/lang/Object;)V", null, null);
generateThrowJDOUnsupportedOptionException(mv);
mv.visitMaxs(0, 0);
}
private void generateJdoMakeDirtyMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoMakeDirty", "(Ljava/lang/String;)V", null, null);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoIsDirtyMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoIsDirty", "()Z", null, null);
generateReturnFalseIfNotIsActive(mv);
//StateItf sa = speedoGetState();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, M_SPEEDO_GET_STATE, "()" + JT_STATE);
mv.visitVarInsn(ASTORE, 1);
//if (sa == null) {
// return false;
//}
mv.visitVarInsn(ALOAD, 1);
Label l4 = new Label();
mv.visitJumpInsn(IFNONNULL, l4);
mv.visitInsn(ICONST_0);
mv.visitInsn(IRETURN);
mv.visitLabel(l4);
//byte status = sa.jdoGetStatus();
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, JCN_STATE, M_SPEEDO_GET_STATUS, "()B");
mv.visitVarInsn(ISTORE, 2);
//return !LifeCycle.isTransient(status) && LifeCycle.isDirty(status);
mv.visitVarInsn(ILOAD, 2);
mv.visitMethodInsn(INVOKESTATIC, JCN_LIFE_CYCLE, "isTransient", "(B)Z");
Label l7 = new Label();
mv.visitJumpInsn(IFNE, l7);
mv.visitVarInsn(ILOAD, 2);
mv.visitMethodInsn(INVOKESTATIC, JCN_LIFE_CYCLE, "isDirty", "(B)Z");
mv.visitJumpInsn(IFEQ, l7);
mv.visitInsn(ICONST_1);
Label l8 = new Label();
mv.visitJumpInsn(GOTO, l8);
mv.visitLabel(l7);
mv.visitInsn(ICONST_0);
mv.visitLabel(l8);
mv.visitInsn(IRETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoIsTransactionalMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoIsTransactional", "()Z", null, null);
generateReturnFalseIfNotIsActive(mv);
//StateItf sa = speedoGetState();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, M_SPEEDO_GET_STATE, "()" + JT_STATE);
mv.visitVarInsn(ASTORE, 1);
//if (sa == null) {
// return false;
//}
mv.visitVarInsn(ALOAD, 1);
Label l4 = new Label();
mv.visitJumpInsn(IFNONNULL, l4);
mv.visitInsn(ICONST_0);
mv.visitInsn(IRETURN);
mv.visitLabel(l4);
//byte status = sa.jdoGetStatus();
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, JCN_STATE, M_SPEEDO_GET_STATUS, "()B");
mv.visitVarInsn(ISTORE, 2);
//return !LifeCycle.isTransient(status) && LifeCycle.isTransactional(status);
mv.visitVarInsn(ILOAD, 2);
mv.visitMethodInsn(INVOKESTATIC, JCN_LIFE_CYCLE, "isTransient", "(B)Z");
Label l7 = new Label();
mv.visitJumpInsn(IFNE, l7);
mv.visitVarInsn(ILOAD, 2);
mv.visitMethodInsn(INVOKESTATIC, JCN_LIFE_CYCLE, "isTransactional", "(B)Z");
mv.visitJumpInsn(IFEQ, l7);
mv.visitInsn(ICONST_1);
Label l8 = new Label();
mv.visitJumpInsn(GOTO, l8);
mv.visitLabel(l7);
mv.visitInsn(ICONST_0);
mv.visitLabel(l8);
mv.visitInsn(IRETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoIsPersistentMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoIsPersistent", "()Z", null, null);
generateReturnFalseIfNotIsActive(mv);
//StateItf sa = speedoGetState();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, M_SPEEDO_GET_STATE, "()" + JT_STATE);
mv.visitVarInsn(ASTORE, 1);
//return sa == null || LifeCycle.isPersistent(sa.jdoGetStatus());
mv.visitVarInsn(ALOAD, 1);
Label l4 = new Label();
mv.visitJumpInsn(IFNULL, l4);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, JCN_STATE, M_SPEEDO_GET_STATUS, "()B");
mv.visitMethodInsn(INVOKESTATIC, JCN_LIFE_CYCLE, "isPersistent", "(B)Z");
Label l5 = new Label();
mv.visitJumpInsn(IFEQ, l5);
mv.visitLabel(l4);
mv.visitInsn(ICONST_1);
Label l6 = new Label();
mv.visitJumpInsn(GOTO, l6);
mv.visitLabel(l5);
mv.visitInsn(ICONST_0);
mv.visitLabel(l6);
mv.visitInsn(IRETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoIsNewMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoIsNew", "()Z", null, null);
generateReturnFalseIfNotIsActive(mv);
//StateItf sa = speedoGetState();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, M_SPEEDO_GET_STATE, "()" + JT_STATE);
mv.visitVarInsn(ASTORE, 1);
//return sa != null && LifeCycle.isNew(sa.jdoGetStatus());
Label l4 = new Label();
mv.visitVarInsn(ALOAD, 1);
mv.visitJumpInsn(IFNULL, l4);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, JCN_STATE, M_SPEEDO_GET_STATUS, "()B");
mv.visitMethodInsn(INVOKESTATIC,JCN_LIFE_CYCLE, "isNew", "(B)Z");
mv.visitJumpInsn(IFEQ, l4);
mv.visitInsn(ICONST_1);
Label l5 = new Label();
mv.visitJumpInsn(GOTO, l5);
mv.visitLabel(l4);
mv.visitInsn(ICONST_0);
mv.visitLabel(l5);
mv.visitInsn(IRETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoIsDeletedMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoIsDeleted", "()Z", null, null);
generateReturnFalseIfNotIsActive(mv);
//StateItf sa = speedoGetState();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, M_SPEEDO_GET_STATE, "()" + JT_STATE);
mv.visitVarInsn(ASTORE, 1);
//return sa != null && LifeCycle.isDeleted(sa.jdoGetStatus());
Label l4 = new Label();
mv.visitVarInsn(ALOAD, 1);
mv.visitJumpInsn(IFNULL, l4);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, JCN_STATE, M_SPEEDO_GET_STATUS, "()B");
mv.visitMethodInsn(INVOKESTATIC, JCN_LIFE_CYCLE, "isDeleted", "(B)Z");
mv.visitJumpInsn(IFEQ, l4);
mv.visitInsn(ICONST_1);
Label l5 = new Label();
mv.visitJumpInsn(GOTO, l5);
mv.visitLabel(l4);
mv.visitInsn(ICONST_0);
mv.visitLabel(l5);
mv.visitInsn(IRETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoIsDetachedMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoIsDetached", "()Z", null, null);
mv.visitInsn(ICONST_0);
mv.visitInsn(IRETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoReplaceObjectIdMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoReplaceObjectId", "(Ljava/lang/Object;)V", null, null);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
}
private void generateJdoReplaceStateManagerMethod() {
CodeVisitor mv;
mv = cv.visitMethod(ACC_PUBLIC, "jdoReplaceStateManager", "(Ljavax/jdo/spi/StateManager;)V", null, null);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
}
}