blob: f03c35d98ec62eccef9b046554b0b324771d263a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011-2012 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* dclarke - Bug 361016: Future Versions Examples
******************************************************************************/
package temporal.persistence;
import static org.eclipse.persistence.internal.dynamic.DynamicPropertiesManager.PROPERTIES_MANAGER_FIELD;
import java.lang.reflect.Modifier;
import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.dynamic.DynamicClassWriter;
import org.eclipse.persistence.internal.libraries.asm.ClassWriter;
import org.eclipse.persistence.internal.libraries.asm.MethodVisitor;
import org.eclipse.persistence.internal.libraries.asm.Opcodes;
/**
* Custom {@link DynamicClassWriter} used to creat edition class with additional
* interface.
*
* @author dclarke
* @since EclipseLink 2.3.1
*/
public class EditionClassWriter extends DynamicClassWriter implements Opcodes {
private Class<?> editionInterface;
public EditionClassWriter(@SuppressWarnings("rawtypes") Class parentClass, Class<?> editionInterface) {
super(parentClass);
this.editionInterface = editionInterface;
}
public byte[] writeClass(DynamicClassLoader loader, String className) throws ClassNotFoundException {
Class<?> parent = getParentClass(loader);
parentClassName = parent.getName();
if (parent == null || parent.isPrimitive() || parent.isArray() || parent.isEnum() || parent.isInterface() || Modifier.isFinal(parent.getModifiers())) {
throw new IllegalArgumentException("Invalid parent class: " + parent);
}
String parentClassNameAsSlashes = parentClassName.replace('.', '/');
String classNameAsSlashes = className.replace('.', '/');
String editionInterfaceName = this.editionInterface.getName().replace('.', '/');
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
// public class Foo extends DynamicEntityImpl {
cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, classNameAsSlashes, null, parentClassNameAsSlashes, new String[] {editionInterfaceName});
// public static DynamicPropertiesManager DPM = new
// DynamicPropertiesManager();
cw.visitField(ACC_PUBLIC + ACC_STATIC, PROPERTIES_MANAGER_FIELD, "L" + DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";", null, null);
MethodVisitor mv = cw.visitMethod(ACC_STATIC, CLINIT, "()V", null, null);
mv.visitTypeInsn(NEW, DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES, INIT, "()V");
mv.visitFieldInsn(PUTSTATIC, classNameAsSlashes, PROPERTIES_MANAGER_FIELD, "L" + DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";");
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
// public Foo() {
// super();
// }
mv = cw.visitMethod(ACC_PUBLIC, INIT, "()V", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, parentClassNameAsSlashes, INIT, "()V");
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv = cw.visitMethod(ACC_PUBLIC, "fetchPropertiesManager", "()L" + DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";", null, null);
mv.visitFieldInsn(GETSTATIC, classNameAsSlashes, PROPERTIES_MANAGER_FIELD, "L" + DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";");
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
cw.visitEnd();
return cw.toByteArray();
}
private Class<?> getParentClass(ClassLoader loader) throws ClassNotFoundException {
if (parentClass == null && parentClassName != null) {
parentClass = loader.loadClass(parentClassName);
}
return parentClass;
}
public byte[] writeInterface() {
ClassWriter cw = new ClassWriter(0);
cw.visit(51, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, "tests/internal/asm/PersonEdition", null, "java/lang/Object", new String[] { "model/Person" });
cw.visitEnd();
return cw.toByteArray();
}
}