001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.weblogic.transform;
006:
007: import com.tc.asm.ClassAdapter;
008: import com.tc.asm.ClassVisitor;
009: import com.tc.asm.Label;
010: import com.tc.asm.MethodAdapter;
011: import com.tc.asm.MethodVisitor;
012: import com.tc.asm.Opcodes;
013: import com.tc.object.bytecode.ByteCodeUtil;
014: import com.tc.object.bytecode.ClassAdapterFactory;
015: import com.tc.object.loaders.Namespace;
016:
017: public class GenericClassLoaderAdapter extends ClassAdapter implements
018: Opcodes, ClassAdapterFactory {
019:
020: private static final String LOADER_DESC_FIELD = ByteCodeUtil.TC_FIELD_PREFIX
021: + "loaderDesc";
022:
023: public GenericClassLoaderAdapter() {
024: super (null);
025: }
026:
027: private GenericClassLoaderAdapter(ClassVisitor cv,
028: ClassLoader caller) {
029: super (cv);
030: }
031:
032: public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) {
033: return new GenericClassLoaderAdapter(visitor, loader);
034: }
035:
036: public void visit(int version, int access, String name,
037: String signature, String super Name, String[] interfaces) {
038: interfaces = ByteCodeUtil.addInterfaces(interfaces,
039: new String[] { ByteCodeUtil.NAMEDCLASSLOADER_CLASS });
040: super .visit(version, access, name, signature, super Name,
041: interfaces);
042:
043: // add field for loader description
044: super .visitField(ACC_PRIVATE | ACC_SYNTHETIC | ACC_TRANSIENT,
045: LOADER_DESC_FIELD, "Ljava/lang/String;", null, null);
046: }
047:
048: public void visitEnd() {
049: addNamedClassLoaderMethods();
050: super .visitEnd();
051: }
052:
053: public MethodVisitor visitMethod(int access, String name,
054: String desc, String signature, String[] exceptions) {
055: MethodVisitor mv = super .visitMethod(access, name, desc,
056: signature, exceptions);
057: if ("setAnnotation".equals(name)) {
058: mv = new SetAnnotationAdatper(mv);
059: }
060:
061: return mv;
062: }
063:
064: private void addNamedClassLoaderMethods() {
065: MethodVisitor mv = super .visitMethod(ACC_PUBLIC | ACC_FINAL
066: | ACC_SYNTHETIC, "__tc_getClassLoaderName",
067: "()Ljava/lang/String;", null, null);
068: mv.visitCode();
069: mv.visitVarInsn(ALOAD, 0);
070: mv.visitFieldInsn(GETFIELD,
071: "weblogic/utils/classloaders/GenericClassLoader",
072: LOADER_DESC_FIELD, "Ljava/lang/String;");
073: Label loaderDescDefined = new Label();
074: mv.visitJumpInsn(IFNONNULL, loaderDescDefined);
075: mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
076: mv.visitInsn(DUP);
077: mv.visitTypeInsn(NEW, "java/lang/StringBuffer");
078: mv.visitInsn(DUP);
079: mv.visitLdcInsn("No terracotta loader name defined for ");
080: mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuffer",
081: "<init>", "(Ljava/lang/String;)V");
082: mv.visitVarInsn(ALOAD, 0);
083: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
084: "append",
085: "(Ljava/lang/Object;)Ljava/lang/StringBuffer;");
086: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
087: "toString", "()Ljava/lang/String;");
088: mv.visitMethodInsn(INVOKESPECIAL,
089: "java/lang/IllegalStateException", "<init>",
090: "(Ljava/lang/String;)V");
091: mv.visitInsn(ATHROW);
092: mv.visitLabel(loaderDescDefined);
093: mv.visitVarInsn(ALOAD, 0);
094: mv.visitFieldInsn(GETFIELD,
095: "weblogic/utils/classloaders/GenericClassLoader",
096: LOADER_DESC_FIELD, "Ljava/lang/String;");
097: mv.visitInsn(ARETURN);
098: mv.visitMaxs(0, 0);
099: mv.visitEnd();
100:
101: mv = super .visitMethod(ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
102: "__tc_setClassLoaderName", "(Ljava/lang/String;)V",
103: null, null);
104: mv.visitCode();
105: mv.visitTypeInsn(NEW, "java/lang/AssertionError");
106: mv.visitInsn(DUP);
107: mv.visitMethodInsn(INVOKESPECIAL, "java/lang/AssertionError",
108: "<init>", "()V");
109: mv.visitInsn(ATHROW);
110: mv.visitMaxs(0, 0);
111: mv.visitEnd();
112: }
113:
114: private static class SetAnnotationAdatper extends MethodAdapter
115: implements Opcodes {
116:
117: public SetAnnotationAdatper(MethodVisitor mv) {
118: super (mv);
119: }
120:
121: public void visitInsn(int opcode) {
122: if (RETURN == opcode) {
123: // update the terracotta loader desc for this loader
124: mv.visitVarInsn(ALOAD, 0);
125: mv.visitLdcInsn(Namespace.WEBLOGIC_NAMESPACE);
126: mv.visitVarInsn(ALOAD, 0);
127: mv
128: .visitMethodInsn(
129: INVOKEVIRTUAL,
130: "weblogic/utils/classloaders/GenericClassLoader",
131: "getAnnotation",
132: "()Lweblogic/utils/classloaders/Annotation;");
133: mv.visitMethodInsn(INVOKEVIRTUAL,
134: "weblogic/utils/classloaders/Annotation",
135: "getAnnotationString", "()Ljava/lang/String;");
136: mv
137: .visitMethodInsn(INVOKESTATIC,
138: "com/tc/object/loaders/Namespace",
139: "createLoaderName",
140: "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
141: mv
142: .visitFieldInsn(
143: PUTFIELD,
144: "weblogic/utils/classloaders/GenericClassLoader",
145: LOADER_DESC_FIELD, "Ljava/lang/String;");
146: mv.visitVarInsn(ALOAD, 0);
147: mv
148: .visitMethodInsn(
149: INVOKESTATIC,
150: "com/tc/object/bytecode/hook/impl/ClassProcessorHelper",
151: "registerGlobalLoader",
152: "(Lcom/tc/object/loaders/NamedClassLoader;)V");
153: }
154: super .visitInsn(opcode);
155: }
156:
157: }
158:
159: // for asm code above
160: // void foo() {
161: // ClassProcessorHelper.registerGlobalLoader((NamedClassLoader) this);
162: // }
163:
164: }
|