From df8d0534cd22effae9dfadc68f7c4bd553f9bb24 Mon Sep 17 00:00:00 2001 From: aclement Date: Mon, 2 May 2011 18:38:42 +0000 Subject: [PATCH] 328099 --- .../src/org/aspectj/weaver/loadtime/Aj.java | 18 ++++--- .../loadtime/ClassLoaderWeavingAdaptor.java | 54 ++++++++++++++++--- .../weaver/loadtime/ClassPreProcessor.java | 35 ++++++------ .../aspectj/weaver/loadtime/JRockitAgent.java | 54 +++++++++---------- 4 files changed, 106 insertions(+), 55 deletions(-) diff --git a/loadtime/src/org/aspectj/weaver/loadtime/Aj.java b/loadtime/src/org/aspectj/weaver/loadtime/Aj.java index db5337e38..3582da871 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/Aj.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/Aj.java @@ -13,6 +13,7 @@ package org.aspectj.weaver.loadtime; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; +import java.security.ProtectionDomain; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -73,7 +74,7 @@ public class Aj implements ClassPreProcessor { * @param loader * @return weaved bytes */ - public byte[] preProcess(String className, byte[] bytes, ClassLoader loader) { + public byte[] preProcess(String className, byte[] bytes, ClassLoader loader, ProtectionDomain protectionDomain) { // TODO AV needs to doc that if (loader == null || className == null || loader.getClass().getName().equals(deleLoader)) { // skip boot loader, null classes (hibernate), or those from a reflection loader @@ -93,11 +94,16 @@ public class Aj implements ClassPreProcessor { trace.exit("preProcess"); return bytes; } - byte[] newBytes = weavingAdaptor.weaveClass(className, bytes, false); - Dump.dumpOnExit(weavingAdaptor.getMessageHolder(), true); - if (trace.isTraceEnabled()) - trace.exit("preProcess", newBytes); - return newBytes; + try { + weavingAdaptor.setActiveProtectionDomain(protectionDomain); + byte[] newBytes = weavingAdaptor.weaveClass(className, bytes, false); + Dump.dumpOnExit(weavingAdaptor.getMessageHolder(), true); + if (trace.isTraceEnabled()) + trace.exit("preProcess", newBytes); + return newBytes; + } finally { + weavingAdaptor.setActiveProtectionDomain(null); + } } /* Don't like to do this but JVMTI swallows all exceptions */ diff --git a/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java b/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java index 13d2bccbb..cf3229035 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java @@ -19,6 +19,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; +import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; @@ -137,8 +138,12 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { } catch (Throwable throwable) { throwable.printStackTrace(); } + if (activeProtectionDomain != null) { + defineClass(loaderRef.getClassLoader(), name, bytes, activeProtectionDomain); + } else { + defineClass(loaderRef.getClassLoader(), name, bytes); // could be done lazily using the hook - defineClass(loaderRef.getClassLoader(), name, bytes); // could be done lazily using the hook + } } } @@ -977,6 +982,9 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { generatedClasses = new HashMap(); } + private Method defineClassMethod; + private Method defineClassWithProtectionDomainMethod; + private void defineClass(ClassLoader loader, String name, byte[] bytes) { if (trace.isTraceEnabled()) { trace.enter("defineClass", this, new Object[] { loader, name, bytes }); @@ -985,11 +993,45 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { debug("generating class '" + name + "'"); try { - // TODO av protection domain, and optimize - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] { String.class, bytes.getClass(), - int.class, int.class }); - defineClass.setAccessible(true); - clazz = defineClass.invoke(loader, new Object[] { name, bytes, new Integer(0), new Integer(bytes.length) }); + if (defineClassMethod == null) { + defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] { String.class, + bytes.getClass(), int.class, int.class }); + } + defineClassMethod.setAccessible(true); + clazz = defineClassMethod.invoke(loader, new Object[] { name, bytes, new Integer(0), new Integer(bytes.length) }); + } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof LinkageError) { + warn("define generated class failed", e.getTargetException()); + // is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved) + // TODO maw I don't think this is OK and + } else { + warn("define generated class failed", e.getTargetException()); + } + } catch (Exception e) { + warn("define generated class failed", e); + } + + if (trace.isTraceEnabled()) { + trace.exit("defineClass", clazz); + } + } + + private void defineClass(ClassLoader loader, String name, byte[] bytes, ProtectionDomain protectionDomain) { + if (trace.isTraceEnabled()) { + trace.enter("defineClass", this, new Object[] { loader, name, bytes, protectionDomain }); + } + Object clazz = null; + debug("generating class '" + name + "'"); + + try { + // System.out.println(">> Defining with protection domain " + name + " pd=" + protectionDomain); + if (defineClassWithProtectionDomainMethod == null) { + defineClassWithProtectionDomainMethod = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] { + String.class, bytes.getClass(), int.class, int.class, ProtectionDomain.class }); + } + defineClassWithProtectionDomainMethod.setAccessible(true); + clazz = defineClassWithProtectionDomainMethod.invoke(loader, new Object[] { name, bytes, new Integer(0), + new Integer(bytes.length), protectionDomain }); } catch (InvocationTargetException e) { if (e.getTargetException() instanceof LinkageError) { warn("define generated class failed", e.getTargetException()); diff --git a/loadtime/src/org/aspectj/weaver/loadtime/ClassPreProcessor.java b/loadtime/src/org/aspectj/weaver/loadtime/ClassPreProcessor.java index d50f59549..12e620215 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/ClassPreProcessor.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/ClassPreProcessor.java @@ -11,26 +11,29 @@ *******************************************************************************/ package org.aspectj.weaver.loadtime; +import java.security.ProtectionDomain; + /** - * Generic class pre processor interface that allows to separate the AspectJ 5 load time weaving - * from Java 5 JVMTI interfaces for further use on Java 1.3 / 1.4 - * + * Generic class pre processor interface that allows to separate the AspectJ 5 load time weaving from Java 5 JVMTI interfaces for + * further use on Java 1.3 / 1.4 + * * @author Alexandre Vasseur */ public interface ClassPreProcessor { - /** - * Post constructor initialization, usually empty - */ - void initialize(); + /** + * Post constructor initialization, usually empty + */ + void initialize(); - /** - * Weave - * - * @param className - * @param bytes - * @param classLoader - * @return - */ - byte[] preProcess(String className, byte[] bytes, ClassLoader classLoader); + /** + * Weave + * + * @param className + * @param bytes + * @param classLoader + * @param a protection domain that may be used for defining extraneous classes generated as part of modifying the one passed in + * @return + */ + byte[] preProcess(String className, byte[] bytes, ClassLoader classLoader, ProtectionDomain protectionDomain); } \ No newline at end of file diff --git a/loadtime/src/org/aspectj/weaver/loadtime/JRockitAgent.java b/loadtime/src/org/aspectj/weaver/loadtime/JRockitAgent.java index 667b74e04..56ad0e958 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/JRockitAgent.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/JRockitAgent.java @@ -16,66 +16,66 @@ import com.bea.jvm.ClassLibrary; import com.bea.jvm.JVMFactory; /** - * BEA JRocket JMAPI agent. + * BEA JRocket JMAPI agent. * * Use "-Xmanagement:class=org.aspectj.weaver.loadtime.JRockitAgent" */ public class JRockitAgent implements com.bea.jvm.ClassPreProcessor { private ClassPreProcessor preProcessor; - + /* - * This is used to implement the recursion protection offered by JVMTI - * but not by JRockit JMAPI. I we are called to preProcess a class while - * already preProcessing another we will return immediately + * This is used to implement the recursion protection offered by JVMTI but not by JRockit JMAPI. I we are called to preProcess a + * class while already preProcessing another we will return immediately */ private static ThreadLocalStack stack = new ThreadLocalStack(); - - - public JRockitAgent () { + + public JRockitAgent() { this.preProcessor = new Aj(); - - ClassLibrary cl = JVMFactory.getJVM().getClassLibrary(); - cl.setClassPreProcessor(this); + + ClassLibrary cl = JVMFactory.getJVM().getClassLibrary(); + cl.setClassPreProcessor(this); } - + public byte[] preProcess(ClassLoader loader, String className, byte[] bytes) { byte[] newBytes = bytes; if (stack.empty()) { stack.push(className); - newBytes = preProcessor.preProcess(className, bytes, loader); + newBytes = preProcessor.preProcess(className, bytes, loader, null); stack.pop(); } - + return newBytes; } private static class ThreadLocalStack extends ThreadLocal { - public boolean empty () { - Stack stack = (Stack)get(); + public boolean empty() { + Stack stack = (Stack) get(); return stack.empty(); } - public Object peek () { + public Object peek() { Object obj = null; - Stack stack = (Stack)get(); - if (!stack.empty()) obj = stack.peek(); + Stack stack = (Stack) get(); + if (!stack.empty()) + obj = stack.peek(); return obj; } - - public void push (Object obj) { - Stack stack = (Stack)get(); - if (!stack.empty() && obj == stack.peek()) throw new RuntimeException(obj.toString()); + + public void push(Object obj) { + Stack stack = (Stack) get(); + if (!stack.empty() && obj == stack.peek()) + throw new RuntimeException(obj.toString()); stack.push(obj); } - - public Object pop () { - Stack stack = (Stack)get(); + + public Object pop() { + Stack stack = (Stack) get(); return stack.pop(); } - + protected Object initialValue() { return new Stack(); } -- 2.39.5