diff options
author | Stephan Herrmann | 2017-01-14 22:56:33 +0000 |
---|---|---|
committer | Stephan Herrmann | 2017-01-14 23:13:41 +0000 |
commit | 22d1e4c575f50ec2962cc27ff61216448e22a4e0 (patch) | |
tree | b3ce85945e4677ee514d480aca365e7bc7bd7173 | |
parent | bee08857b4e28094514d94f1173828350a399d6c (diff) | |
download | org.eclipse.objectteams-22d1e4c575f50ec2962cc27ff61216448e22a4e0.tar.gz org.eclipse.objectteams-22d1e4c575f50ec2962cc27ff61216448e22a4e0.tar.xz org.eclipse.objectteams-22d1e4c575f50ec2962cc27ff61216448e22a4e0.zip |
Bug 510471: Avoid use of global flag -Dot.weaving
8 files changed, 134 insertions, 24 deletions
diff --git a/plugins/org.eclipse.objectteams.otequinox/META-INF/p2.inf b/plugins/org.eclipse.objectteams.otequinox/META-INF/p2.inf index 8b205486c..adddf908e 100644 --- a/plugins/org.eclipse.objectteams.otequinox/META-INF/p2.inf +++ b/plugins/org.eclipse.objectteams.otequinox/META-INF/p2.inf @@ -40,9 +40,8 @@ units.0.instructions.uninstall=\ uninstallBundle(bundle:${artifact}) instructions.install = \ - addJvmArg(jvmArg:-Dot.weaving=otdre); \ + removeJvmArg(jvmArg:-Dot.weaving=otdre); \ addJvmArg(jvmArg:-javaagent:${artifact.location}/otequinoxAgent.jar); instructions.uninstall = \ - removeJvmArg(jvmArg:-Dot.weaving=otdre); \ removeJvmArg(jvmArg:-javaagent:${artifact.location}/otequinoxAgent.jar);
\ No newline at end of file diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ASMByteCodeAnalyzer.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ASMByteCodeAnalyzer.java index c698da993..d55bf4c26 100644 --- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ASMByteCodeAnalyzer.java +++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ASMByteCodeAnalyzer.java @@ -21,7 +21,13 @@ import java.io.InputStream; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.objectteams.internal.osgi.weaving.OTWeavingHook.WeavingScheme;
+import org.eclipse.objectteams.otredyn.bytecode.asm.Attributes;
+import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
/**
@@ -99,4 +105,55 @@ public class ASMByteCodeAnalyzer { classInformationMap.put(className, classInformation);
return classInformation;
}
+
+ public static WeavingScheme determineWeavingScheme(byte[] classBytes, String className) {
+ return determineWeavingScheme(classBytes, null, className);
+ }
+ public static @NonNull WeavingScheme determineWeavingScheme(InputStream classStream, String className) {
+ return determineWeavingScheme(null, classStream, className);
+ }
+ static @NonNull WeavingScheme determineWeavingScheme(byte[] classBytes, InputStream classStream, String className) {
+
+ class OTCompilerVersion extends Attribute {
+ WeavingScheme weavingScheme;
+ public OTCompilerVersion() {
+ super(Attributes.ATTRIBUTE_OT_COMPILER_VERSION);
+ }
+ @Override
+ protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
+ int encodedVersion = cr.readUnsignedShort(off);
+ weavingScheme = ((encodedVersion & Attributes.OTDRE_FLAG) != 0) ? WeavingScheme.OTDRE : WeavingScheme.OTRE;
+ return this;
+ }
+ }
+ class MyClassVisitor extends ClassVisitor {
+ OTCompilerVersion compilerVersion;
+
+ private MyClassVisitor() {
+ super(org.eclipse.objectteams.otredyn.bytecode.asm.AsmBoundClass.ASM_API);
+ }
+
+ @Override
+ public void visitAttribute(Attribute attr) {
+ if (attr instanceof OTCompilerVersion)
+ compilerVersion = (OTCompilerVersion) attr;
+ }
+ }
+
+ try {
+ ClassReader classReader = classBytes != null ? new ClassReader(classBytes) : new ClassReader(classStream);
+ // TODO: consider optimizing by copying reduced internals
+ MyClassVisitor classVisitor = new MyClassVisitor();
+ classReader.accept(classVisitor, new Attribute[] { new OTCompilerVersion() }, ClassReader.SKIP_CODE);
+ OTCompilerVersion version = classVisitor.compilerVersion;
+ if (version != null) {
+ WeavingScheme scheme = version.weavingScheme;
+ if (scheme != null)
+ return scheme;
+ }
+ } catch (IOException e) {
+ // ignore
+ }
+ return WeavingScheme.Unknown;
+ }
}
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java index cc6f1ef72..fc5cc8545 100644 --- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java +++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java @@ -18,6 +18,8 @@ package org.eclipse.objectteams.internal.osgi.weaving; import static org.eclipse.objectteams.otequinox.TransformerPlugin.log; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -31,6 +33,7 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.objectteams.internal.osgi.weaving.OTWeavingHook.WeavingScheme; import org.eclipse.objectteams.internal.osgi.weaving.Util.ProfileKind; import org.eclipse.objectteams.otequinox.ActivationKind; import org.eclipse.objectteams.otequinox.AspectPermission; @@ -40,6 +43,7 @@ import org.osgi.framework.Bundle; import org.osgi.framework.hooks.weaving.WovenClass; import org.osgi.framework.namespace.PackageNamespace; import org.osgi.framework.wiring.BundleRevision; +import org.osgi.framework.wiring.BundleWiring; import org.osgi.resource.Capability; /** @@ -276,6 +280,7 @@ public class AspectBinding { public boolean hasScannedTeams; public AspectPermission forcedExportsPermission = AspectPermission.UNDEFINED; public boolean hasBeenDenied = false; + public WeavingScheme weavingScheme = WeavingScheme.Unknown; Set<TeamBinding> teamsInProgress = new HashSet<>(); // TODO cleanup teams that are done @@ -299,9 +304,27 @@ public class AspectBinding { } catch (IllegalArgumentException iae) { log(iae, "Invalid activation kind "+activationSpecifier+" for team "+teamName); } + checkWeavingScheme(teamName); return this.teams[count] = new TeamBinding(teamName, kind, superTeamName); } + private void checkWeavingScheme(String className) { + if (this.weavingScheme != WeavingScheme.Unknown) + return; + Bundle bundle = this.aspectBundle; + if (bundle == null) + return; + BundleWiring wiring = bundle.adapt(BundleWiring.class); + try (InputStream classStream = wiring.getClassLoader().getResourceAsStream(className.replace('.', '/')+".class")) { + this.weavingScheme = ASMByteCodeAnalyzer.determineWeavingScheme(classStream, className); + if (OTWeavingHook.DEFAULT_WEAVING_SCHEME == WeavingScheme.Unknown) + OTWeavingHook.DEFAULT_WEAVING_SCHEME = this.weavingScheme; + TransformerPlugin.log(IStatus.INFO, "use weaving scheme "+this.weavingScheme+" for aspectBinding "+this.aspectPlugin+"<-"+this.basePluginName); + } catch (IOException e) { + // ignore + } + } + /** Connect all resolvable info in all contained TeamBindings using the given lookup table. */ public void connect(Map<String, Set<TeamBinding>> teamLookup) { for (int i = 0; i < teams.length; i++) { diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java index c14dbed33..8298409a6 100644 --- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java +++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java @@ -23,9 +23,11 @@ import java.util.List; import java.util.Set; import org.eclipse.core.runtime.IStatus; +import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.objectteams.internal.osgi.weaving.AspectBinding.BaseBundle; +import org.eclipse.objectteams.internal.osgi.weaving.OTWeavingHook.WeavingScheme; import org.osgi.framework.Bundle; import org.osgi.framework.hooks.weaving.WovenClass; @@ -54,6 +56,19 @@ public class BaseBundleLoadTrigger { this.admin = admin; } + WeavingScheme getWeavingScheme() { + @NonNull WeavingScheme scheme = OTWeavingHook.DEFAULT_WEAVING_SCHEME; + for (AspectBinding aspectBinding : aspectBindings) { + if (aspectBinding.weavingScheme != WeavingScheme.Unknown) { + scheme = aspectBinding.weavingScheme; + if (OTWeavingHook.DEFAULT_WEAVING_SCHEME == WeavingScheme.Unknown) + OTWeavingHook.DEFAULT_WEAVING_SCHEME = scheme; + break; + } + } + return scheme; + } + /** * Signal that the given class is being loaded and trigger any necessary steps: * (1) add import to OTRE (now) @@ -65,12 +80,12 @@ public class BaseBundleLoadTrigger { public void fire(WovenClass baseClass, Set<String> beingDefined, OTWeavingHook hook) { // (1) OTRE import added once per base bundle: - boolean useDynamicWeaver = OTWeavingHook.USE_DYNAMIC_WEAVER; + WeavingScheme weavingScheme = getWeavingScheme(); synchronized(this) { final BaseBundle baseBundle2 = baseBundle; if (!otreAdded) { otreAdded = true; - addOTREImport(baseBundle2, baseBundleName, baseClass, useDynamicWeaver); + addOTREImport(baseBundle2, baseBundleName, baseClass, weavingScheme == WeavingScheme.OTDRE); } } @@ -100,18 +115,18 @@ public class BaseBundleLoadTrigger { } // (2) scan all teams in affecting aspect bindings: if (!aspectBinding.hasScannedTeams) { - Collection<String> boundBases = aspectBinding.scanTeamClasses(aspectBundle, DelegatingTransformer.newTransformer(useDynamicWeaver, hook, baseClass.getBundleWiring())); + Collection<String> boundBases = aspectBinding.scanTeamClasses(aspectBundle, DelegatingTransformer.newTransformer(weavingScheme, hook, baseClass.getBundleWiring())); aspectBindingRegistry.addBoundBaseClasses(boundBases); } // (3) add dependencies to the base bundle: - if (!useDynamicWeaver) // OTDRE access aspects by generic interface in o.o.Team + if (weavingScheme == WeavingScheme.OTRE) // OTDRE accesses aspects by generic interface in o.o.Team aspectBinding.addImports(baseClass); } } // (4) try optional steps concerning all teams for this base (across all involved aspect bindings): - TeamLoader loading = new TeamLoader(deferredTeamClasses, beingDefined, useDynamicWeaver); + TeamLoader loading = new TeamLoader(deferredTeamClasses, beingDefined, weavingScheme == WeavingScheme.OTDRE); final BaseBundle baseBundle3 = this.baseBundle; if (baseBundle3 != null) { loading.loadTeamsForBase(baseBundle3, baseClass, hook.getAspectPermissionManager()); diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java index cf12392e2..5c82a8ee9 100644 --- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java +++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java @@ -27,6 +27,7 @@ import java.util.Collection; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.objectteams.internal.osgi.weaving.OTWeavingHook.WeavingReason; +import org.eclipse.objectteams.internal.osgi.weaving.OTWeavingHook.WeavingScheme; import org.eclipse.objectteams.internal.osgi.weaving.Util.ProfileKind; import org.eclipse.objectteams.otredyn.bytecode.IRedefineStrategy; import org.eclipse.objectteams.otredyn.bytecode.RedefineStrategyFactory; @@ -41,11 +42,15 @@ import org.osgi.framework.wiring.BundleWiring; public abstract class DelegatingTransformer { /** Factory method for a fresh transformer. */ - static @NonNull DelegatingTransformer newTransformer(boolean useDynamicWeaver, OTWeavingHook hook, BundleWiring wiring) { - if (useDynamicWeaver) - return new OTDRETransformer(getWeavingContext(hook, wiring)); - else - return new OTRETransformer(); + static @NonNull DelegatingTransformer newTransformer(WeavingScheme weavingScheme, OTWeavingHook hook, BundleWiring wiring) { + switch (weavingScheme) { + case OTDRE: + return new OTDRETransformer(getWeavingContext(hook, wiring)); + case OTRE: + return new OTRETransformer(); + default: + throw new NullPointerException("WeavingScheme must be defined"); + } } private static class OTRETransformer extends DelegatingTransformer { diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java index 631c88410..be962e811 100644 --- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java +++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java @@ -74,16 +74,23 @@ import org.osgi.resource.Wire; */ public class OTWeavingHook implements WeavingHook, WovenClassListener { + static @NonNull WeavingScheme DEFAULT_WEAVING_SCHEME = WeavingScheme.Unknown; + enum WeavingScheme { Unknown, OTRE, OTDRE }; - // TODO: this master-switch, which selects the weaver, should probably be replaced by s.t. else? - static final boolean USE_DYNAMIC_WEAVER; static final ThreadWeaving WEAVE_THREAD_NOTIFICATION; enum ThreadWeaving { Never, Base, Always } + static final Map<String,Set<String>> KNOWN_LOGGING_CLASSES = new HashMap<>(); + static { - String weaving = System.getProperty("ot.weaving"); -System.err.println("OT/Equinox: ot.weaving="+weaving); - USE_DYNAMIC_WEAVER = (weaving != null) && weaving.toLowerCase().equals("otdre"); + String weaving = System.getProperty("ot.weaving.force"); + if (weaving != null) { + System.err.println("OT/Equinox: ot.weaving.force="+weaving); + if ("otdre".equalsIgnoreCase(weaving)) + DEFAULT_WEAVING_SCHEME = WeavingScheme.OTDRE; + else if ("otre".equalsIgnoreCase(weaving)) + DEFAULT_WEAVING_SCHEME = WeavingScheme.OTRE; + } String threadWeaving = System.getProperty("otequinox.weave.thread"); if ("base".equalsIgnoreCase(threadWeaving)) WEAVE_THREAD_NOTIFICATION = ThreadWeaving.Base; @@ -265,13 +272,17 @@ System.err.println("OT/Equinox: ot.weaving="+weaving); if (reason == WeavingReason.Base && allAspectsAreDenied) { return; // don't weave for denied bindings } else if (reason == WeavingReason.Thread) { + if (DEFAULT_WEAVING_SCHEME == WeavingScheme.Unknown) { + log(IStatus.WARNING, "Not performing thread weaving for "+className+" (weaving scheme not yet knonw)"); + return; + } BaseBundle baseBundle = this.aspectBindingRegistry.getBaseBundle(bundleName); - BaseBundleLoadTrigger.addOTREImport(baseBundle, bundleName, wovenClass, USE_DYNAMIC_WEAVER); + BaseBundleLoadTrigger.addOTREImport(baseBundle, bundleName, wovenClass, DEFAULT_WEAVING_SCHEME == WeavingScheme.OTDRE); } long time = 0; - DelegatingTransformer transformer = DelegatingTransformer.newTransformer(USE_DYNAMIC_WEAVER, this, bundleWiring); + DelegatingTransformer transformer = DelegatingTransformer.newTransformer(DEFAULT_WEAVING_SCHEME, this, bundleWiring); Class<?> classBeingRedefined = null; // TODO prepare for otre-dyn try { String displayName = reason+" class "+className; @@ -460,7 +471,7 @@ System.err.println("OT/Equinox: ot.weaving="+weaving); String teamName = record.team.teamName; log(IStatus.INFO, "Consider for instantiation/activation: team "+teamName); try { - TeamLoader loader = new TeamLoader(deferredTeams, beingDefined, USE_DYNAMIC_WEAVER); + TeamLoader loader = new TeamLoader(deferredTeams, beingDefined, DEFAULT_WEAVING_SCHEME == WeavingScheme.OTDRE); // Instantiate (we only get here if activationKind != NONE) loader.instantiateAndActivate(record.aspectBinding, record.team, record.activationKind); // may re-insert to deferredTeams } catch (Exception e) { diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmBoundClass.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmBoundClass.java index 9a9e905d6..d9e5917af 100644 --- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmBoundClass.java +++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmBoundClass.java @@ -32,7 +32,7 @@ import org.objectweb.asm.Opcodes; * It parses the bytecode with ASM.
* @author Oliver Frank
*/
-abstract class AsmBoundClass extends AbstractTeam {
+public abstract class AsmBoundClass extends AbstractTeam {
public static final int ASM_API = Opcodes.ASM5;
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java index 56adc3238..affd6854f 100644 --- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java +++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java @@ -33,15 +33,15 @@ import org.objectweb.asm.Label; * This class contains all classes representing OT/J class file attributes
* @author Oliver Frank
*/
-abstract class Attributes {
+public abstract class Attributes {
protected final static String ATTRIBUTE_OT_DYN_CALLIN_BINDINGS="OTDynCallinBindings";
protected final static String ATTRIBUTE_ROLE_BASE_BINDINGS = "CallinRoleBaseBindings";
protected final static String ATTRIBUTE_CALLIN_PRECEDENCE = "CallinPrecedence";
protected final static String ATTRIBUTE_OT_CLASS_FLAGS = "OTClassFlags";
protected final static String ATTRIBUTE_OT_SPECIAL_ACCESS = "OTSpecialAccess";
- protected final static String ATTRIBUTE_OT_COMPILER_VERSION = "OTCompilerVersion";
+ public final static String ATTRIBUTE_OT_COMPILER_VERSION = "OTCompilerVersion";
- private static final int OTDRE_FLAG = 0x8000; // high bit in OTCompilerVersion
+ public static final int OTDRE_FLAG = 0x8000; // high bit in OTCompilerVersion
protected final static Attribute[] attributes = {
new CallinBindingsAttribute(0),
|