Bug 218422 - Graduating the transform bundles from the incubator
diff --git a/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformInstanceListData.java b/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformInstanceListData.java
index b7dc28a..3983e0a 100644
--- a/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformInstanceListData.java
+++ b/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformInstanceListData.java
@@ -54,14 +54,25 @@
 	}
 
 	/**
-	 * Return the transforms currently held by this list. If a change has been detected since the last request this list will be rebuilt.
-	 * @return the transforms currently held by this list
+	 * Return the transforms types currently held by this list. If a change has been detected since the last request this list will be rebuilt.
+	 * @return the transforms types currently held by this list
 	 */
-	public synchronized TransformTuple[] getTransformsFor(String transformerClass) {
+	public synchronized String[] getTransformTypes() {
 		if (stale)
 			rebuildTransformMap();
 
-		return (TransformTuple[]) transformerToTuple.get(transformerClass);
+		return (String[]) transformerToTuple.keySet().toArray(new String[transformerToTuple.size()]);
+	}
+
+	/**
+	 * Return the transforms of a particular type currently held by this list. If a change has been detected since the last request this list will be rebuilt.
+	 * @return the transforms currently held by this list
+	 */
+	public synchronized TransformTuple[] getTransformsFor(String type) {
+		if (stale)
+			rebuildTransformMap();
+
+		return (TransformTuple[]) transformerToTuple.get(type);
 	}
 
 	/**
diff --git a/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformTuple.java b/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformTuple.java
index 2867129..6aab9b6 100644
--- a/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformTuple.java
+++ b/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformTuple.java
@@ -22,7 +22,7 @@
 	/**
 	 * Constant used when registering transform tuples to identify the type of transformer they should be assigned to.
 	 */
-	public static final String TRANSFORMER_TYPE = "transformerType"; //$NON-NLS-1$
+	public static final String TRANSFORMER_TYPE = "equinox.transformerType"; //$NON-NLS-1$
 	public Pattern bundlePattern;
 	public Pattern pathPattern;
 	public URL transformerUrl;
diff --git a/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformedBundleFile.java b/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformedBundleFile.java
index 240d99b..7b67673 100644
--- a/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformedBundleFile.java
+++ b/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformedBundleFile.java
@@ -97,16 +97,19 @@
 	 */
 	protected InputStream getInputStream(InputStream inputStream, Bundle bundle, String path) {
 		String namespace = bundle.getSymbolicName();
-		StreamTransformer[] transformerArray = transformers.getTransformers();
-		for (int i = 0; i < transformerArray.length; i++) {
-			StreamTransformer transformer = transformerArray[i];
-			Object toTest = transformer instanceof ProxyStreamTransformer ? ((ProxyStreamTransformer) transformer).getTransformer() : transformer;
 
-			TransformTuple[] transforms = templates.getTransformsFor(toTest.getClass().getName());
-			if (transforms == null)
-				return null;
-			for (int j = 0; j < transforms.length; j++) {
-				TransformTuple transformTuple = transforms[j];
+		String[] transformTypes = templates.getTransformTypes();
+		if (transformTypes.length == 0)
+			return null;
+		for (int i = 0; i < transformTypes.length; i++) {
+			StreamTransformer transformer = transformers.getTransformers(transformTypes[i]);
+			if (transformer == null)
+				continue;
+			TransformTuple[] transformTuples = templates.getTransformsFor(transformTypes[i]);
+			if (transformTuples == null)
+				continue;
+			for (int j = 0; j < transformTuples.length; j++) {
+				TransformTuple transformTuple = transformTuples[j];
 				if (match(transformTuple.bundlePattern, namespace) && match(transformTuple.pathPattern, path)) {
 					try {
 						return transformer.getInputStream(inputStream, transformTuple.transformerUrl);
@@ -116,8 +119,8 @@
 					}
 				}
 			}
-
 		}
+
 		return null;
 	}
 
@@ -210,7 +213,7 @@
 	 * a transform associated with it.
 	 */
 	private boolean hasTransforms(String path) {
-		if (transformers.getTransformers().length == 0)
+		if (!transformers.hasTransformers())
 			return false;
 		return templates.hasTransformsFor(data.getBundle());
 	}
diff --git a/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformerList.java b/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformerList.java
index b90b4f0..58caa4d 100644
--- a/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformerList.java
+++ b/bundles/org.eclipse.equinox.transforms.hook/src/org/eclipse/equinox/internal/transforms/TransformerList.java
@@ -11,7 +11,7 @@
 
 package org.eclipse.equinox.internal.transforms;
 
-import java.util.ArrayList;
+import java.util.HashMap;
 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
 import org.osgi.framework.*;
 import org.osgi.util.tracker.ServiceTracker;
@@ -29,7 +29,7 @@
 	/**
 	 * Local cache of transformers.
 	 */
-	private StreamTransformer[] transformers;
+	private HashMap transformers = new HashMap();
 
 	/**
 	 * Create a new instance of this list.
@@ -37,8 +37,9 @@
 	 * @throws InvalidSyntaxException thrown if there's an issue listening for changes to the given transformer type
 	 */
 	public TransformerList(BundleContext context) throws InvalidSyntaxException {
-		super(context, context.createFilter("(objectClass=" //$NON-NLS-1$
-				+ Object.class.getName() + ')'), null);
+		super(context, context.createFilter("(&(objectClass=" //$NON-NLS-1$
+				+ Object.class.getName() + ")(" + TransformTuple.TRANSFORMER_TYPE //$NON-NLS-1$
+				+ "=*))"), null); //$NON-NLS-1$
 		open();
 	}
 
@@ -47,42 +48,50 @@
 	 * If the list is stale it will first be rebuilt.
 	 * @return the transformers.
 	 */
-	public synchronized StreamTransformer[] getTransformers() {
+	public synchronized StreamTransformer getTransformers(String type) {
 		if (stale) {
-			rebuildTransformerArray();
+			rebuildTransformersMap();
 		}
-		return transformers;
+		return (StreamTransformer) transformers.get(type);
+	}
+
+	public synchronized boolean hasTransformers() {
+		if (stale) {
+			rebuildTransformersMap();
+		}
+		return transformers.size() > 0;
 	}
 
 	/**
 	 * Consults the bundle context for services of the transformer type and builds the internal cache.
 	 */
-	private void rebuildTransformerArray() {
-		Object[] services = getServices();
+	private void rebuildTransformersMap() {
+		transformers.clear();
+		ServiceReference[] serviceReferences = getServiceReferences();
 		stale = false;
-		if (services == null) {
-			transformers = new StreamTransformer[0];
-		} else {
-			ArrayList transformerList = new ArrayList(services.length);
-			for (int i = 0; i < services.length; i++) {
-				Object object = services[i];
-				if (object instanceof StreamTransformer)
-					transformerList.add(object);
-				else {
-					ProxyStreamTransformer transformer;
-					try {
-						transformer = new ProxyStreamTransformer(object);
-						transformerList.add(transformer);
-					} catch (SecurityException e) {
-						TransformerHook.log(FrameworkLogEntry.ERROR, "Problem creating transformer", e); //$NON-NLS-1$
-					} catch (NoSuchMethodException e) {
-						TransformerHook.log(FrameworkLogEntry.ERROR, "Problem creating transformer", e); //$NON-NLS-1$
-					}
+		if (serviceReferences == null)
+			return;
+
+		for (int i = 0; i < serviceReferences.length; i++) {
+			ServiceReference serviceReference = serviceReferences[i];
+			String type = serviceReference.getProperty(TransformTuple.TRANSFORMER_TYPE).toString();
+			if (type == null || transformers.get(type) != null)
+				continue;
+			Object object = getService(serviceReference);
+			if (object instanceof StreamTransformer)
+				transformers.put(type, object);
+			else {
+				ProxyStreamTransformer transformer;
+				try {
+					transformer = new ProxyStreamTransformer(object);
+					transformers.put(type, transformer);
+				} catch (SecurityException e) {
+					TransformerHook.log(FrameworkLogEntry.ERROR, "Problem creating transformer", e); //$NON-NLS-1$
+				} catch (NoSuchMethodException e) {
+					TransformerHook.log(FrameworkLogEntry.ERROR, "Problem creating transformer", e); //$NON-NLS-1$
 				}
 			}
-			this.transformers = (StreamTransformer[]) transformerList.toArray(new StreamTransformer[transformerList.size()]);
 		}
-
 	}
 
 	public Object addingService(ServiceReference reference) {
diff --git a/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/ProcessPipeInputStream.java b/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/ProcessPipeInputStream.java
deleted file mode 100644
index 3035679..0000000
--- a/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/ProcessPipeInputStream.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006 IBM Corporation 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
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.equinox.internal.transforms;
-
-import java.io.*;
-
-/**
- * This class allows the easy piping of data from an input stream to an external process.  
- * The resulting output is then returned via the {@link InputStream} methods of this class.
- */
-public class ProcessPipeInputStream extends InputStream {
-	protected Process process = null;
-	protected InputStream standardInput;
-	protected IOException failure;
-	private String commandString;
-	private String[] environment;
-	private File workingDirectory;
-
-	/**
-	 * Create a new process pipe with the provided stream supplying the contents of the standard input to the process.
-	 * 
-	 * @param standardInput the contents of standard input
-	 */
-	public ProcessPipeInputStream(InputStream standardInput, String commandString, String[] environment, File workingDirectory) {
-		this.standardInput = standardInput;
-		if (commandString == null)
-			throw new IllegalArgumentException();
-		this.commandString = commandString;
-		this.environment = environment;
-		this.workingDirectory = workingDirectory;
-	}
-
-	/**
-	 * Get the command string for this process.
-	 * The format of this String must conform to the specifications of the command parameter of {@link Runtime#exec(String[], String[], File)}.
-	 * @return the command string.  Never <code>null</code>.
-	 */
-	protected String getCommandString() {
-		return commandString;
-	}
-
-	/**
-	 * Get the environment variables for this process.
-	 * The format of the Strings in this array must conform to the specifications of the environment parameter of {@link Runtime#exec(String[], String[], File)}.
-	 * @return the environment variables or <code>null</code>
-	 */
-	protected String[] getEnvironment() {
-		return environment;
-	}
-
-	/**
-	 * Get the working directory for the process. 
-	 * @return the working directory or <code>null</code>
-	 */
-	protected File getWorkingDirectory() {
-		return workingDirectory;
-	}
-
-	public int read() throws IOException {
-		synchronized (this) {
-			if (failure != null) {
-				IOException e = new IOException("Problem piping the stream."); //$NON-NLS-1$
-				e.fillInStackTrace();
-				e.initCause(failure);
-				throw e;
-			}
-			if (process == null) {
-
-				process = Runtime.getRuntime().exec(getCommandString(), getEnvironment(), getWorkingDirectory());
-
-				Thread thread = new Thread(new Runnable() {
-
-					public void run() {
-						byte[] buffer = new byte[2048];
-						int len = 0;
-						try {
-							while ((len = standardInput.read(buffer)) > 0) {
-								process.getOutputStream().write(buffer, 0, len);
-							}
-							process.getOutputStream().close();
-						} catch (IOException e) {
-							synchronized (ProcessPipeInputStream.this) {
-								failure = e;
-								process.destroy();
-							}
-						}
-
-					}
-				});
-				thread.start();
-
-			}
-			return process.getInputStream().read();
-		}
-	}
-
-	/**
-	 * Resets the stream.  This has the effect of destroying the process, if one exists.
-	 */
-	public void reset() throws IOException {
-		synchronized (this) {
-			if (process != null) {
-				process.destroy();
-				process = null;
-				failure = null;
-			}
-		}
-		super.reset();
-	}
-}
diff --git a/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/xslt/Activator.java b/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/xslt/Activator.java
index 53ecf2e..b0188da 100644
--- a/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/xslt/Activator.java
+++ b/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/xslt/Activator.java
@@ -12,7 +12,6 @@
 package org.eclipse.equinox.internal.transforms.xslt;
 
 import java.util.Properties;
-import org.eclipse.equinox.internal.transforms.xslt.provisional.XSLTStreamTransformer;
 import org.eclipse.osgi.framework.log.FrameworkLog;
 import org.osgi.framework.*;
 import org.osgi.util.tracker.ServiceTracker;
@@ -30,7 +29,7 @@
 		logTracker.open();
 
 		Properties properties = new Properties();
-		properties.put("isStreamTransformer", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+		properties.put("equinox.transformerType", "xslt"); //$NON-NLS-1$ //$NON-NLS-2$
 
 		Object transformer = new XSLTStreamTransformer(logTracker);
 		registration = context.registerService(Object.class.getName(), transformer, properties);
diff --git a/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/xslt/provisional/XSLTStreamTransformer.java b/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/xslt/XSLTStreamTransformer.java
similarity index 98%
rename from bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/xslt/provisional/XSLTStreamTransformer.java
rename to bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/xslt/XSLTStreamTransformer.java
index 27a1e7e..d2d5b1e 100644
--- a/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/xslt/provisional/XSLTStreamTransformer.java
+++ b/bundles/org.eclipse.equinox.transforms.xslt/src/org/eclipse/equinox/internal/transforms/xslt/XSLTStreamTransformer.java
@@ -9,7 +9,7 @@
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 
-package org.eclipse.equinox.internal.transforms.xslt.provisional;
+package org.eclipse.equinox.internal.transforms.xslt;
 
 import java.io.*;
 import java.lang.ref.SoftReference;
@@ -19,7 +19,7 @@
 import javax.xml.transform.*;
 import javax.xml.transform.sax.SAXSource;
 import javax.xml.transform.stream.StreamResult;
-import org.eclipse.equinox.transforms.Pipe;
+import org.eclipse.equinox.internal.transforms.Pipe;
 import org.eclipse.osgi.framework.log.FrameworkLog;
 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
 import org.osgi.framework.FrameworkEvent;