Bug 406518 - migrate OT/Equinox to the standard OSGi WeavingHook
Preparation: make resource loading strategy configurable
- default: ClassLoader, optional: via provided java.lang.Method's
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/ClassLoaderAccess.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/ClassLoaderAccess.java
new file mode 100644
index 0000000..a92e184
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/ClassLoaderAccess.java
@@ -0,0 +1,69 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2013 GK Software AG
+ *  
+ * 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.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * 	Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otre;
+
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+
+/**
+ * Generalization over different strategies for obtaining a resource / class on the classpath.
+ * <p>
+ * If a {@link ClassLoader} is provided use its method {@link ClassLoader#getResource(String)} 
+ * and {@link ClassLoader#loadClass(String)}.
+ * </p><p>
+ * Otherwise we need a {@link Method} instance for each kind of access which needs to match
+ * the type of the object passed as "loader". The latter method is used in Equinox settings,
+ * where the "loader" will be an <code>org.osgi.framework.Bundle</code>.
+ * </p><p>
+ * Selecting one of the above strategies happens globally when the system start up,
+ * which implies that {@link #setGetResource(Method)} and {@link #setLoadClass(Method)}
+ * need to be called before any weaving is triggered.
+ * </p>
+ */
+public class ClassLoaderAccess {
+
+	private static Method getResourceMethod;
+	private static Method loadClassMethod;
+
+	public static void setGetResource(Method method) {
+		getResourceMethod = method;
+	}
+	public static void setLoadClass(Method method) {
+		loadClassMethod = method;
+	}
+
+	public static InputStream getResourceAsStream(Object loader, String name) {
+		if (loader instanceof ClassLoader)
+			return ((ClassLoader) loader).getResourceAsStream(name);
+		try {
+			URL url = (URL) getResourceMethod.invoke(loader, name);
+			return url.openStream();
+		} catch (Exception e) {
+			return null;
+		}
+	}
+
+	public static Class<?> loadClass(Object loader, String name) 
+			throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException 
+	{
+		if (loader instanceof ClassLoader)
+			return ((ClassLoader) loader).loadClass(name);
+		else
+			return (Class<?>)loadClassMethod.invoke(loader, name);
+	}
+}
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 0dcdb56..b62e874 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
@@ -116,7 +116,7 @@
 			if (participant != null)
 				throw new IllegalStateException("liftingParticipant already installed.");				
 			// install a shared instance into class Team:
-			Class<?> participantClass = loader.loadClass(PARTICIPANT_NAME);
+			Class<?> participantClass = ClassLoaderAccess.loadClass(loader, PARTICIPANT_NAME); 
 			participantField.set(null, participantClass.newInstance());
 		} 
 		else if (participant != null) 
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java
index 1463e2a..daaa278 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java
@@ -95,9 +95,9 @@
 	InstructionFactory factory;
    
     /** Which class loader are we working for? */
-    protected ClassLoader loader;
+    protected Object loader; // standalone: ClassLoader, new equinox.weaving: Bundle
 
-	public ObjectTeamsTransformation(ClassLoader loader) {
+	public ObjectTeamsTransformation(Object loader) {
 		this.loader = loader;
 	}
 
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/RepositoryAccess.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/RepositoryAccess.java
index 04b6fd0..15cd23c 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/RepositoryAccess.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/RepositoryAccess.java
@@ -32,7 +32,7 @@
 public class RepositoryAccess {
 
 	/** One class repository per class loader. */
-	private static HashMap<ClassLoader,DietClassLoaderRepository> repositories = new HashMap<ClassLoader,DietClassLoaderRepository>();
+	private static HashMap<Object,DietClassLoaderRepository> repositories = new HashMap<Object,DietClassLoaderRepository>();
 	/** One current repository per thread. */
 	private static ThreadLocal<DietClassLoaderRepository> currentRepository = new ThreadLocal<DietClassLoaderRepository>();
 	 
@@ -41,7 +41,7 @@
 	 * @param loader class loader, may be null
 	 * @return the previously active class repository for this thread
 	 */
-	public static synchronized DietClassLoaderRepository setClassLoader(ClassLoader loader) {
+	public static synchronized DietClassLoaderRepository setClassLoader(Object loader) {
 		DietClassLoaderRepository clr = null;
 		if (loader != null) { // avoid creating ClassLoaderRepository with null loader
 			clr = repositories.get(loader);
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/bcel/DietClassLoaderRepository.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/bcel/DietClassLoaderRepository.java
index f5654cf..3d92bc7 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/bcel/DietClassLoaderRepository.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/bcel/DietClassLoaderRepository.java
@@ -38,6 +38,7 @@
 
 import org.apache.bcel.classfile.JavaClass;
 import org.apache.bcel.util.ClassLoaderRepository;
+import org.eclipse.objectteams.otre.ClassLoaderAccess;
 
 /**
  * Class loader repository that retains less memory than BCEL's original.
@@ -46,10 +47,10 @@
 public class DietClassLoaderRepository extends ClassLoaderRepository {
 
 	// repeat a field that is private in the super class:
-	ClassLoader dietClassLoaderRepository_loader;
+	Object dietClassLoaderRepository_loader;
 	
-	public DietClassLoaderRepository(ClassLoader loader) {
-		super(loader);
+	public DietClassLoaderRepository(Object loader) {
+		super(loader instanceof ClassLoader ? (ClassLoader) loader : null);
 		dietClassLoaderRepository_loader = loader;
 	}
 
@@ -61,7 +62,7 @@
             return c;
         }
         try {
-            InputStream is = dietClassLoaderRepository_loader.getResourceAsStream(classFile + ".class");
+            InputStream is = ClassLoaderAccess.getResourceAsStream(dietClassLoaderRepository_loader, classFile + ".class");
             if (is == null) {
                 throw new ClassNotFoundException(className + " not found.");
             }
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 5944db4..d68b87d 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
@@ -228,7 +228,7 @@
 	 * @throws IOException 
 	 * @throws ClassFormatError 
 	 */
-	public void readOTAttributes(InputStream file, String fileName, ClassLoader loader) 
+	public void readOTAttributes(InputStream file, String fileName, Object loader) 
 			throws ClassFormatError, IOException 
 	{
 		ClassParser   cp  = new ClassParser(file, fileName);
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java
index 4d72e02..52a449c 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java
@@ -25,7 +25,7 @@
  */
 public class AttributeReadingGuard {
 	
-	private static Map<ClassLoader, AttributeReadingGuard> instances = new HashMap<ClassLoader, AttributeReadingGuard>();
+	private static Map<Object, AttributeReadingGuard> instances = new HashMap<Object, AttributeReadingGuard>();
     private static AttributeReadingGuard defaultInstance = new AttributeReadingGuard();
     
     private ArrayList<String> servedClasses = new ArrayList<String>();
@@ -66,15 +66,15 @@
 
 	/**
 	 * Since actual data are stored in an instance, static methods need to retrieve the appropriate
-     * instance regarding the given class loader.
+     * instance regarding the given token (s.t. like a class loader).
 	 */
-	public static AttributeReadingGuard getInstanceForLoader(ClassLoader loader) {
-		if (loader == null)
+	public static AttributeReadingGuard getInstanceForLoader(Object token) {
+		if (token == null)
 			return defaultInstance;
 		
-		AttributeReadingGuard instance = instances.get(loader);
+		AttributeReadingGuard instance = instances.get(token);
 		if (instance == null)
-			instances.put(loader, instance = new AttributeReadingGuard());
+			instances.put(token, instance = new AttributeReadingGuard());
 		return instance;
 	}
 }