diff options
6 files changed, 72 insertions, 52 deletions
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.osgi.weaving/META-INF/MANIFEST.MF index 46c0025ea..6657733b5 100644 --- a/plugins/org.eclipse.objectteams.osgi.weaving/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.objectteams.osgi.weaving/META-INF/MANIFEST.MF @@ -9,6 +9,7 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.objectteams.runtime;bundle-version="2.1.0", org.eclipse.osgi, org.eclipse.equinox.ds;bundle-version="1.4.100" +Import-Package: org.osgi.service.component;version="1.2.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ActivationPolicy: lazy Service-Component: OSGI-INF/weavinghook.xml diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/OSGI-INF/weavinghook.xml b/plugins/org.eclipse.objectteams.osgi.weaving/OSGI-INF/weavinghook.xml index 31f3c9de4..9253e2645 100644 --- a/plugins/org.eclipse.objectteams.osgi.weaving/OSGI-INF/weavinghook.xml +++ b/plugins/org.eclipse.objectteams.osgi.weaving/OSGI-INF/weavinghook.xml @@ -3,5 +3,6 @@ <implementation class="org.eclipse.objectteams.internal.osgi.weaving.OTWeavingHook"/> <service> <provide interface="org.osgi.framework.hooks.weaving.WeavingHook"/> + <provide interface="org.osgi.framework.hooks.weaving.WovenClassListener"/> </service> </component>
\ 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 3cb24f9cf..295bca944 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 @@ -110,8 +110,6 @@ public class AspectBindingRegistry { } // records of teams that have been deferred due to unresolved class dependencies: private List<WaitingTeamRecord> deferredTeams = new ArrayList<>(); - // records of teams whose class dependencies should/could be unblocked by now: - private List<WaitingTeamRecord> scheduledTeams = new ArrayList<>(); public static boolean IS_OTDT = false; @@ -323,37 +321,32 @@ public class AspectBindingRegistry { } /** Record the given team classes as waiting for instantiation/activation. */ - public synchronized void addDeferredTeamClasses(List<WaitingTeamRecord> teamClasses) { - deferredTeams.addAll(teamClasses); - } - - /** - * Check if the given class has been recorded as not-found before, - * If so, unblock the team class(es) that depend on this class - */ - public synchronized void scheduleTeamClassesFor(@Nullable String className) { - List<WaitingTeamRecord> currentList = deferredTeams; - deferredTeams = new ArrayList<>(); - for (WaitingTeamRecord record : currentList) { - if (record.notFoundClass.equals(className)) - scheduledTeams.add(record); - else - deferredTeams.add(record); + public void addDeferredTeamClasses(List<WaitingTeamRecord> teamClasses) { + synchronized (deferredTeams) { + deferredTeams.addAll(teamClasses); } } /** - * Try to instantiate/activate any deferred teams that have been unblocked by now. + * Try to instantiate/activate any deferred teams that may be unblocked + * by the definition of the given trigger class. */ - public void instantiateScheduledTeams() { - List<WaitingTeamRecord> currentList; - synchronized (this) { - currentList = scheduledTeams; - scheduledTeams = new ArrayList<>(); + public void instantiateScheduledTeams(String triggerClassName) { + List<WaitingTeamRecord> scheduledTeams = null; + synchronized(deferredTeams) { + for (WaitingTeamRecord record : new ArrayList<>(deferredTeams)) { + if (record.notFoundClass.equals(triggerClassName)) { + if (scheduledTeams == null) + scheduledTeams = new ArrayList<>(); + if (deferredTeams.remove(record)) + scheduledTeams.add(record); + } + } } - for(WaitingTeamRecord record : currentList) { + if (scheduledTeams == null) return; + for(WaitingTeamRecord record : scheduledTeams) { try { - new TeamLoader(deferredTeams).instantiateWaitingTeam(record); + new TeamLoader(deferredTeams).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/OTWeavingHook.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java index 3371dfc59..18dde181e 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 @@ -23,32 +23,62 @@ import java.security.ProtectionDomain; import org.eclipse.core.runtime.IStatus; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.objectteams.osgi.weaving.Activator; +import org.eclipse.objectteams.otequinox.hook.ILogger; import org.eclipse.objectteams.otre.jplis.ObjectTeamsTransformer; import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; import org.osgi.framework.hooks.weaving.WeavingHook; import org.osgi.framework.hooks.weaving.WovenClass; +import org.osgi.framework.hooks.weaving.WovenClassListener; import org.osgi.framework.wiring.BundleWiring; +import org.osgi.service.component.ComponentContext; + /** * This class integrates the OT/J weaver into OSGi using the standard API {@link WeavingHook}. + * <p> + * Additionally, we listen to events of woven classes changing to state {@link WovenClass#DEFINED}: + * </p> + * <ul> + * <li>Given that {@link AspectBindingRegistry#addDeferredTeamClasses} was used to record + * teams that could not be instantiated due to some required class being reported + * as {@link NoClassDefFoundError}.</li> + * <li>Assuming further that this error happened because the required class was in the process + * of being loaded further down the call stack.</li> + * <li>If later one of the not-found classes has been defined we use that trigger to + * re-attempt instantiating the dependent team(s).</li> + * </ul> */ -public class OTWeavingHook implements WeavingHook { +public class OTWeavingHook implements WeavingHook, WovenClassListener { private AspectBindingRegistry aspectBindingRegistry; private ObjectTeamsTransformer objectTeamsTransformer; - public OTWeavingHook() { - this.aspectBindingRegistry = Activator.loadAspectBindingRegistry(); + /** Call-back from DS framework. */ + public void activate(ComponentContext context) { + this.aspectBindingRegistry = loadAspectBindingRegistry(context.getBundleContext()); this.objectTeamsTransformer = new ObjectTeamsTransformer(); } + @SuppressWarnings("deprecation") + private AspectBindingRegistry loadAspectBindingRegistry(BundleContext context) { + org.osgi.service.packageadmin.PackageAdmin packageAdmin = null;; + + ServiceReference<?> ref= context.getServiceReference(org.osgi.service.packageadmin.PackageAdmin.class.getName()); + if (ref!=null) + packageAdmin = (org.osgi.service.packageadmin.PackageAdmin)context.getService(ref); + else + log(ILogger.ERROR, "Failed to load PackageAdmin service. Will not be able to handle fragments."); + + AspectBindingRegistry aspectBindingRegistry = new AspectBindingRegistry(); + aspectBindingRegistry.loadAspectBindings(packageAdmin); + return aspectBindingRegistry; + } + @Override public void weave(WovenClass wovenClass) { try { - // TODO(SH): ideally this trigger would be inserted into the previous woven class - // do whatever left-overs we find from previous invocations: - aspectBindingRegistry.instantiateScheduledTeams(); - BundleWiring bundleWiring = wovenClass.getBundleWiring(); String bundleName = bundleWiring.getBundle().getSymbolicName(); String className = wovenClass.getClassName(); @@ -70,12 +100,18 @@ public class OTWeavingHook implements WeavingHook { log(e, "Failed to transform class "+className); } } - // unblock any waiting teams depending on this class: - aspectBindingRegistry.scheduleTeamClassesFor(className); } catch (ClassCircularityError cce) { log(cce, "Weaver encountered a circular class dependency"); } } + + @Override + public void modified(WovenClass wovenClass) { + if (wovenClass.getState() == WovenClass.DEFINED) { + @SuppressWarnings("null") @NonNull String className = wovenClass.getClassName(); + aspectBindingRegistry.instantiateScheduledTeams(className); + } + } private boolean requiresWeaving(BundleWiring bundleWiring) { @SuppressWarnings("null")@NonNull 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 794d7289c..fc21590ca 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 @@ -101,7 +101,9 @@ public class TeamLoader { return instance; } catch (NoClassDefFoundError ncdfe) { needDeferring = true; - deferredTeams.add(new WaitingTeamRecord(teamClass, aspectBinding, ncdfe.getMessage().replace('/','.'))); + synchronized(deferredTeams) { + deferredTeams.add(new WaitingTeamRecord(teamClass, aspectBinding, ncdfe.getMessage().replace('/','.'))); + } } catch (Throwable e) { // application error during constructor execution? log(e, "Failed to instantiate team "+teamName); @@ -124,7 +126,9 @@ public class TeamLoader { break; } } catch (NoClassDefFoundError e) { - deferredTeams.add(new WaitingTeamRecord(teamInstance, aspectBinding, e.getMessage().replace('/','.'))); // TODO(SH): synchronization + synchronized (deferredTeams) { + deferredTeams.add(new WaitingTeamRecord(teamInstance, aspectBinding, e.getMessage().replace('/','.'))); // TODO(SH): synchronization + } } catch (Throwable t) { // application errors during activation log(t, "Failed to activate team "+teamName); diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/osgi/weaving/Activator.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/osgi/weaving/Activator.java index bd2224623..2dd0029c1 100644 --- a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/osgi/weaving/Activator.java +++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/osgi/weaving/Activator.java @@ -35,21 +35,6 @@ public class Activator implements BundleActivator { OTREInit(); } - @SuppressWarnings("deprecation") - public static AspectBindingRegistry loadAspectBindingRegistry() { - org.osgi.service.packageadmin.PackageAdmin packageAdmin = null;; - - ServiceReference<?> ref= context.getServiceReference(org.osgi.service.packageadmin.PackageAdmin.class.getName()); - if (ref!=null) - packageAdmin = (org.osgi.service.packageadmin.PackageAdmin)context.getService(ref); - else - log(ILogger.ERROR, "Failed to load PackageAdmin service. Will not be able to handle fragments."); - - AspectBindingRegistry aspectBindingRegistry = new AspectBindingRegistry(); - aspectBindingRegistry.loadAspectBindings(packageAdmin); - return aspectBindingRegistry; - } - @SuppressWarnings("restriction") private void acquireLog(BundleContext bundleContext) { try { |