Bug 406518 - migrate OT/Equinox to the standard OSGi WeavingHook
Uniformly use the transformer with a Bundle instead of a ClassLoader
Progress on when to do which piece of work
- don't try instantiate/activate before all needed classes are available
- keep track of classes being processed
- check all bases of a given team
- no multiple processing of the same team triggered by different bases
- remove baseTripWires when done
Add reverse imports (base->aspect)
Logging; wiring to fwLog still not working
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java
index 940327a..e9b8ac3 100644
--- a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java
@@ -16,6 +16,8 @@
**********************************************************************/
package org.eclipse.objectteams.internal.osgi.weaving;
+import static org.eclipse.objectteams.otequinox.TransformerPlugin.log;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -25,8 +27,10 @@
import java.util.Set;
import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.objectteams.otequinox.ActivationKind;
+import org.osgi.framework.Bundle;
/**
* A simple record representing the information read from an extension to org.eclipse.objectteams.otequinox.aspectBindings.
@@ -34,16 +38,25 @@
* @since 1.3.0 (was a nested class before that)
*/
public class AspectBinding {
+ enum State { Initial, TeamsScanned, TeamsActivated };
+
public String aspectPlugin;
public String basePlugin;
public IConfigurationElement[] forcedExports;
public ActivationKind[] activations = null;
public String[] teamClasses;
public List<String>[] subTeamClasses;
- public boolean activated= false; // FIXME: consistently set?
+
+ public State state = State.Initial;
+
+ /** Dispenser for team classes indexed by base classes that should trigger activating the team. */
private HashMap<String, Set<String>> teamsPerBase = new HashMap<>();
+
+ /** Lookup to find base classes affected by a team (need to be available before instantiate/activate). */
HashMap<String, Collection<String>> basesPerTeam = new HashMap<>();
+ Set<String> teamsInProgress = new HashSet<>(); // TODO cleanup teams that are done
+
public AspectBinding(String aspectId, String baseId, IConfigurationElement[] forcedExportsConfs) {
this.aspectPlugin= aspectId;
this.basePlugin= baseId;
@@ -93,8 +106,13 @@
}
/** Destructively read the names of teams to load for a given base class. */
- public @Nullable Collection<String> getTeamsForBase(String baseClassName) {
- return teamsPerBase.remove(baseClassName);
+ public synchronized @Nullable Collection<String> getTeamsForBase(String baseClassName) {
+ Set<String> teamNames = teamsPerBase.remove(baseClassName);
+ if (teamNames != null) {
+ teamNames.removeAll(teamsInProgress);
+ teamsInProgress.addAll(teamNames);
+ }
+ return teamNames;
}
public ActivationKind getActivation(String teamClassName) {
@@ -104,4 +122,20 @@
}
return ActivationKind.NONE;
}
+
+ /** Read OT attributes of all teams in aspectBinding and collect affected base classes. */
+ public synchronized void scanTeamClasses(Bundle bundle) {
+ ClassScanner scanner = new ClassScanner();
+ for (String teamName : getAllTeams()) {
+ try {
+ teamName = scanner.readOTAttributes(bundle, teamName);
+ Collection<String> baseClassNames = scanner.getCollectedBaseClassNames();
+ addBaseClassNames(teamName, baseClassNames);
+ log(IStatus.INFO, "Scanned team class "+teamName+", found "+baseClassNames.size()+" base classes");
+ } catch (Exception e) {
+ log(e, "Failed to scan team class "+teamName);
+ }
+ }
+ this.state = State.TeamsScanned;
+ }
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBindingRegistry.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBindingRegistry.java
index 96c57c7..b06206e 100644
--- a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBindingRegistry.java
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBindingRegistry.java
@@ -35,6 +35,7 @@
import java.util.Set;
import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.RegistryFactory;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -43,6 +44,7 @@
import org.eclipse.objectteams.otequinox.hook.ILogger;
import org.objectteams.ITeam;
import org.osgi.framework.Bundle;
+import org.osgi.framework.hooks.weaving.WovenClass;
/**
* An instance of this class holds the information loaded from extensions
@@ -72,6 +74,12 @@
private Set<String> selfAdaptingAspects= new HashSet<String>(); // TODO, never read / evaluated
private HashMap<String, BaseBundleLoadTrigger> baseTripWires = new HashMap<>();
+
+ Set<String> beingDefined = new HashSet<>(); // shared with OTWeavingHook!
+
+ public AspectBindingRegistry(Set<String> beingDefined) {
+ this.beingDefined = beingDefined;
+ }
/** Record for one team waiting for instantiation/activation. */
static class WaitingTeamRecord {
@@ -314,10 +322,12 @@
}
/** Check if the given base bundle / base class mandate any loading/instantiation/activation of teams. */
- public void triggerLoadingHooks(@Nullable String bundleName, @Nullable String className) {
+ public void triggerLoadingHooks(@Nullable String bundleName, @Nullable WovenClass baseClass) {
BaseBundleLoadTrigger activation = baseTripWires.get(bundleName);
- if (activation != null)
- activation.fire(className);
+ if (activation != null) {
+ if (activation.fire(baseClass, beingDefined))
+ baseTripWires.remove(bundleName);
+ }
}
/** Record the given team classes as waiting for instantiation/activation. */
@@ -345,8 +355,9 @@
}
if (scheduledTeams == null) return;
for(WaitingTeamRecord record : scheduledTeams) {
+ log(IStatus.INFO, "Consider for instantiation/activation: team "+record.getTeamName());
try {
- new TeamLoader(deferredTeams).instantiateWaitingTeam(record); // may re-insert to deferredTeams
+ new TeamLoader(deferredTeams, beingDefined).instantiateWaitingTeam(record); // may re-insert to deferredTeams
} catch (Exception e) {
log(e, "Failed to instantiate team "+record.getTeamName());
continue;
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java
index d775f07..958f310 100644
--- a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java
@@ -15,13 +15,16 @@
**********************************************************************/
package org.eclipse.objectteams.internal.osgi.weaving;
-import static org.eclipse.objectteams.otequinox.Activator.log;
+import static org.eclipse.objectteams.otequinox.TransformerPlugin.log;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.objectteams.internal.osgi.weaving.AspectBinding.State;
import org.osgi.framework.Bundle;
+import org.osgi.framework.hooks.weaving.WovenClass;
/**
* Each instance of this class represents the fact that a given base bundle has aspect bindings,
@@ -33,10 +36,7 @@
@SuppressWarnings("deprecation")
private org.osgi.service.packageadmin.PackageAdmin admin;
- private String baseBundleName;
-
- private boolean teamsScanned = false;
-
+ private String baseBundleName;
public BaseBundleLoadTrigger(String bundleSymbolicName, AspectBindingRegistry aspectBindingRegistry,
@SuppressWarnings("deprecation") org.osgi.service.packageadmin.PackageAdmin admin)
@@ -46,13 +46,20 @@
this.admin = admin;
}
- /** Signal that the given class is being loaded and trigger any necessary loading/instantiation/activation. */
- public void fire(String className) {
+ /**
+ * Signal that the given class is being loaded and trigger any necessary steps:
+ * - scan team & add reverse imports (now)
+ * - load & instantiate & activate (now or later).
+ */
+ public boolean fire(WovenClass baseClass, Set<String> beingDefined) {
List<AspectBindingRegistry.WaitingTeamRecord> deferredTeamClasses = new ArrayList<>();
List<AspectBinding> aspectBindings = aspectBindingRegistry.getAdaptingAspectBindings(baseBundleName);
+ boolean allDone = true;
if (aspectBindings != null) {
for (AspectBinding aspectBinding : aspectBindings) {
- if (aspectBinding.activated)
+ if (aspectBinding.state == State.Initial)
+ log(IStatus.INFO, "Preparing aspect binding for base bundle "+baseBundleName);
+ if (aspectBinding.state == State.TeamsActivated)
continue;
@SuppressWarnings("deprecation")
Bundle[] aspectBundles = admin.getBundles(aspectBinding.aspectPlugin, null);
@@ -61,35 +68,17 @@
continue;
}
Bundle aspectBundle = aspectBundles[0];
- if (shouldScan())
- scanTeamClasses(aspectBundle, aspectBinding);
- TeamLoader loading = new TeamLoader(deferredTeamClasses);
- if (loading.loadTeams(aspectBundle, aspectBinding, className))
-// aspectBinding.activated = true; // FIXME(SH): this still spoils team activation, the given class may not be the trigger
- ;
+ if (aspectBinding.state != State.TeamsScanned)
+ aspectBinding.scanTeamClasses(aspectBundle);
+ TeamLoader loading = new TeamLoader(deferredTeamClasses, beingDefined);
+ if (!loading.loadTeamsForBase(aspectBundle, aspectBinding, baseClass))
+ allDone = false;
}
- if (!deferredTeamClasses.isEmpty())
+ if (!deferredTeamClasses.isEmpty()) {
aspectBindingRegistry.addDeferredTeamClasses(deferredTeamClasses);
- }
- }
-
- private synchronized boolean shouldScan() {
- boolean shouldScan = !teamsScanned;
- teamsScanned = true;
- return shouldScan;
- }
-
- /** Read OT attributes of all teams in aspectBinding and collect affected base classes. */
- private void scanTeamClasses(Bundle bundle, AspectBinding aspectBinding) {
- List<String> allTeams = aspectBinding.getAllTeams();
- ClassScanner scanner = new ClassScanner();
- for (String teamName : allTeams) {
- try {
- teamName = scanner.readOTAttributes(bundle, teamName);
- aspectBinding.addBaseClassNames(teamName, scanner.getCollectedBaseClassNames());
- } catch (Exception e) {
- log(e, "Failed to load team class "+teamName);
+ return false;
}
}
+ return allDone;
}
}
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/Logger.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/Logger.java
new file mode 100644
index 0000000..7ee6979
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/Logger.java
@@ -0,0 +1,80 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2007, 2013 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany, and others
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.internal.osgi.weaving;
+
+import org.eclipse.objectteams.otequinox.hook.HookConfigurator;
+import org.eclipse.objectteams.otequinox.hook.ILogger;
+import org.eclipse.osgi.framework.log.FrameworkLog;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+
+
+/**
+ * Log either to console or - as soon as it is initialized - via the TransformerPlugin.
+ *
+ * @author stephan
+ * @since OTDT 1.1.4
+ */
+public class Logger implements ILogger
+{
+ private FrameworkLog fwLog;
+
+ public Logger(FrameworkLog fwLog) {
+ this.fwLog = fwLog;
+ }
+
+ public void log(Throwable t, String msg) {
+ log(HookConfigurator.class.getPackage().getName(), t, msg);
+ }
+ public void log(String pluginID, Throwable t, String msg) {
+ if (this.fwLog != null) {
+ this.fwLog.log(new FrameworkLogEntry(pluginID, FrameworkLogEntry.ERROR, 0, msg, 0, t, null));
+ return;
+ } else {
+ // no success logging, print to console instead:
+ System.err.println("OT/Equinox: "+msg); //$NON-NLS-1$
+ t.printStackTrace();
+ }
+ }
+
+ public void log(int status, String msg) {
+ if (status >= Util.WARN_LEVEL)
+ doLog(HookConfigurator.class.getPackage().getName(), status, msg);
+ }
+ public void log(String pluginID, int status, String msg) {
+ if (status >= Util.WARN_LEVEL)
+ doLog(pluginID, status, msg);
+ }
+
+ public void doLog(int status, String msg) {
+ doLog(HookConfigurator.class.getPackage().getName(), status, msg);
+ }
+ public void doLog(String pluginID, int status, String msg) {
+ if (this.fwLog != null) {
+ this.fwLog.log(new FrameworkLogEntry(pluginID, status, 0, msg, 0, null, null));
+ } else {
+ // no success logging, print to console instead:
+ msg = "OT/Equinox: "+msg; //$NON-NLS-1$
+ if ((status & ERROR) != 0)
+ System.err.println(msg);
+ else
+ System.out.println(msg);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java
index 6b3f7a8..656530c 100644
--- a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java
@@ -20,7 +20,6 @@
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.Arrays;
-import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -58,12 +57,13 @@
public class OTWeavingHook implements WeavingHook, WovenClassListener {
private AspectBindingRegistry aspectBindingRegistry;
- private ObjectTeamsTransformer objectTeamsTransformer;
+
+ @NonNull Set<String> beingDefined = new HashSet<>(); // shared with AspectBindingRegistry!
+
/** Call-back from DS framework. */
public void activate(ComponentContext context) {
this.aspectBindingRegistry = loadAspectBindingRegistry(context.getBundleContext());
- this.objectTeamsTransformer = new ObjectTeamsTransformer();
TransformerPlugin.getDefault().registerAspectBindingRegistry(this.aspectBindingRegistry);
}
@@ -77,46 +77,39 @@
else
log(ILogger.ERROR, "Failed to load PackageAdmin service. Will not be able to handle fragments.");
- AspectBindingRegistry aspectBindingRegistry = new AspectBindingRegistry();
+ AspectBindingRegistry aspectBindingRegistry = new AspectBindingRegistry(this.beingDefined);
aspectBindingRegistry.loadAspectBindings(packageAdmin);
return aspectBindingRegistry;
}
@Override
public void weave(WovenClass wovenClass) {
+ beingDefined.add(wovenClass.getClassName());
+
try {
BundleWiring bundleWiring = wovenClass.getBundleWiring();
String bundleName = bundleWiring.getBundle().getSymbolicName();
String className = wovenClass.getClassName();
// do whatever is needed *before* loading this class:
- aspectBindingRegistry.triggerLoadingHooks(bundleName, className);
+ aspectBindingRegistry.triggerLoadingHooks(bundleName, wovenClass);
if (requiresWeaving(bundleWiring)) {
+ ObjectTeamsTransformer transformer = new ObjectTeamsTransformer();
Class<?> classBeingRedefined = null; // TODO
ProtectionDomain protectionDomain = wovenClass.getProtectionDomain();
byte[] bytes = wovenClass.getBytes();
try {
- log(IStatus.INFO, "About to transform class "+wovenClass);
- byte[] newBytes = objectTeamsTransformer.transform(bundleWiring.getClassLoader(),
+ log(IStatus.OK, "About to transform class "+className);
+ byte[] newBytes = transformer.transform(bundleWiring.getBundle(),
className, classBeingRedefined, protectionDomain, bytes);
if (newBytes != bytes && !Arrays.equals(newBytes, bytes)) {
+ log(IStatus.INFO, "Transformation performed on "+className);
wovenClass.setBytes(newBytes);
if (otreAdded.add(bundleWiring.getBundle())) {
+ log(IStatus.INFO, "Adding OTRE import to "+bundleName);
List<String> imports = wovenClass.getDynamicImports();
imports.add("org.objectteams");
- List<AspectBinding> aspects = aspectBindingRegistry.getAdaptingAspectBindings(bundleName);
- if (aspects != null) {
- for (AspectBinding aspect : aspects) {
- Collection<String> teamsForBase = aspect.getTeamsForBase(className);
- if (teamsForBase != null) {
- for (String t : teamsForBase) {
- int dot = t.lastIndexOf('.');
- imports.add(t.substring(0, dot));
- }
- }
- }
- }
}
}
} catch (IllegalClassFormatException e) {
@@ -132,6 +125,7 @@
@Override
public void modified(WovenClass wovenClass) {
if (wovenClass.getState() == WovenClass.DEFINED) {
+ beingDefined.remove(wovenClass.getClassName());
@SuppressWarnings("null") @NonNull String className = wovenClass.getClassName();
aspectBindingRegistry.instantiateScheduledTeams(className);
}
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/TeamLoader.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/TeamLoader.java
index 0a60d80..bb840e9 100644
--- a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/TeamLoader.java
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/TeamLoader.java
@@ -21,7 +21,9 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.objectteams.internal.osgi.weaving.AspectBindingRegistry.WaitingTeamRecord;
import org.eclipse.objectteams.otequinox.ActivationKind;
@@ -30,6 +32,7 @@
import org.objectteams.ITeam;
import org.objectteams.Team;
import org.osgi.framework.Bundle;
+import org.osgi.framework.hooks.weaving.WovenClass;
/**
* This class triggers the actual loading/instantiation/activation of teams.
@@ -48,17 +51,32 @@
private List<WaitingTeamRecord> deferredTeams;
/** did we record the fact that a team needs deferring? */
- boolean needDeferring;
+ boolean needDeferring;
+
+ private Set<String> beingDefined;
- public TeamLoader(List<WaitingTeamRecord> deferredTeams) {
+ public TeamLoader(List<WaitingTeamRecord> deferredTeams, Set<String> beingDefined) {
this.deferredTeams = deferredTeams;
+ this.beingDefined = beingDefined;
}
- /** Team loading, 1st attempt (trying to do all three phases load/instantiate/activate). */
- public boolean loadTeams(Bundle aspectBundle, AspectBinding aspectBinding, String className) {
- Collection<String> teamsForBase = aspectBinding.getTeamsForBase(className);
- if (teamsForBase == null) return true;
+ /**
+ * Team loading, 1st attempt before the base class is even loaded
+ * Trying to do these phases load/instantiate/activate,
+ * and also adds a reverse import to the base.
+ */
+ public boolean loadTeamsForBase(Bundle aspectBundle, AspectBinding aspectBinding, WovenClass baseClass) {
+ Collection<String> teamsForBase = aspectBinding.getTeamsForBase(baseClass.getClassName());
+ if (teamsForBase == null) return false;
+ List<String> imports = baseClass.getDynamicImports();
for (String teamForBase : teamsForBase) {
+ // Add dependency:
+ String packageOfTeam = "";
+ int dot = teamForBase.lastIndexOf('.');
+ if (dot != -1)
+ packageOfTeam = teamForBase.substring(0, dot);
+ imports.add(packageOfTeam);
+ log(IStatus.INFO, "Added dependency from base "+baseClass.getClassName()+" to package '"+packageOfTeam+"'");
// Load:
Class<? extends ITeam> teamClass;
teamClass = findTeamClass(teamForBase, aspectBundle);
@@ -76,7 +94,7 @@
// Activate?
activateTeam(aspectBinding, teamForBase, teamInstance, activationKind);
}
- return !needDeferring; // TODO, need to figure out whether we're done with aspectBinding.
+ return true;
}
/** Team loading, subsequent attempts. */
@@ -155,6 +173,10 @@
}
private @Nullable ITeam instantiateTeam(AspectBinding aspectBinding, Class<? extends ITeam> teamClass, String teamName) {
+ // don't try to instantiate before all base classes successfully loaded.
+ if (!isReadyToLoad(aspectBinding, teamClass, null, teamName))
+ return null;
+
try {
ITeam instance = teamClass.newInstance();
TransformerPlugin.registerTeamInstance(instance);
@@ -174,26 +196,19 @@
private void activateTeam(AspectBinding aspectBinding, String teamName, ITeam teamInstance, ActivationKind activationKind)
{
- // don't try to activate before all base classes successfully load.
- ClassLoader loader = teamInstance.getClass().getClassLoader();
- for (String baseclass : aspectBinding.basesPerTeam.get(teamName)) {
- try {
- loader.loadClass(baseclass);
- } catch (ClassNotFoundException cnfe) {
- synchronized (deferredTeams) {
- deferredTeams.add(new WaitingTeamRecord(teamInstance, aspectBinding, baseclass)); // TODO(SH): synchronization, deadlock?
- }
- return;
- }
- }
+ // don't try to activate before all base classes successfully loaded.
+ if (!isReadyToLoad(aspectBinding, teamInstance.getClass(), teamInstance, teamName))
+ return;
// good to go, so go:
try {
switch (activationKind) {
case ALL_THREADS:
teamInstance.activate(Team.ALL_THREADS);
+ log(IStatus.INFO, "Activated team "+teamName);
break;
case THREAD:
teamInstance.activate();
+ log(IStatus.INFO, "Activated team "+teamName);
break;
//$CASES-OMITTED$
default:
@@ -204,4 +219,19 @@
log(t, "Failed to activate team "+teamName);
}
}
+ boolean isReadyToLoad(AspectBinding aspectBinding, Class<? extends ITeam> teamClass, ITeam teamInstance, String teamName) {
+ for (String baseclass : aspectBinding.basesPerTeam.get(teamName)) {
+ if (this.beingDefined.contains(baseclass)) {
+ synchronized (deferredTeams) {
+ WaitingTeamRecord record = teamInstance != null
+ ? new WaitingTeamRecord(teamInstance, aspectBinding, baseclass)
+ : new WaitingTeamRecord(teamClass, aspectBinding, baseclass);
+ deferredTeams.add(record); // TODO(SH): synchronization, deadlock?
+ }
+ log(IStatus.INFO, "Defer instantation/activation of team "+teamName);
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/Util.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/Util.java
new file mode 100644
index 0000000..ff85099
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/Util.java
@@ -0,0 +1,123 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id: Util.java 23461 2010-02-04 22:10:39Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.internal.osgi.weaving;
+
+import java.util.HashSet;
+import static org.eclipse.core.runtime.IStatus.*;
+
+public class Util
+{
+
+ // configure OT/Equinox debugging:
+ public static int WARN_LEVEL = INFO;
+ public static boolean PROFILE= false;
+ static {
+ String level = System.getProperty("otequinox.debug"); //$NON-NLS-1$
+ if (level != null) {
+ level = level.toUpperCase();
+ if (level.equals("OK")) //$NON-NLS-1$
+ WARN_LEVEL = OK;
+ else if (level.equals("INFO")) //$NON-NLS-1$
+ WARN_LEVEL = INFO;
+ else if (level.startsWith("WARN")) //$NON-NLS-1$
+ WARN_LEVEL = WARNING;
+ else if (level.startsWith("ERR")) //$NON-NLS-1$
+ WARN_LEVEL = ERROR;
+ else
+ WARN_LEVEL = OK;
+ }
+ PROFILE= (System.getProperty("otequinox.profile") != null); //$NON-NLS-1$
+ }
+
+ /** Profiling data: */
+ enum ProfileKind { BaseTransformation, AspectTransformation, SuperClassFetching }
+ private static long[] profileTimes= new long[ProfileKind.values().length];
+ private static long systemStartTime= System.nanoTime();
+
+ static HashSet<String> PLATFORM_BUNDLES = null;
+
+ @SuppressWarnings("nls")
+ private static void checkInit() {
+ if (PLATFORM_BUNDLES == null) {
+ PLATFORM_BUNDLES = new HashSet<String>();
+ // FIXME: reconsider:
+ for (String bundle : new String[] { "org.eclipse.equinox.common",
+ "org.eclipse.update.configurator",
+ "org.eclipse.core.runtime",
+ "org.eclipse.equinox.registry",
+ "org.eclipse.equinox.app",
+ "org.eclipse.equinox.ds",
+ "org.eclipse.equinox.event",
+ "org.eclipse.equinox.util",
+ "org.eclipse.osgi.services",
+ "org.eclipse.core.runtime.compatibility.auth",
+ "org.eclipse.equinox.preferences",
+ "org.eclipse.equinox.simpleconfigurator",
+ "org.eclipse.core.jobs",
+ "org.eclipse.core.runtime.compatibility",
+ "org.eclipse.equinox.p2.core",
+ "org.eclipse.equinox.p2.reconciler.dropins",
+ "org.eclipse.equinox.p2.directorywatcher",
+ "org.eclipse.ecf",
+ "org.eclipse.ecf.identity",
+ "org.eclipse.ecf.filetransfer",
+ "org.eclipse.ecf.provider.filetransfer",
+ "org.eclipse.ecf.provider.filetransfer.httpclient",
+ "org.apache.commons.httpclient",
+ // for Eclipse 4.x:
+ "org.eclipse.swt",
+ "org.eclipse.e4.ui.css.core",
+ "org.eclipse.e4.ui.css.swt.theme",
+ "org.eclipse.core.contenttype"
+ })
+ PLATFORM_BUNDLES.add(bundle);
+ }
+ }
+
+ static boolean isPlatformBundle(String bundleName) {
+ checkInit();
+ return PLATFORM_BUNDLES.contains(bundleName);
+ }
+
+ @SuppressWarnings("nls")
+ public static void profile(long startTime, ProfileKind kind, String msg, Logger logger)
+ {
+ long now= System.nanoTime();
+ long delta= (now-startTime) / getActiveCount();
+ long total= (profileTimes[kind.ordinal()]+= delta);
+ msg = msg.substring(msg.lastIndexOf('.')+1);
+ logger.doLog(INFO, "Profile "+kind.name()+": "+m(delta)+"("+m(total)+"/"+m(now-systemStartTime)+") ["+msg+"]");
+ }
+ // nano-to milli conversion
+ private static double m(long l) {
+ return (l/1000000.0);
+ }
+
+ private static int getActiveCount() {
+ ThreadGroup group= Thread.currentThread().getThreadGroup();
+ ThreadGroup parent= group.getParent();
+ while (parent != null) {
+ group= parent;
+ parent= group.getParent();
+ }
+ return group.activeCount();
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
index d26aff9..cb6eeea 100644
--- a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
@@ -128,7 +128,11 @@
* {@link IAspectRegistry#getAdaptingAspectPlugins(Bundle)}
*/
public @NonNull String[] getAdaptingAspectPlugins(Bundle basePlugin) {
- List<AspectBinding> aspectBindings = this.aspectBindingRegistry.getAdaptingAspectBindings(basePlugin.getSymbolicName());
+ return getAdaptingAspectPlugins(basePlugin.getSymbolicName());
+ }
+
+ public @NonNull String[] getAdaptingAspectPlugins(String id) {
+ List<AspectBinding> aspectBindings = this.aspectBindingRegistry.getAdaptingAspectBindings(id);
if (aspectBindings == null)
return new String[0];
String[] result = new String[aspectBindings.size()];
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/BaseCallRedirection.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/BaseCallRedirection.java
index 639a870..c1357e3 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/BaseCallRedirection.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/BaseCallRedirection.java
@@ -58,7 +58,7 @@
public InstructionHandle snd() {return _ih2; }
}
- public BaseCallRedirection(ClassLoader loader) {
+ public BaseCallRedirection(Object loader) {
super(loader);
}
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java
index 2118419..ad2d6b4 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java
@@ -142,7 +142,7 @@
public boolean useReflection = false;
- public BaseMethodTransformation(ClassLoader loader) {
+ public BaseMethodTransformation(Object loader) {
super(loader);
}
/**
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/Decapsulation.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/Decapsulation.java
index c91e352..c9c8ae1 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/Decapsulation.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/Decapsulation.java
@@ -53,7 +53,7 @@
private HashSet<String/*callout accessed fields*/> generatedFieldCalloutAccessors = new HashSet<String>();
private HashSet<String/*super-accessed methods (sign)*/> generatedSuperAccessors = new HashSet<String>();
- public Decapsulation(ClassLoader loader) {
+ public Decapsulation(Object loader) {
super(loader);
}
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java
index b62e874..14c402c 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java
@@ -69,7 +69,7 @@
private static final String CREATE_ROLE_METHOD = "createRole";
private static final String LIFTING_PARTICIPANT_FIELD = "_OT$liftingParticipant";
- public LiftingParticipantTransformation(ClassLoader loader) { super(loader); }
+ public LiftingParticipantTransformation(Object loader) { super(loader); }
public void doTransformCode(ClassGen cg)
{
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java
index 7d75263..ab76fc1 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java
@@ -50,7 +50,7 @@
static final String _OT_ACTIVE_TEAMS= "_OT$activeTeams"; //$NON-NLS-1$
static final String _OT_ACTIVE_TEAM_IDS= "_OT$activeTeamIDs"; //$NON-NLS-1$
- public StaticSliceBaseTransformation(ClassLoader loader) { super(loader); }
+ public StaticSliceBaseTransformation(Object loader) { super(loader); }
private HashMap<String,String> rejectReasons = new HashMap<String, String>();
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java
index 92e2656..9dc5691 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java
@@ -38,7 +38,7 @@
public class SubBoundBaseMethodRedefinition
extends ObjectTeamsTransformation {
- public SubBoundBaseMethodRedefinition(ClassLoader loader) { super(loader); }
+ public SubBoundBaseMethodRedefinition(Object loader) { super(loader); }
/**
* Main entry for this transformer.
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java
index ce29d45..6bacee9 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java
@@ -46,7 +46,7 @@
extends ObjectTeamsTransformation {
- public TeamInterfaceImplementation(ClassLoader loader) {
+ public TeamInterfaceImplementation(Object loader) {
super(loader);
}
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java
index e752986..29d0c11 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java
@@ -21,9 +21,9 @@
import java.io.InputStream;
import org.eclipse.objectteams.otre.ClassEnhancer;
+import org.eclipse.objectteams.otre.ClassLoaderAccess;
import org.eclipse.objectteams.otre.OTREInternalError;
import org.eclipse.objectteams.otre.ObjectTeamsTransformation;
-
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.Field;
@@ -44,9 +44,9 @@
public class JPLISEnhancer implements ClassEnhancer {
- private ClassLoader loader;
+ private Object loader;
- public JPLISEnhancer(ClassGen cg, ClassLoader loader) {
+ public JPLISEnhancer(ClassGen cg, Object loader) {
this.loader = loader;
}
@@ -109,7 +109,7 @@
InputStream is = null;
try {
String binaryName = className.replace('.', '/');
- is = loader.getResourceAsStream(binaryName+".class");
+ is = ClassLoaderAccess.getResourceAsStream(this.loader, binaryName+".class");
if (is != null) {
ClassGen cg = new ClassGen(new ClassParser(is, className).parse());
client.checkReadClassAttributes(this, cg, className, cg.getConstantPool());
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java
index 2e90dac..9d70991 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java
@@ -65,6 +65,7 @@
};
static boolean warmedUp = false;
+
/*
* (non-Javadoc)
*
@@ -72,7 +73,13 @@
* java.lang.String, java.lang.Class, java.security.ProtectionDomain,
* byte[])
*/
- public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
+ public byte[] transform(ClassLoader loader, String className,
+ Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
+ byte[] classfileBuffer) throws IllegalClassFormatException {
+ return transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
+ }
+
+ public byte[] transform(Object loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException
{
@@ -86,7 +93,7 @@
}
}
}
- public byte[] internalTransform(ClassLoader loader, String className, Class<?> classBeingRedefined,
+ public byte[] internalTransform(Object loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException
{
@@ -125,7 +132,7 @@
StaticSliceBaseTransformation staticSliceBaseTransformation = new StaticSliceBaseTransformation(loader);
SubBoundBaseMethodRedefinition subBoundBaseMethodRedefinition = new SubBoundBaseMethodRedefinition(loader);
TeamInterfaceImplementation teamInterfaceImplementation = new TeamInterfaceImplementation(loader);
- ThreadActivation threadActivation = new ThreadActivation();
+// ThreadActivation threadActivation = new ThreadActivation();
// tell Repository about the class loader for improved lookupClass()
DietClassLoaderRepository prevRepository = RepositoryAccess.setClassLoader(loader);
@@ -179,7 +186,8 @@
// baseMethodTransformation.doTransformInterface(jpe, cg);
// staticSliceBaseTransformation.doTransformInterface(jpe, cg);
// teamInterfaceImplementation.doTransformInterface(jpe, cg);
- threadActivation.doTransformInterface(jpe, cg);
+// FIXME:
+// threadActivation.doTransformInterface(jpe, cg);
// baseCallRedirection.doTransformCode(cg); // empty method
@@ -187,7 +195,8 @@
liftingParticipantTransformation.doTransformCode(cg);
staticSliceBaseTransformation.doTransformCode(cg);
teamInterfaceImplementation.doTransformCode(cg);
- threadActivation.doTransformCode(cg);
+// FIXME:
+// threadActivation.doTransformCode(cg);
JavaClass new_java_class = cg.getJavaClass();
if (dumping) {