[155723] Runtime bridge doesn't allow multiple components
diff --git a/plugins/org.eclipse.jst.server.core/plugin.xml b/plugins/org.eclipse.jst.server.core/plugin.xml
index f8e59fe..cf23753 100644
--- a/plugins/org.eclipse.jst.server.core/plugin.xml
+++ b/plugins/org.eclipse.jst.server.core/plugin.xml
@@ -5,6 +5,7 @@
   <extension-point id="runtimeClasspathProviders" name="%extensionPointRuntimeClasspathProviders" schema="schema/runtimeClasspathProviders.exsd"/>
   <extension-point id="runtimeFacetMappings" name="%extensionPointRuntimeFacetMappings" schema="schema/runtimeFacetMappings.exsd"/>
   <extension-point id="serverProfilers" name="%extensionPointServerProfilers" schema="schema/serverProfilers.exsd"/>
+  <extension-point id="internalRuntimeComponentProviders" name="internalRuntimeComponentProviders" schema="schema/internalRuntimeComponentProviders.exsd"/>
 
   <extension point="org.eclipse.jdt.core.classpathContainerInitializer">
     <classpathContainerInitializer
diff --git a/plugins/org.eclipse.jst.server.core/schema/internalRuntimeComponentProviders.exsd b/plugins/org.eclipse.jst.server.core/schema/internalRuntimeComponentProviders.exsd
new file mode 100644
index 0000000..bacc5c9
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.core/schema/internalRuntimeComponentProviders.exsd
@@ -0,0 +1,138 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.jst.server.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.jst.server.core" id="runtimeComponentProviders" name="Runtime Component Providers"/>
+      </appInfo>
+      <documentation>
+         This extension point is internal and experimental and should not be used by downstream components.
+This extension point is used to provide new runtime components to an existing facet runtime.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="runtimeComponentProvider" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  a fully qualified identifier of the target extension point
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  an optional identifier of the extension instance
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  an optional name of the extension instance
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="runtimeComponentProvider">
+      <annotation>
+         <appInfo>
+            <meta.element labelAttribute="name"/>
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence>
+         </sequence>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  specifies a unique identifier for this extension point
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="runtimeTypeIds" type="string" use="required">
+            <annotation>
+               <documentation>
+                  a comma separated list of runtime type ids that this provider may support. Used for memory &amp; performance reasons
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  specifies the fully qualified name of the Java class that extends &lt;samp&gt;RuntimeClasspathProviderDelegate&lt;/samp&gt;.
+Runtime classpath provider instances of this type will delegate to instances of this class.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.jst.server.core.RuntimeClasspathProviderDelegate"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         1.5.1
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         The following is an example of a runtime component provider extension point:
+
+&lt;pre&gt;
+  &lt;extension point=&quot;org.eclipse.jst.server.core.runtimeComponentProviders&quot;&gt;
+     &lt;runtimeComponentProvider
+        id=&quot;com.example.runtimeComponentProvider&quot;
+        runtimeTypeIds=&quot;com.example.runtime, com.example2.*&quot;
+        class=&quot;com.example.ExampleRuntimeComponentProvider&quot;/&gt;
+   &lt;/extension&gt;
+&lt;/pre&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that extends &lt;b&gt;org.eclipse.jst.server.core.RuntimeClasspathProviderDelegate&lt;/b&gt; and contains a public 0-arg constructor.
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2006 IBM Corporation and others.&lt;br&gt;
+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 
+&lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/JavaServerPlugin.java b/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/JavaServerPlugin.java
index acd18d6..22b76d6 100644
--- a/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/JavaServerPlugin.java
+++ b/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/JavaServerPlugin.java
@@ -45,6 +45,9 @@
 	//	cached copy of all runtime classpath providers
 	private static List runtimeClasspathProviders;
 
+	//	cached copy of all runtime component providers
+	private static List runtimeComponentProviders;
+
 	//	cached copy of all runtime facet mappings
 	private static List runtimeFacetMappings;
 
