Bug 406518 - migrate OT/Equinox to the standard OSGi WeavingHook
- start restoring the API for stuff like BrandingAdaptor and OT/EMonitor
- try adding imports base->team-package (not triggered, yet)
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 486ebe3..b41be2e 100644
--- a/plugins/org.eclipse.objectteams.osgi.weaving/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: OT/J Weaving for OSGi
 Bundle-SymbolicName: org.eclipse.objectteams.otequinox;singleton:=true
 Bundle-Version: 2.3.0.qualifier
-Bundle-Activator: org.eclipse.objectteams.otequinox.Activator
+Bundle-Activator: org.eclipse.objectteams.otequinox.TransformerPlugin
 Bundle-Vendor: Eclipse.org - Object Teams
 Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.objectteams.runtime;bundle-version="2.3.0";visibility:="reexport",
@@ -13,3 +13,4 @@
 Bundle-RequiredExecutionEnvironment: JavaSE-1.7
 Bundle-ActivationPolicy: lazy
 Service-Component: OSGI-INF/weavinghook.xml
+Export-Package: org.eclipse.objectteams.otequinox
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 c50b16c..940327a 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
@@ -25,6 +25,7 @@
 import java.util.Set;
 
 import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.objectteams.otequinox.ActivationKind;
 
 /** 
@@ -92,7 +93,7 @@
 	}
 
 	/** Destructively read the names of teams to load for a given base class. */
