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.object.bytecode;
006:
007: import com.tc.asm.ClassAdapter;
008: import com.tc.asm.ClassVisitor;
009: import com.tc.asm.Label;
010: import com.tc.asm.MethodVisitor;
011: import com.tc.asm.Opcodes;
012: import com.tc.asm.Type;
013: import com.tc.object.applicator.TCURL;
014:
015: import java.net.URL;
016:
017: public class JavaNetURLAdapter extends ClassAdapter implements Opcodes {
018:
019: public final static String TCSET_METHOD_NAME = "__tc_set";
020: public final static String TCSET_LOGICAL_METHOD_NAME = "__tc_set_logical";
021:
022: public JavaNetURLAdapter(ClassVisitor cv) {
023: super (cv);
024: }
025:
026: public void visit(int version, int access, String name,
027: String signature, String super Name, String[] interfaces) {
028: String[] interfacesNew = new String[interfaces.length + 1];
029: System.arraycopy(interfaces, 0, interfacesNew, 0,
030: interfaces.length);
031: interfacesNew[interfacesNew.length - 1] = TCURL.class.getName()
032: .replace('.', '/');
033: super .visit(version, access, name, signature, super Name,
034: interfacesNew);
035: }
036:
037: public void visitEnd() {
038: createTCSetLogicalMethod();
039: super .visitEnd();
040: }
041:
042: /*
043: * Creates a method like this:
044: *
045: * public void __tc_set_logical(String protocol, String host, int port,
046: * String authority, String userInfo, String path,
047: * String query, String ref) {
048: * synchronized (this) {
049: * if (null == handler) {
050: * handler = getURLStreamHandler(protocol);
051: * }
052: * this.__tc_set(protocol, host, port, authority, userInfo, path, query, ref);
053: * }
054: * }
055: */
056: public void createTCSetLogicalMethod() {
057: MethodVisitor mv = cv
058: .visitMethod(
059: ACC_PUBLIC | ACC_SYNTHETIC,
060: TCSET_LOGICAL_METHOD_NAME,
061: "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
062: null, null);
063: mv.visitCode();
064:
065: // synchronization
066: Label l0 = new Label();
067: Label l1 = new Label();
068: Label l2 = new Label();
069: mv.visitTryCatchBlock(l0, l1, l2, null);
070: Label l3 = new Label();
071: mv.visitTryCatchBlock(l2, l3, l2, null);
072: mv.visitVarInsn(ALOAD, 0);
073: mv.visitInsn(DUP);
074: mv.visitVarInsn(ASTORE, 9);
075: mv.visitInsn(MONITORENTER);
076: mv.visitLabel(l0);
077:
078: // lookup a handler from the protocol if it's null
079: mv.visitVarInsn(ALOAD, 0);
080: mv.visitFieldInsn(GETFIELD, Type.getInternalName(URL.class),
081: "handler", "Ljava/net/URLStreamHandler;");
082: Label labelHandlerNotNull = new Label();
083: mv.visitJumpInsn(IFNONNULL, labelHandlerNotNull);
084: mv.visitVarInsn(ALOAD, 0);
085: mv.visitVarInsn(ALOAD, 1);
086: mv.visitMethodInsn(INVOKESTATIC, Type
087: .getInternalName(URL.class), "getURLStreamHandler",
088: "(Ljava/lang/String;)Ljava/net/URLStreamHandler;");
089: mv.visitFieldInsn(PUTFIELD, Type.getInternalName(URL.class),
090: "handler", "Ljava/net/URLStreamHandler;");
091: mv.visitLabel(labelHandlerNotNull);
092:
093: // use the __tc_set method that is now wrapped by the set method for logical actions
094: mv.visitVarInsn(ALOAD, 0);
095: mv.visitVarInsn(ALOAD, 1);
096: mv.visitVarInsn(ALOAD, 2);
097: mv.visitVarInsn(ILOAD, 3);
098: mv.visitVarInsn(ALOAD, 4);
099: mv.visitVarInsn(ALOAD, 5);
100: mv.visitVarInsn(ALOAD, 6);
101: mv.visitVarInsn(ALOAD, 7);
102: mv.visitVarInsn(ALOAD, 8);
103: mv
104: .visitMethodInsn(
105: INVOKEVIRTUAL,
106: Type.getInternalName(URL.class),
107: TCSET_METHOD_NAME,
108: "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
109:
110: // synchronization
111: mv.visitVarInsn(ALOAD, 9);
112: mv.visitInsn(MONITOREXIT);
113: mv.visitLabel(l1);
114:
115: Label labelReturnSuccessfully = new Label();
116: mv.visitJumpInsn(GOTO, labelReturnSuccessfully);
117: mv.visitLabel(l2);
118: mv.visitVarInsn(ALOAD, 9);
119: mv.visitInsn(MONITOREXIT);
120: mv.visitLabel(l3);
121: mv.visitInsn(ATHROW);
122: mv.visitLabel(labelReturnSuccessfully);
123: mv.visitInsn(RETURN);
124: mv.visitMaxs(9, 10);
125: mv.visitEnd();
126: }
127: }
|