001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.jboss.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:
016: public class UCLAdapter extends ClassAdapter implements Opcodes,
017: ClassAdapterFactory {
018:
019: private static final String LOADER_DESC_FIELD = ByteCodeUtil.TC_FIELD_PREFIX
020: + "loaderDesc";
021: private String owner;
022:
023: public UCLAdapter() {
024: super (null);
025: }
026:
027: private UCLAdapter(ClassVisitor cv, ClassLoader caller) {
028: super (cv);
029: }
030:
031: public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) {
032: return new UCLAdapter(visitor, loader);
033: }
034:
035: public void visit(int version, int access, String name,
036: String signature, String super Name, String[] interfaces) {
037: interfaces = ByteCodeUtil.addInterfaces(interfaces,
038: new String[] { ByteCodeUtil.NAMEDCLASSLOADER_CLASS });
039: super .visit(version, access, name, signature, super Name,
040: interfaces);
041: owner = name;
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:
049: if ("<init>".equals(name)) {
050: mv = new CstrAdapter(mv);
051: }
052:
053: return mv;
054: }
055:
056: public void visitEnd() {
057: addLoaderDescField();
058: addNamedClassLoaderMethods();
059: super .visitEnd();
060: }
061:
062: private void addNamedClassLoaderMethods() {
063: MethodVisitor mv = super .visitMethod(ACC_PUBLIC | ACC_FINAL
064: | ACC_SYNTHETIC, "__tc_setClassLoaderName",
065: "(Ljava/lang/String;)V", null, null);
066: mv
067: .visitTypeInsn(NEW,
068: "java/lang/UnsupportedOperationException");
069: mv.visitInsn(DUP);
070: mv.visitMethodInsn(INVOKESPECIAL,
071: "java/lang/UnsupportedOperationException", "<init>",
072: "()V");
073: mv.visitInsn(ATHROW);
074: mv.visitMaxs(0, 0);
075: mv.visitEnd();
076:
077: mv = super .visitMethod(ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
078: "__tc_getClassLoaderName", "()Ljava/lang/String;",
079: null, null);
080: mv.visitVarInsn(ALOAD, 0);
081: mv.visitFieldInsn(GETFIELD, owner, LOADER_DESC_FIELD,
082: "Ljava/lang/String;");
083: Label l1 = new Label();
084: mv.visitJumpInsn(IFNONNULL, l1);
085: mv
086: .visitTypeInsn(NEW,
087: "java/lang/UnsupportedOperationException");
088: mv.visitInsn(DUP);
089: mv.visitTypeInsn(NEW, "java/lang/StringBuffer");
090: mv.visitInsn(DUP);
091: mv.visitLdcInsn("Classes from this loader cannot be shared ");
092: mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuffer",
093: "<init>", "(Ljava/lang/String;)V");
094: mv.visitVarInsn(ALOAD, 0);
095: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
096: "toString", "()Ljava/lang/String;");
097: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
098: "append",
099: "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
100: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer",
101: "toString", "()Ljava/lang/String;");
102: mv.visitMethodInsn(INVOKESPECIAL,
103: "java/lang/UnsupportedOperationException", "<init>",
104: "(Ljava/lang/String;)V");
105: mv.visitInsn(ATHROW);
106: mv.visitLabel(l1);
107: mv.visitVarInsn(ALOAD, 0);
108: mv.visitFieldInsn(GETFIELD, owner, LOADER_DESC_FIELD,
109: "Ljava/lang/String;");
110: mv.visitInsn(ARETURN);
111: mv.visitMaxs(0, 0);
112: mv.visitEnd();
113: }
114:
115: private void addLoaderDescField() {
116: super .visitField(ACC_SYNTHETIC | ACC_TRANSIENT | ACC_PRIVATE
117: | ACC_FINAL, LOADER_DESC_FIELD, "Ljava/lang/String;",
118: null, null);
119: }
120:
121: private class CstrAdapter extends MethodAdapter implements Opcodes {
122:
123: public CstrAdapter(MethodVisitor mv) {
124: super (mv);
125: }
126:
127: public void visitInsn(int opcode) {
128: if (RETURN == opcode) {
129: assignLoaderDesc();
130:
131: super .visitVarInsn(ALOAD, 0);
132: super .visitFieldInsn(GETFIELD, owner,
133: LOADER_DESC_FIELD, "Ljava/lang/String;");
134: Label isNull = new Label();
135: super .visitJumpInsn(IFNULL, isNull);
136: super .visitVarInsn(ALOAD, 0);
137: super
138: .visitMethodInsn(
139: INVOKESTATIC,
140: "com/tc/object/bytecode/hook/impl/ClassProcessorHelper",
141: "registerGlobalLoader",
142: "(Lcom/tc/object/loaders/NamedClassLoader;)V");
143: super .visitLabel(isNull);
144: }
145:
146: super .visitInsn(opcode);
147: }
148:
149: private void assignLoaderDesc() {
150: super .visitVarInsn(ALOAD, 0);
151: super .visitVarInsn(ALOAD, 0);
152: super .visitMethodInsn(INVOKESTATIC,
153: "com/tc/jboss/JBossLoaderNaming", "getLoaderName",
154: "(Ljava/lang/ClassLoader;)Ljava/lang/String;");
155: super .visitFieldInsn(PUTFIELD, owner, LOADER_DESC_FIELD,
156: "Ljava/lang/String;");
157: }
158:
159: }
160:
161: }
|