@@ -322,6 +325,57 @@
 	}
 
 	/**
+	 * Returns the runtime component provider that supports the given runtime type, or <code>null</code>
+	 * if none. This convenience method searches the list of known runtime
+	 * component providers for the one with a matching runtime type.
+	 * The runtimeType may not be null.
+	 *
+	 * @param runtimeType a runtime type
+	 * @return the runtime component provider instance, or <code>null</code> if
+	 *   there is no runtime component provider with the given id
+	 */
+	public static RuntimeComponentProviderWrapper findRuntimeComponentProvider(IRuntimeType runtimeType) {
+		if (runtimeType == null)
+			throw new IllegalArgumentException();
+
+		if (runtimeComponentProviders == null)
+			loadRuntimeComponentProviders();
+		
+		Iterator iterator = runtimeComponentProviders.iterator();
+		while (iterator.hasNext()) {
+			RuntimeComponentProviderWrapper runtimeComponentProvider = (RuntimeComponentProviderWrapper) iterator.next();
+			if (runtimeComponentProvider.supportsRuntimeType(runtimeType))
+				return runtimeComponentProvider;
+		}
+		return null;
+	}
+
+	/**
+	 * Load the runtime component providers.
+	 */
+	private static synchronized void loadRuntimeComponentProviders() {
+		if (runtimeComponentProviders != null)
+			return;
+		Trace.trace(Trace.CONFIG, "->- Loading .runtimeComponentProviders extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(JavaServerPlugin.PLUGIN_ID, "internalRuntimeComponentProviders");
+		
+		int size = cf.length;
+		List list = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				list.add(new RuntimeComponentProviderWrapper(cf[i]));
+				Trace.trace(Trace.CONFIG, "  Loaded runtimeComponentProviders: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load runtimeComponentProvider: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		runtimeComponentProviders = list;
+		
+		Trace.trace(Trace.CONFIG, "-<- Done loading .runtimeComponentProviders extension point -<-");
+	}
+
+	/**
 	 * Load the runtime facet mappings.
 	 */
 	private static synchronized void loadRuntimeFacetMapping() {
diff --git a/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/RuntimeBridge.java b/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/RuntimeBridge.java
index 998c21a..336ee89 100644
--- a/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/RuntimeBridge.java
+++ b/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/RuntimeBridge.java
@@ -1,5 +1,6 @@
 /******************************************************************************
  * Copyright (c) 2005 BEA Systems, Inc.
+ * 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
@@ -191,6 +192,13 @@
 				components.add(RuntimeManager.createRuntimeComponent(rcv, properties));
 			}
 			
+			RuntimeComponentProviderWrapper componentProvider = JavaServerPlugin.findRuntimeComponentProvider(runtime.getRuntimeType());
+			if (componentProvider != null) {
+				List list = componentProvider.getComponents(runtime);
+				if (list != null)
+					components.addAll(list);
+			}
+			
 			return components;
 		}
 
diff --git a/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/RuntimeComponentProviderDelegate.java b/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/RuntimeComponentProviderDelegate.java
new file mode 100644
index 0000000..e5185f5
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/RuntimeComponentProviderDelegate.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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.jst.server.core.internal;
+
+import java.util.List;
+
+import org.eclipse.wst.server.core.IRuntime;
+/**
+ * A runtime component provider can provide additional runtime components for a facet runtime.
+ * This provider is scoped by runtime type and may provide components for multiple
+ * runtime instances.
+ * <p>
+ * This abstract class is intended to be extended only by clients
+ * to extend the <code>internalRuntimeComponentProviders</code> extension point.
+ * </p>
+ * <p>
+ * <b>Provisional API:</b> This class/interface is part of an interim API that is still under development and expected to 
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback 
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken 
+ * (repeatedly) as the API evolves.
+ * </p>
+ * 
+ * @plannedfor 2.0
+ */
+public abstract class RuntimeComponentProviderDelegate {
+	public RuntimeComponentProviderDelegate() {
+		// default constructor
+	}
+
+	/**
+	 * Add runtime components to the given runtime. Components should be created by calling
+	 * RuntimeManager.createRuntimeComponent(IRuntimeComponentVersion, Map)
+	 * 
+	 * @param runtime a server runtime
+	 * @return a list of runtimes, or an empty list or null if there are no additional components
+	 */
+	public abstract List getRuntimeComponents(IRuntime runtime);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/RuntimeComponentProviderWrapper.java b/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/RuntimeComponentProviderWrapper.java
new file mode 100644
index 0000000..fd74dcc
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.core/sjavacore/org/eclipse/jst/server/core/internal/RuntimeComponentProviderWrapper.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * 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.jst.server.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IRuntimeType;
+/**
+ * 
+ */
+public class RuntimeComponentProviderWrapper {
+	private IConfigurationElement element;
+	private RuntimeComponentProviderDelegate delegate;
+
+	/**
+	 * Create a new runtime component handler.
+	 * 
+	 * @param element a configuration element
+	 */
+	public RuntimeComponentProviderWrapper(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+	
+	protected IConfigurationElement getElement() {
+		return element;
+	}
+
+	/**
+	 * 
+	 * @return the id
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+
+	public String[] getRuntimeTypeIds() {
+		try {
+			List list = new ArrayList();
+			StringTokenizer st = new StringTokenizer(element.getAttribute("runtimeTypeIds"), ",");
+			while (st.hasMoreTokens()) {
+				String str = st.nextToken();
+				if (str != null && str.length() > 0)
+					list.add(str.trim());
+			}
+			String[] s = new String[list.size()];
+			list.toArray(s);
+			return s;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not parse runtime type ids: " + element);
+			return null;
+		}
+	}
+
+	/**
+	 * Returns true if the given server resource type (given by the
+	 * id) can be opened with this editor. This result is based on
+	 * the result of the getServerResources() method.
+	 *
+	 * @param runtimeType a runtime type
+	 * @return boolean
+	 */
+	public boolean supportsRuntimeType(IRuntimeType runtimeType) {
+		if (runtimeType == null)
+			return false;
+		String id = runtimeType.getId();
+		if (id == null || id.length() == 0)
+			return false;
+
+		String[] s = getRuntimeTypeIds();
+		if (s == null)
+			return false;
+		
+		int size = s.length;
+		for (int i = 0; i < size; i++) {
+			if (s[i].endsWith("*")) {
+				if (id.length() >= s[i].length() && id.startsWith(s[i].substring(0, s[i].length() - 1)))
+					return true;
+			} else if (id.equals(s[i]))
+				return true;
+		}
+		return false;
+	}
+
+	/*
+	 * Loads the delegate class.
+	 */
+	protected RuntimeComponentProviderDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (RuntimeComponentProviderDelegate) element.createExecutableExtension("class");
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString() + ": " + t.getMessage());
+			}
+		}
+		return delegate;
+	}
+
+	/*
+	 * @see RuntimeComponentProviderDelegate#getRuntimeComponents(IRuntime)
+	 */
+	public List getComponents(IRuntime runtime) {
+		if (runtime == null)
+			return null;
+		try {
+			return getDelegate().getRuntimeComponents(runtime);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+		return null;
+	}
+
+	public String toString() {
+		return "RuntimeComponentProviderWrapper[" + getId() + "]";
+	}
+}
\ No newline at end of file