001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.geronimo.transform;
005:
006: import com.tc.asm.ClassAdapter;
007: import com.tc.asm.ClassVisitor;
008: import com.tc.asm.FieldVisitor;
009: import com.tc.asm.MethodAdapter;
010: import com.tc.asm.MethodVisitor;
011: import com.tc.asm.Opcodes;
012: import com.tc.object.bytecode.ByteCodeUtil;
013: import com.tc.object.bytecode.ClassAdapterFactory;
014:
015: /**
016: * Adds NamedClassLoader interface to Geronimo loader, and register it with DSO
017: */
018: public class MultiParentClassLoaderAdapter extends ClassAdapter
019: implements Opcodes, ClassAdapterFactory {
020:
021: private String idDesc;
022:
023: public MultiParentClassLoaderAdapter() {
024: super (null);
025: }
026:
027: private MultiParentClassLoaderAdapter(ClassVisitor cv,
028: ClassLoader caller) {
029: super (cv);
030: }
031:
032: public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) {
033: return new MultiParentClassLoaderAdapter(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:
044: public MethodVisitor visitMethod(int access, String name,
045: String desc, String signature, String[] exceptions) {
046: MethodVisitor mv = super .visitMethod(access, name, desc,
047: signature, exceptions);
048: if ("<init>".equals(name)) {
049: return new CstrVisitor(mv);
050: }
051: return mv;
052: }
053:
054: public void visitEnd() {
055: addNamedClassLoaderMethods();
056: super .visitEnd();
057: }
058:
059: public FieldVisitor visitField(int access, String name,
060: String desc, String signature, Object value) {
061: if ("id".equals(name)) {
062: // the type of the "id" field is different between 1.0 and 1.1
063: idDesc = desc;
064: }
065:
066: return super .visitField(access, name, desc, signature, value);
067: }
068:
069: private void addNamedClassLoaderMethods() {
070: MethodVisitor mv = super .visitMethod(ACC_PUBLIC | ACC_FINAL
071: | ACC_SYNTHETIC, "__tc_getClassLoaderName",
072: "()Ljava/lang/String;", null, null);
073: mv.visitCode();
074: mv.visitFieldInsn(GETSTATIC, "com/tc/object/loaders/Namespace",
075: "GERONIMO_NAMESPACE", "Ljava/lang/String;");
076: mv.visitVarInsn(ALOAD, 0);
077: mv
078: .visitMethodInsn(
079: INVOKEVIRTUAL,
080: "org/apache/geronimo/kernel/config/MultiParentClassLoader",
081: "getId", "()" + idDesc);
082: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
083: "toString", "()Ljava/lang/String;");
084: mv
085: .visitMethodInsn(INVOKESTATIC,
086: "com/tc/object/loaders/Namespace",
087: "createLoaderName",
088: "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
089: mv.visitMethodInsn(INVOKESTATIC,
090: "com/tc/geronimo/GeronimoLoaderNaming", "adjustName",
091: "(Ljava/lang/String;)Ljava/lang/String;");
092:
093: mv.visitInsn(ARETURN);
094: mv.visitMaxs(0, 0);
095: mv.visitEnd();
096:
097: mv = super .visitMethod(ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
098: "__tc_setClassLoaderName", "(Ljava/lang/String;)V",
099: null, null);
100: mv.visitCode();
101: mv.visitTypeInsn(NEW, "java/lang/AssertionError");
102: mv.visitInsn(DUP);
103: mv.visitMethodInsn(INVOKESPECIAL, "java/lang/AssertionError",
104: "<init>", "()V");
105: mv.visitInsn(ATHROW);
106: mv.visitMaxs(0, 0);
107: mv.visitEnd();
108: }
109:
110: private static class CstrVisitor extends MethodAdapter implements
111: Opcodes {
112:
113: public CstrVisitor(MethodVisitor mv) {
114: super (mv);
115: }
116:
117: public void visitInsn(int opcode) {
118: if (opcode == RETURN) {
119: mv.visitVarInsn(ALOAD, 0);
120: mv
121: .visitMethodInsn(
122: INVOKESTATIC,
123: "com/tc/object/bytecode/hook/impl/ClassProcessorHelper",
124: "registerGlobalLoader",
125: "("
126: + ByteCodeUtil.NAMEDCLASSLOADER_TYPE
127: + ")V");
128: }
129: super.visitInsn(opcode);
130: }
131:
132: }
133:
134: }
|