Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2017-01-14 22:56:33 +0000
committerStephan Herrmann2017-01-15 18:35:55 +0000
commit54b61fe5e6eadb19bb7f0441c3947dadf081845e (patch)
tree4692a0b660629e32698a9664d24ba52a1480010d
parentb8cfa8b73c41199370f42c8762faff1dfd17701f (diff)
downloadorg.eclipse.objectteams-54b61fe5e6eadb19bb7f0441c3947dadf081845e.tar.gz
org.eclipse.objectteams-54b61fe5e6eadb19bb7f0441c3947dadf081845e.tar.xz
org.eclipse.objectteams-54b61fe5e6eadb19bb7f0441c3947dadf081845e.zip
Bug 510471: Avoid use of global flag -Dot.weaving
-rw-r--r--plugins/org.eclipse.objectteams.otequinox/META-INF/p2.inf3
-rw-r--r--plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ASMByteCodeAnalyzer.java57
-rw-r--r--plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java23
-rw-r--r--plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java25
-rw-r--r--plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java15
-rw-r--r--plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java27
-rw-r--r--plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmBoundClass.java2
-rw-r--r--plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java6
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 4be9ff53c..fdb1c40a0 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),

Back to the top