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.tomcat.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 CatalinaAdapter extends ClassAdapter implements Opcodes,
017: ClassAdapterFactory {
018:
019: private static final String INJECT_CLASSES = ByteCodeUtil.TC_METHOD_PREFIX
020: + "injectClasses";
021:
022: public CatalinaAdapter() {
023: super (null);
024: }
025:
026: private CatalinaAdapter(ClassVisitor cv, ClassLoader caller) {
027: super (cv);
028: }
029:
030: public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) {
031: return new CatalinaAdapter(visitor, loader);
032: }
033:
034: public MethodVisitor visitMethod(int access, String name,
035: String desc, String signature, String[] exceptions) {
036: MethodVisitor mv = super .visitMethod(access, name, desc,
037: signature, exceptions);
038:
039: if ("start".equals(name) && "()V".equals(desc)) {
040: return new StartAdapter(mv);
041: } else if ("<clinit>".equals(name)) {
042: return new CLInitMethodAdapter(mv);
043: }
044:
045: return mv;
046: }
047:
048: public void visitEnd() {
049: addInjectClassesMethod();
050: }
051:
052: private void addInjectClassesMethod() {
053: MethodVisitor mv = visitMethod(ACC_PRIVATE + ACC_STATIC
054: + ACC_SYNTHETIC, INJECT_CLASSES, "()V", null, null);
055: mv.visitCode();
056: Label l0 = new Label();
057: Label l1 = new Label();
058: Label l2 = new Label();
059: mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Exception");
060: mv.visitLabel(l0);
061: mv.visitLdcInsn("org.apache.catalina.startup.Catalina");
062: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Class", "forName",
063: "(Ljava/lang/String;)Ljava/lang/Class;");
064: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class",
065: "getClassLoader", "()Ljava/lang/ClassLoader;");
066: mv.visitMethodInsn(INVOKESTATIC,
067: "com/tc/object/bytecode/hook/impl/SessionsHelper",
068: "injectClasses", "(Ljava/lang/ClassLoader;)V");
069: mv.visitLabel(l1);
070: Label l3 = new Label();
071: mv.visitJumpInsn(GOTO, l3);
072: mv.visitLabel(l2);
073: mv.visitVarInsn(ASTORE, 0);
074: mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
075: mv.visitInsn(DUP);
076: mv.visitVarInsn(ALOAD, 0);
077: mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException",
078: "<init>", "(Ljava/lang/Throwable;)V");
079: mv.visitInsn(ATHROW);
080: mv.visitLabel(l3);
081: mv.visitInsn(RETURN);
082: mv.visitMaxs(0, 0);
083: mv.visitEnd();
084: }
085:
086: private static class CLInitMethodAdapter extends MethodAdapter
087: implements Opcodes {
088:
089: public CLInitMethodAdapter(MethodVisitor mv) {
090: super (mv);
091: }
092:
093: public void visitInsn(int opcode) {
094: if (opcode == Opcodes.RETURN) {
095: super .visitMethodInsn(INVOKESTATIC,
096: "org/apache/catalina/startup/Catalina",
097: INJECT_CLASSES, "()V");
098: }
099: super .visitInsn(opcode);
100: }
101: }
102:
103: private static class StartAdapter extends MethodAdapter implements
104: Opcodes {
105:
106: public StartAdapter(MethodVisitor mv) {
107: super (mv);
108: }
109:
110: public void visitInsn(int opcode) {
111: if (opcode == RETURN) {
112: super .visitVarInsn(ALOAD, 0);
113: super .visitFieldInsn(GETFIELD,
114: "org/apache/catalina/startup/Catalina",
115: "await", "Z");
116: Label notAwait = new Label();
117: super .visitJumpInsn(IFEQ, notAwait);
118: super
119: .visitMethodInsn(
120: INVOKESTATIC,
121: "com/tc/object/bytecode/hook/impl/ClassProcessorHelper",
122: "shutdown", "()V");
123: super.visitLabel(notAwait);
124: }
125: super.visitInsn(opcode);
126: }
127: }
128:
129: }
|