-	public Collection<String> getTeamsForBase(String baseClassName) {
+	public @Nullable Collection<String> getTeamsForBase(String baseClassName) {
 		return teamsPerBase.remove(baseClassName);		
 	}
 
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 6859ec9..96c57c7 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
@@ -16,7 +16,7 @@
  **********************************************************************/
 package org.eclipse.objectteams.internal.osgi.weaving;
 
-import static org.eclipse.objectteams.otequinox.Activator.log;
+import static org.eclipse.objectteams.otequinox.TransformerPlugin.log;
 import static org.eclipse.objectteams.otequinox.Constants.ACTIVATION;
 import static org.eclipse.objectteams.otequinox.Constants.ASPECT_BINDING_EXTPOINT_ID;
 import static org.eclipse.objectteams.otequinox.Constants.BASE_PLUGIN;
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/ClassScanner.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/ClassScanner.java
index 75f953a..f8ef150 100644
--- a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/ClassScanner.java
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/internal/osgi/weaving/ClassScanner.java
@@ -16,7 +16,7 @@
  **********************************************************************/
 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.io.IOException;
 import java.io.InputStream;
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 d0ca523..6b3f7a8 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
@@ -15,15 +15,19 @@
  **********************************************************************/
 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.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;
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.objectteams.otequinox.TransformerPlugin;
 import org.eclipse.objectteams.otequinox.hook.ILogger;
 import org.eclipse.objectteams.otre.jplis.ObjectTeamsTransformer;
 import org.osgi.framework.Bundle;
@@ -60,6 +64,7 @@
 	public void activate(ComponentContext context) {
 		this.aspectBindingRegistry = loadAspectBindingRegistry(context.getBundleContext());
 		this.objectTeamsTransformer = new ObjectTeamsTransformer();
+		TransformerPlugin.getDefault().registerAspectBindingRegistry(this.aspectBindingRegistry);
 	}
 
 	@SuppressWarnings("deprecation")
@@ -95,10 +100,24 @@
 					log(IStatus.INFO, "About to transform class "+wovenClass);
 					byte[] newBytes = objectTeamsTransformer.transform(bundleWiring.getClassLoader(),
 										className, classBeingRedefined, protectionDomain, bytes);
-					if (newBytes != bytes) {
+					if (newBytes != bytes && !Arrays.equals(newBytes, bytes)) {
 						wovenClass.setBytes(newBytes);
-						if (otreAdded.add(bundleWiring.getBundle()))
-							wovenClass.getDynamicImports().add("org.objectteams");
+						if (otreAdded.add(bundleWiring.getBundle())) {
+							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) {
 					log(e, "Failed to transform class "+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 5467182..0a60d80 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
@@ -15,7 +15,7 @@
  **********************************************************************/
 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.net.URL;
 import java.util.ArrayList;
@@ -25,6 +25,7 @@
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.objectteams.internal.osgi.weaving.AspectBindingRegistry.WaitingTeamRecord;
 import org.eclipse.objectteams.otequinox.ActivationKind;
+import org.eclipse.objectteams.otequinox.TransformerPlugin;
 import org.eclipse.objectteams.otequinox.hook.ILogger;
 import org.objectteams.ITeam;
 import org.objectteams.Team;
@@ -156,6 +157,7 @@
 	private @Nullable ITeam instantiateTeam(AspectBinding aspectBinding, Class<? extends ITeam> teamClass, String teamName) {
 		try {
 			ITeam instance = teamClass.newInstance();
+			TransformerPlugin.registerTeamInstance(instance);
 			log(ILogger.INFO, "Instantiated team "+teamName);
 			return instance;
 		} catch (NoClassDefFoundError ncdfe) {
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/Activator.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/Activator.java
deleted file mode 100644
index b917a01..0000000
--- a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/Activator.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.eclipse.objectteams.otequinox;
-
-import static org.eclipse.objectteams.otequinox.Constants.TRANSFORMER_PLUGIN_ID;
-
-import org.eclipse.core.runtime.ILog;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.objectteams.otequinox.hook.ILogger;
-import org.eclipse.objectteams.otre.ClassLoaderAccess;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-public class Activator implements BundleActivator {
-
-	private static BundleContext context;
-
-	static BundleContext getContext() {
-		return context;
-	}
-
-	private static ILog log;
-
-	/*
-	 * (non-Javadoc)
-	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
-	 */
-	public void start(BundleContext bundleContext) throws Exception {
-		Activator.context = bundleContext;
-		
-		acquireLog(bundleContext);
-	
-		OTREInit();
-	}
-
-	@SuppressWarnings("restriction")
-	private void acquireLog(BundleContext bundleContext) {
-		try {
-			Activator.log = org.eclipse.core.internal.runtime.InternalPlatform.getDefault().getLog(bundleContext.getBundle());
-		} catch (NullPointerException npe) {
-			// WTF?
-		}
-	}
-
-	private void OTREInit() {
-		try {
-			ClassLoaderAccess.setLoadClass(Bundle.class.getMethod("loadClass", String.class));
-			ClassLoaderAccess.setGetResource(Bundle.class.getMethod("getResource", String.class));
-		} catch (NoSuchMethodException | SecurityException e) {
-			log(e, "Failed to wire an OSGi class into the OTRE");
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
-	 */
-	public void stop(BundleContext bundleContext) throws Exception {
-		Activator.context = null;
-	}
-
-	// configure OT/Equinox debugging:
-	public static int WARN_LEVEL = ILogger.ERROR;
-	static {
-		String level = System.getProperty("otequinox.debug");
-		if (level != null) {
-			level = level.toUpperCase();
-			if (level.equals("OK"))
-				WARN_LEVEL = ILogger.OK;
-			else if (level.equals("INFO"))
-				WARN_LEVEL = ILogger.INFO;
-			else if (level.startsWith("WARN"))
-				WARN_LEVEL = ILogger.WARNING;
-			else if (level.startsWith("ERR"))
-				WARN_LEVEL = ILogger.ERROR;
-			else
-				WARN_LEVEL = ILogger.OK;
-		}
-	}
-
-	public static void log (Throwable ex, String msg) {
-		msg = "OT/Equinox: "+msg;
-		System.err.println(msg);
-		ex.printStackTrace();
-		if (log != null)
-			log.log(new Status(IStatus.ERROR, TRANSFORMER_PLUGIN_ID, msg, ex));
-		else
-			System.err.println(msg);
-	}
-	
-	public static void log(int status, String msg) {
-		if (status >= WARN_LEVEL)
-			doLog(status, msg);
-	}
-
-	private static void doLog(int status, String msg) {
-		msg = "OT/Equinox: "+msg;
-		if (log != null)
-			log.log(new Status(status, TRANSFORMER_PLUGIN_ID, msg));
-		else
-			System.err.println(msg);
-	}
-}
diff --git a/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/IAspectRegistry.java b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/IAspectRegistry.java
new file mode 100644
index 0000000..0fc118a
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/IAspectRegistry.java
@@ -0,0 +1,67 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ * 
+ * Copyright 2007, 2009 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
+ * 
+ * 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.otequinox;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.osgi.framework.Bundle;
+
+/**
+ * This slice of the IOTEquinoxService provides features to query the
+ * registry of aspectBindings.
+ * 
+ * @author stephan
+ * @since OTDT 1.1.4
+ */
+public interface IAspectRegistry {
+
+	/** Are we running within the OTDT? */
+	public boolean isOTDT();
+	
+	/** Is `symbolicName' the name of a base plugin for which an adapting team is registered? */
+	public boolean isAdaptedBasePlugin(String baseBundleName);
+
+	/**
+  	 * Get the names of aspect plugins adapting a given base plugin.
+	 * @param basePlugin base plugin.
+	 * @return non-null array of symbolic names of aspect plugins.
+ 	 */
+	public @NonNull String[] getAdaptingAspectPlugins(Bundle baseBundle);
+
+	/**
+	 *  Get the plugin IDs of all base plugins adapted by this aspect plugin.
+	 *  If this plugin is not an aspect plugin return null.
+	 *  @param aspectBundle potential aspect plugin
+	 *  @return array of base plugin IDs or null.
+	 */
+	public @Nullable String[] getAdaptedBasePlugins(Bundle aspectBundle);
+
+	/**
+	 * Does `bundle' have internal teams, i.e., teams that adapt classes from their
+	 * enclosing plug-in only?
+	 * @param bundle
+	 * @return
+	 */
+	public boolean hasInternalTeams(Bundle bundle);
+
+	/**
+	 * Does the symbolic name refer to an aspect bundle for which some permission was denied?
+	 * @param symbolicName
+	 * @return
+	 */
+	public boolean isDeniedAspectPlugin(String symbolicName);
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..d26aff9
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.osgi.weaving/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
@@ -0,0 +1,179 @@
+package org.eclipse.objectteams.otequinox;
+
+import static org.eclipse.objectteams.otequinox.Constants.TRANSFORMER_PLUGIN_ID;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.objectteams.internal.osgi.weaving.AspectBinding;
+import org.eclipse.objectteams.internal.osgi.weaving.AspectBindingRegistry;
+import org.eclipse.objectteams.otequinox.hook.ILogger;
+import org.eclipse.objectteams.otre.ClassLoaderAccess;
+import org.objectteams.ITeam;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class TransformerPlugin implements BundleActivator, IAspectRegistry {
+
+	private static BundleContext context;
+
+	static BundleContext getContext() {
+		return context;
+	}
+
+	private static ILog log;
+	private static TransformerPlugin plugin;
+	
+	private AspectBindingRegistry aspectBindingRegistry;
+	private List<ITeam> teamInstances = new ArrayList<>();
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext bundleContext) throws Exception {
+		plugin = this;
+		TransformerPlugin.context = bundleContext;
+		
+		acquireLog(bundleContext);
+	
+		OTREInit();
+	}
+
+	@SuppressWarnings("restriction")
+	private void acquireLog(BundleContext bundleContext) {
+		try {
+			TransformerPlugin.log = org.eclipse.core.internal.runtime.InternalPlatform.getDefault().getLog(bundleContext.getBundle());
+		} catch (NullPointerException npe) {
+			// WTF?
+		}
+	}
+
+	private void OTREInit() {
+		try {
+			ClassLoaderAccess.setLoadClass(Bundle.class.getMethod("loadClass", String.class));
+			ClassLoaderAccess.setGetResource(Bundle.class.getMethod("getResource", String.class));
+		} catch (NoSuchMethodException | SecurityException e) {
+			log(e, "Failed to wire an OSGi class into the OTRE");
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext bundleContext) throws Exception {
+		TransformerPlugin.context = null;
+	}
+
+	// configure OT/Equinox debugging:
+	public static int WARN_LEVEL = ILogger.ERROR;
+	static {
+		String level = System.getProperty("otequinox.debug");
+		if (level != null) {
+			level = level.toUpperCase();
+			if (level.equals("OK"))
+				WARN_LEVEL = ILogger.OK;
+			else if (level.equals("INFO"))
+				WARN_LEVEL = ILogger.INFO;
+			else if (level.startsWith("WARN"))
+				WARN_LEVEL = ILogger.WARNING;
+			else if (level.startsWith("ERR"))
+				WARN_LEVEL = ILogger.ERROR;
+			else
+				WARN_LEVEL = ILogger.OK;
+		}
+	}
+
+	public static void log (Throwable ex, String msg) {
+		msg = "OT/Equinox: "+msg;
+		System.err.println(msg);
+		ex.printStackTrace();
+		if (log != null)
+			log.log(new Status(IStatus.ERROR, TRANSFORMER_PLUGIN_ID, msg, ex));
+		else
+			System.err.println(msg);
+	}
+	
+	public static void log(int status, String msg) {
+		if (status >= WARN_LEVEL)
+			doLog(status, msg);
+	}
+
+	private static void doLog(int status, String msg) {
+		msg = "OT/Equinox: "+msg;
+		if (log != null)
+			log.log(new Status(status, TRANSFORMER_PLUGIN_ID, msg));
+		else
+			System.err.println(msg);
+	}
+	
+	
+
+	public static TransformerPlugin getDefault() {
+		return plugin;
+	}
+
+	public void registerAspectBindingRegistry(AspectBindingRegistry aspectBindingRegistry) {
+		this.aspectBindingRegistry = aspectBindingRegistry;
+	}
+
+	/**
+	 * public API:
+	 * {@link IAspectRegistry#getAdaptingAspectPlugins(Bundle)} 
+	 */
+	public @NonNull String[] getAdaptingAspectPlugins(Bundle basePlugin) {
+		List<AspectBinding> aspectBindings = this.aspectBindingRegistry.getAdaptingAspectBindings(basePlugin.getSymbolicName());
+		if (aspectBindings == null)
+			return new String[0];
+		String[] result = new String[aspectBindings.size()];
+		for (int i = 0; i < result.length; i++)
+			result[i] = aspectBindings.get(i).aspectPlugin;
+		return result;
+	}
+
+	public static void registerTeamInstance(ITeam instance) {
+		plugin.teamInstances.add(instance);
+	}
+	/**
+	 * Copy all registered team instances into the given list,
+     */
+	public static synchronized void getTeamInstances(List<ITeam> list) {
+		list.addAll(plugin.teamInstances);
+	}
+
+	@Override
+	public boolean isOTDT() {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	@Override
+	public boolean isAdaptedBasePlugin(String baseBundleName) {
+		return this.aspectBindingRegistry.isAdaptedBasePlugin(baseBundleName);
+	}
+
+	@Override
+	public String[] getAdaptedBasePlugins(Bundle aspectBundle) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public boolean hasInternalTeams(Bundle bundle) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	@Override
+	public boolean isDeniedAspectPlugin(String symbolicName) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+}