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 org.terracotta.modules.cglib_2_1_3;
006:
007: import org.osgi.framework.Bundle;
008: import org.terracotta.modules.cglib_2_1_3.util.FilterTCMethods;
009:
010: import com.tc.asm.ClassAdapter;
011: import com.tc.asm.ClassReader;
012: import com.tc.asm.ClassVisitor;
013: import com.tc.asm.MethodAdapter;
014: import com.tc.asm.MethodVisitor;
015: import com.tc.asm.Opcodes;
016: import com.tc.asm.tree.ClassNode;
017: import com.tc.asm.tree.MethodNode;
018: import com.tc.exception.TCRuntimeException;
019: import com.tc.object.bytecode.ClassAdapterFactory;
020: import com.tc.object.util.JarResourceLoader;
021:
022: import java.io.ByteArrayOutputStream;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.net.URL;
026: import java.util.Iterator;
027: import java.util.List;
028:
029: public class CGLibProxyEnhancerAdapter extends ClassAdapter implements
030: ClassAdapterFactory, Opcodes {
031: private final ClassLoader caller;
032: private final Bundle bundle;
033:
034: public CGLibProxyEnhancerAdapter(Bundle bundle) {
035: super (null);
036: this .caller = null;
037: this .bundle = bundle;
038: }
039:
040: private CGLibProxyEnhancerAdapter(ClassVisitor cv,
041: ClassLoader caller, Bundle bundle) {
042: super (cv);
043: this .caller = caller;
044: this .bundle = bundle;
045: }
046:
047: public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) {
048: return new CGLibProxyEnhancerAdapter(visitor, loader, bundle);
049: }
050:
051: public MethodVisitor visitMethod(int access, String name,
052: String desc, String signature, String[] exceptions) {
053: // public final Object intercept(Object object, Method method, Object args[], MethodProxy proxy)
054:
055: MethodVisitor mv = super .visitMethod(access, name, desc,
056: signature, exceptions);
057: if ("getMethods".equals(name)
058: && "(Ljava/lang/Class;[Ljava/lang/Class;Ljava/util/List;Ljava/util/List;Ljava/util/Set;)V"
059: .equals(desc)) { //
060: return new InterceptAdapter(mv);
061: }
062: return mv;
063: }
064:
065: public void visitEnd() {
066: addFilterMethod();
067: super .visitEnd();
068: }
069:
070: private void addFilterMethod() {
071: try {
072: byte[] bytes = getBytesForClass(bundle,
073: FilterTCMethods.class);
074: ClassReader tcCR = new ClassReader(bytes);
075: ClassNode tcCN = new ClassNode();
076: tcCR.accept(tcCN, ClassReader.SKIP_DEBUG
077: | ClassReader.SKIP_FRAMES);
078:
079: List tcMethods = tcCN.methods;
080: for (Iterator i = tcMethods.iterator(); i.hasNext();) {
081: MethodNode mNode = (MethodNode) i.next();
082: if (!"<init>".equals(mNode.name)) {
083: mNode.accept(cv);
084: }
085: }
086: } catch (ClassNotFoundException e) {
087: throw new TCRuntimeException(e);
088: }
089: }
090:
091: public byte[] getBytesForClass(final Bundle bundle, Class clazz)
092: throws ClassNotFoundException {
093: String className = clazz.getName().replace('.', '/') + ".class";
094: InputStream is = null;
095: ByteArrayOutputStream baos = null;
096: try {
097: is = JarResourceLoader.getJarResource(new URL(bundle
098: .getLocation()), className);
099: if (is == null) {
100: throw new ClassNotFoundException(
101: "No resource found for class: " + className);
102: }
103: final int size = 4096;
104: byte[] buffer = new byte[size];
105: baos = new ByteArrayOutputStream(size);
106:
107: int read;
108:
109: while ((read = is.read(buffer, 0, size)) > 0) {
110: baos.write(buffer, 0, read);
111: }
112: } catch (IOException ioe) {
113: throw new ClassNotFoundException("Error reading bytes for "
114: + className, ioe);
115: } finally {
116: if (is != null) {
117: try {
118: is.close();
119: } catch (IOException ioe) {
120: // ignore
121: }
122: }
123: }
124:
125: return baos.toByteArray();
126: }
127:
128: private static class InterceptAdapter extends MethodAdapter
129: implements Opcodes {
130:
131: public InterceptAdapter(MethodVisitor mv) {
132: super (mv);
133: }
134:
135: public void visitInsn(int opcode) {
136: if (RETURN == opcode) {
137: mv.visitVarInsn(ALOAD, 2);
138: mv.visitMethodInsn(INVOKESTATIC,
139: "net/sf/cglib/proxy/Enhancer",
140: "filterTCMethods", "(Ljava/util/Collection;)V");
141: }
142: super.visitInsn(opcode);
143: }
144: }
145:
146: }
|