Bug 363930 - Add org.eclipse.equinox.http.servlet.tests to rt.equinox.bundles
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/.classpath b/bundles/org.eclipse.equinox.http.servlet.tests/.classpath
new file mode 100644
index 0000000..7aada44
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="bundles_src/tb1" output="bundles_bin/tb1"/>	
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/.gitignore b/bundles/org.eclipse.equinox.http.servlet.tests/.gitignore
new file mode 100644
index 0000000..cd03099
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/.gitignore
@@ -0,0 +1 @@
+/bundles_bin
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/.project b/bundles/org.eclipse.equinox.http.servlet.tests/.project
new file mode 100644
index 0000000..2fdc7fe
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.equinox.http.servlet.tests</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ds.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..370ae2c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=ISO-8859-1
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..5a0ad22
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..d4cbd54
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Wed Oct 19 14:22:52 EDT 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
+org.eclipse.jdt.core.compiler.source=1.3
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.pde.core.prefs b/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000..4acfed6
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,3 @@
+#Wed Oct 19 16:40:20 EDT 2011
+eclipse.preferences.version=1
+resolve.requirebundle=false
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.http.servlet.tests/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..dd83e15
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: org.eclipse.equinox.http.servlet.tests
+Bundle-SymbolicName: org.eclipse.equinox.http.servlet.tests
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-Activator: org.eclipse.equinox.http.servlet.tests.bundle.Activator
+Import-Package: javax.servlet;version="2.6.0",
+ javax.servlet.http;version="2.6.0",
+ junit.framework;version="4.8.2",
+ org.eclipse.osgi.service.urlconversion;version="1.0.0",
+ org.osgi.framework;version="1.6.0",
+ org.osgi.service.http;version="1.2.1",
+ org.osgi.util.tracker;version="1.5.0"
+Bundle-ActivationPolicy: lazy
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/about.html b/bundles/org.eclipse.equinox.http.servlet.tests/about.html
new file mode 100644
index 0000000..4602330
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 2, 2006</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/build.properties b/bundles/org.eclipse.equinox.http.servlet.tests/build.properties
new file mode 100644
index 0000000..8cd66c8
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/build.properties
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2011 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
+###############################################################################
+source.. = src/
+bin.includes = .,\
+               META-INF/,\
+               bundles_bin/tb1.jar,\
+               about.html
+jars.compile.order = .,\
+                     bundles_bin/tb1.jar
+source.bundles_bin/tb1.jar = bundles_src/tb1/
+manifest.bundles_bin/tb1.jar = META-INF/MANIFEST.MF
+
+additional.bundles = org.junit,\
+                     javax.servlet,\
+                     org.eclipse.osgi.services,\
+                     org.eclipse.osgi
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..c260711
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ActivationPolicy: lazy
+Bundle-ManifestVersion: 2
+Bundle-Name: org.eclipse.equinox.http.servlet.tests.tb1
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-SymbolicName: org.eclipse.equinox.http.servlet.tests.tb1
+Bundle-Vendor: IBM
+Bundle-Version: 1.0.0.qualifier
+Service-Component: OSGI-INF/*_component.xml
+Import-Package: javax.servlet,
+ javax.servlet.http,
+ org.osgi.service.http
+Require-Bundle: org.eclipse.equinox.ds;bundle-version="1.3.100"
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/OSGI-INF/testServlet1_component.xml b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/OSGI-INF/testServlet1_component.xml
new file mode 100644
index 0000000..7d28daa
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/OSGI-INF/testServlet1_component.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true">
+   <implementation class="org.eclipse.equinox.http.servlet.tests.tb1.TestServlet1"/>
+   <reference interface="org.osgi.service.http.HttpService"
+      bind="setHttpService"/>
+</scr:component>
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/OSGI-INF/testServlet2_component.xml b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/OSGI-INF/testServlet2_component.xml
new file mode 100644
index 0000000..9a4e360
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/OSGI-INF/testServlet2_component.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true">
+   <implementation class="org.eclipse.equinox.http.servlet.tests.tb1.TestServlet2"/>
+   <reference interface="org.osgi.service.http.HttpService"
+      bind="setHttpService"/>
+</scr:component>
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/OSGI-INF/testServlet3_component.xml b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/OSGI-INF/testServlet3_component.xml
new file mode 100644
index 0000000..1571f84
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/OSGI-INF/testServlet3_component.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true">
+   <implementation class="org.eclipse.equinox.http.servlet.tests.tb1.TestServlet3"/>
+   <reference interface="org.osgi.service.http.HttpService"
+      bind="setHttpService"/>
+</scr:component>
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb/AbstractTestServlet.java b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb/AbstractTestServlet.java
new file mode 100644
index 0000000..e16d5e8
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb/AbstractTestServlet.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.http.servlet.tests.tb;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.NamespaceException;
+
+/*
+ * The parent class for the various test servlets. This class is responsible 
+ * for registering the servlet with the HttpService, and handles the HTTP GET
+ * requests by providing a template method that is implemented by subclasses.
+ */
+public abstract class AbstractTestServlet extends HttpServlet {
+	private static final long serialVersionUID = 1L;
+	protected static final String STATUS_OK = "OK"; //$NON-NLS-1$	
+	protected static final String STATUS_ERROR = "ERROR"; //$NON-NLS-1$
+	
+	private HttpService service;
+	
+	public final void activate() throws ServletException, NamespaceException {
+		HttpService service = getHttpService();
+		String alias = getAlias();
+		service.registerServlet(alias, this, null, null);
+	}
+
+	protected final String createDefaultAlias() {
+		return '/' + getSimpleClassName();
+	}
+	
+	public final void deactivate() {
+		HttpService service = getHttpService();
+		String alias = getAlias();
+		service.unregister(alias);
+	}
+
+	protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+		PrintWriter writer = response.getWriter();
+		try {
+			handleDoGet(request, writer);
+		} finally {
+			writer.close();
+		}
+	}
+	
+	protected String getAlias() {
+		return createDefaultAlias();
+	}
+
+	private HttpService getHttpService() {
+		return service;
+	}
+	
+	private String getSimpleClassName() {
+		Class clazz = getClass();
+		return clazz.getSimpleName();
+	}
+
+	protected void handleDoGet(HttpServletRequest request, PrintWriter writer) throws ServletException, IOException {
+		writer.print(AbstractTestServlet.STATUS_OK);
+	}
+	
+	public final void setHttpService(HttpService service) {
+		this.service = service;
+	}
+}
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb1/TestServlet1.java b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb1/TestServlet1.java
new file mode 100644
index 0000000..0f02d97
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb1/TestServlet1.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.http.servlet.tests.tb1;
+
+import org.eclipse.equinox.http.servlet.tests.tb.AbstractTestServlet;
+
+/*
+ * This servlet is registered with the HttpService via the immediate DS
+ * component OSGI-INF/testServlet1_component.xml.
+ */
+public class TestServlet1 extends AbstractTestServlet {
+	private static final long serialVersionUID = 1L;
+}
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb1/TestServlet2.java b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb1/TestServlet2.java
new file mode 100644
index 0000000..defb7db
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb1/TestServlet2.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.http.servlet.tests.tb1;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.equinox.http.servlet.tests.tb.AbstractTestServlet;
+
+/*
+ * This servlet is registered with the HttpService via the immediate DS
+ * component OSGI-INF/testServlet2_component.xml.
+ */
+public class TestServlet2 extends AbstractTestServlet {
+	private static final long serialVersionUID = 1L;
+
+	private int getEffectiveMajorVersion() {
+		ServletContext context = getServletContext();
+		return context.getEffectiveMajorVersion(); // This is a Servlet 3.0 API.
+		
+	}
+
+	protected void handleDoGet(HttpServletRequest request, PrintWriter writer) throws ServletException, IOException {
+		int version = getEffectiveMajorVersion();
+		writer.print(version);
+	}
+}
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb1/TestServlet3.java b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb1/TestServlet3.java
new file mode 100644
index 0000000..dd8ab4d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/bundles_src/tb1/org/eclipse/equinox/http/servlet/tests/tb1/TestServlet3.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.http.servlet.tests.tb1;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.equinox.http.servlet.tests.tb.AbstractTestServlet;
+
+/*
+ * This servlet is registered with the HttpService via the immediate DS
+ * component OSGI-INF/testServlet3_component.xml.
+ */
+public class TestServlet3 extends AbstractTestServlet {
+	private static final long serialVersionUID = 1L;
+
+	private String getSessionCookieConfigComment() {
+		ServletContext context = getServletContext();
+		SessionCookieConfig cookieConfig = context.getSessionCookieConfig();  // This is a Servlet 3.0 API.
+		return cookieConfig.getComment();
+	}
+
+	protected void handleDoGet(HttpServletRequest request, PrintWriter writer) throws ServletException, IOException {
+		String expected = "Equinox";  //$NON-NLS-1$
+		setSessionCookieConfigComment(expected);
+		String actual = getSessionCookieConfigComment();
+		boolean ok = actual.equals(expected);
+		if (ok == false) {
+			writer.print(AbstractTestServlet.STATUS_ERROR);
+			return;
+		}
+		super.handleDoGet(request, writer);
+	}
+	
+	private void setSessionCookieConfigComment(String comment) {
+		ServletContext context = getServletContext();
+		SessionCookieConfig cookieConfig = context.getSessionCookieConfig();  // This is a Servlet 3.0 API.
+		cookieConfig.setComment(comment);
+	}
+}
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/AllTests.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/AllTests.java
new file mode 100644
index 0000000..a3f8742
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/AllTests.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.http.servlet.tests;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests extends Object {
+	public static Test suite() {
+		TestSuite suite = new TestSuite("Equinox HTTP Servlet Tests"); //$NON-NLS-1$
+		//$JUnit-BEGIN$
+		suite.addTestSuite(ServletTest.class);
+		//$JUnit-END$
+		return suite;
+	}
+}
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java
new file mode 100644
index 0000000..ceb556d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.http.servlet.tests;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.eclipse.equinox.http.servlet.tests.bundle.Activator;
+import org.eclipse.equinox.http.servlet.tests.bundle.BundleAdvisor;
+import org.eclipse.equinox.http.servlet.tests.bundle.BundleInstaller;
+import org.eclipse.equinox.http.servlet.tests.util.ServletRequestAdvisor;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+public class ServletTest extends TestCase {
+	private static final String EQUINOX_DS_BUNDLE = "org.eclipse.equinox.ds"; //$NON-NLS-1$
+	private static final String EQUINOX_JETTY_BUNDLE = "org.eclipse.equinox.http.jetty"; //$NON-NLS-1$
+	private static final String JETTY_PROPERTY_PREFIX = "org.eclipse.equinox.http.jetty."; //$NON-NLS-1$
+	private static final String OSGI_HTTP_PORT_PROPERTY = "org.osgi.service.http.port"; //$NON-NLS-1$
+	private static final String STATUS_OK = "OK"; //$NON-NLS-1$
+	private static final String TEST_BUNDLES_BINARY_DIRECTORY = "/bundles_bin/"; //$NON-NLS-1$
+	private static final String TEST_BUNDLE_1 = "tb1"; //$NON-NLS-1$
+	
+	private static final String[] BUNDLES = new String[] {
+		ServletTest.EQUINOX_DS_BUNDLE
+	};
+
+	private BundleInstaller installer;
+	private BundleAdvisor advisor;
+	private ServletRequestAdvisor requestAdvisor;
+
+	private BundleContext getBundleContext() {
+		return Activator.getBundleContext();
+	}
+	
+	private String getJettyProperty(String key, String defaultValue) {
+		String qualifiedKey = ServletTest.JETTY_PROPERTY_PREFIX + key;
+		String value = getProperty(qualifiedKey);
+		if (value == null) {
+			value = defaultValue;
+		}
+		return value;
+	}
+	
+	private String getPort() {
+		String defaultPort = getProperty(ServletTest.OSGI_HTTP_PORT_PROPERTY);
+		if (defaultPort == null) {
+			defaultPort = "80"; //$NON-NLS-1$
+		}
+		return getJettyProperty("port", defaultPort); //$NON-NLS-1$
+	}
+	
+	private String getProperty(String key) {
+		BundleContext bundleContext = getBundleContext();
+		String value = bundleContext.getProperty(key);
+		return value;
+	}
+	
+	private Bundle installBundle(String bundle) throws BundleException {
+		return installer.installBundle(bundle);
+	}
+
+	public void setUp() throws Exception {
+		BundleContext bundleContext = getBundleContext();
+		installer = new BundleInstaller(ServletTest.TEST_BUNDLES_BINARY_DIRECTORY, bundleContext);
+		advisor = new BundleAdvisor(bundleContext);
+		String port = getPort();
+		requestAdvisor = new ServletRequestAdvisor(port);
+		startBundles();
+		stopJetty();
+		startJetty();
+	}
+
+	private void startBundles() throws BundleException {
+		for (int i = 0; i < ServletTest.BUNDLES.length; i++) {
+			String bundle = ServletTest.BUNDLES[i];
+			advisor.startBundle(bundle);
+		}
+	}
+
+	private void startJetty() throws BundleException {
+		advisor.startBundle(ServletTest.EQUINOX_JETTY_BUNDLE);
+	}
+
+	private void stopBundles() throws BundleException {
+		for (int i = ServletTest.BUNDLES.length - 1; i >= 0; i--) {
+			String bundle = ServletTest.BUNDLES[i];
+			advisor.stopBundle(bundle);
+		}
+	}
+
+	private void stopJetty() throws BundleException {
+		advisor.stopBundle(ServletTest.EQUINOX_JETTY_BUNDLE);
+	}
+
+	public void tearDown() throws Exception {
+		stopJetty();
+		stopBundles();
+		requestAdvisor = null;		
+		advisor = null;
+		try {
+			installer.shutdown();
+		} finally {
+			installer = null;
+		}
+	}
+
+	public void test_TestServlet1() throws Exception {
+		String expected = ServletTest.STATUS_OK;
+		String actual;
+		Bundle bundle = installBundle(ServletTest.TEST_BUNDLE_1);
+		try {
+			bundle.start();
+			actual = requestAdvisor.request("TestServlet1"); //$NON-NLS-1$
+		} finally {
+			uninstallBundle(bundle);
+		}
+		Assert.assertEquals(expected, actual);
+	}
+	
+	public void test_TestServlet2() throws Exception {
+		String expected = "3";  //$NON-NLS-1$
+		String actual;
+		Bundle bundle = installBundle(ServletTest.TEST_BUNDLE_1);
+		try {
+			bundle.start();
+			actual = requestAdvisor.request("TestServlet2"); //$NON-NLS-1$
+			Assert.assertEquals(expected, actual);
+		} finally {
+			uninstallBundle(bundle);
+		}
+		Assert.assertEquals(expected, actual);		
+	}
+
+	public void test_TestServlet3() throws Exception {
+		String expected = ServletTest.STATUS_OK;
+		String actual;
+		Bundle bundle = installBundle(ServletTest.TEST_BUNDLE_1);
+		try {
+			bundle.start();
+			actual = requestAdvisor.request("TestServlet3"); //$NON-NLS-1$
+		} finally {
+			uninstallBundle(bundle);
+		}
+		Assert.assertEquals(expected, actual);
+	}
+	
+	private void uninstallBundle(Bundle bundle) throws BundleException {
+		installer.uninstallBundle(bundle);
+	}
+}
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/Activator.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/Activator.java
new file mode 100644
index 0000000..ec7ff5f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/Activator.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.http.servlet.tests.bundle;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/*
+ * The Bundle-Activator for the bundle. Ideally this class is kept as small as
+ * possible. 
+ */
+public class Activator extends Object implements BundleActivator {
+	private static Activator INSTANCE;
+
+	public static BundleContext getBundleContext() {
+		return Activator.INSTANCE != null ? Activator.INSTANCE.bundleContext : null;
+	}
+	
+	private BundleContext bundleContext;
+	
+	public Activator() {
+		super();
+		Activator.INSTANCE = this;
+	}
+
+	public void start(BundleContext bundleContext) throws Exception {
+		this.bundleContext = bundleContext;
+	}
+	
+	public void stop(BundleContext bundleContext) throws Exception {
+		this.bundleContext = null;
+	}
+}
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/BundleAdvisor.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/BundleAdvisor.java
new file mode 100644
index 0000000..1bb1046
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/BundleAdvisor.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.http.servlet.tests.bundle;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+/*
+ * The BundleAdvisor is responsible for starting and stopping bundles, given
+ * a Bundle-SymbolicName. It is an OSGi dependent class.
+ */
+public class BundleAdvisor extends Object {
+	private final BundleContext bundleContext;
+	
+	public BundleAdvisor(BundleContext bundleContext) {
+		super();
+		if (bundleContext == null)
+			throw new IllegalArgumentException("bundleContext must not be null"); //$NON-NLS-1$
+		this.bundleContext = bundleContext;
+	}
+	
+	private Bundle getBundle(String symbolicName) {
+		if (symbolicName == null)
+			throw new IllegalArgumentException("symbolicName must not be null"); //$NON-NLS-1$
+		BundleContext context = getBundleContext();
+		Bundle[] bundles = context.getBundles();
+		for (int i = 0; i < bundles.length; i++) {
+			Bundle bundle = bundles [ i ];
+			String bsn = bundle.getSymbolicName();
+			boolean match = symbolicName.equals(bsn); 
+			if (match) {
+				return bundle;
+			}
+		}
+		throw new IllegalArgumentException("Failed to find bundle: " + symbolicName); //$NON-NLS-1$
+	}
+	
+	private BundleContext getBundleContext() {
+		return bundleContext;
+	}
+	
+	public void startBundle(String symbolicName) throws BundleException {
+		Bundle bundle = getBundle(symbolicName);
+		int state = bundle.getState();
+		if (state == Bundle.ACTIVE) {
+			return;
+		}
+		bundle.start(Bundle.START_TRANSIENT);
+	}
+	
+	public void stopBundle(String symbolicName) throws BundleException {
+		Bundle bundle = getBundle(symbolicName);
+		bundle.stop();
+	}
+}
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/BundleInstaller.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/BundleInstaller.java
new file mode 100644
index 0000000..a2be4ed
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/BundleInstaller.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 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.http.servlet.tests.bundle;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.osgi.service.urlconversion.URLConverter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class BundleInstaller {
+	private BundleContext context;
+	private String rootLocation;
+	private HashMap bundles = new HashMap();
+	private ServiceTracker converter;
+
+	public BundleInstaller(String bundlesRoot, BundleContext context) throws InvalidSyntaxException {
+		this.context = context;
+		rootLocation = bundlesRoot;
+		converter = new ServiceTracker(context, context.createFilter("(&(objectClass=" + URLConverter.class.getName() + ")(protocol=bundleentry))"), null);
+		converter.open();
+	}
+
+	synchronized public Bundle installBundle(String name) throws BundleException {
+		return installBundle(name, true);
+	}
+
+	synchronized public Bundle installBundle(String name, boolean track) throws BundleException {
+		if (bundles == null && track)
+			return null;
+		String location = getBundleLocation(name);
+		Bundle bundle = context.installBundle(location);
+		if (track)
+			bundles.put(name, bundle);
+		return bundle;
+	}
+
+	public String getBundleLocation(String name) throws BundleException {
+		String bundleFileName = rootLocation + "/" + name;
+		URL bundleURL = context.getBundle().getEntry(bundleFileName);
+		if (bundleURL == null)
+			bundleURL = context.getBundle().getEntry(bundleFileName + ".jar");
+		if (bundleURL == null)
+			throw new BundleException("Could not find bundle to install at: " + name);
+		try {
+			bundleURL = ((URLConverter) converter.getService()).resolve(bundleURL);
+		} catch (IOException e) {
+			throw new BundleException("Converter error", e);
+		}
+		String location = bundleURL.toExternalForm();
+		if ("file".equals(bundleURL.getProtocol()))
+			location = "reference:" + location;
+		return location;
+	}
+
+	synchronized public Bundle updateBundle(String fromName, String toName) throws BundleException {
+		if (bundles == null)
+			return null;
+		Bundle fromBundle = (Bundle) bundles.get(fromName);
+		if (fromBundle == null)
+			throw new BundleException("The bundle to update does not exist!! " + fromName);
+		String bundleFileName = rootLocation + "/" + toName;
+		URL bundleURL = context.getBundle().getEntry(bundleFileName);
+		if (bundleURL == null)
+			bundleURL = context.getBundle().getEntry(bundleFileName + ".jar");
+		try {
+			bundleURL = ((URLConverter) converter.getService()).resolve(bundleURL);
+		} catch (IOException e) {
+			throw new BundleException("Converter error", e);
+		}
+		String location = bundleURL.toExternalForm();
+		if ("file".equals(bundleURL.getProtocol()))
+			location = "reference:" + location;
+		try {
+			fromBundle.update(new URL(location).openStream());
+		} catch (Exception e) {
+			throw new BundleException("Errors when updating bundle " + fromBundle, e);
+		}
+		bundles.remove(fromName);
+		bundles.put(toName, fromBundle);
+		return fromBundle;
+	}
+
+	synchronized public Bundle uninstallBundle(String name) throws BundleException {
+		if (bundles == null)
+			return null;
+		Bundle bundle = (Bundle) bundles.remove(name);
+		if (bundle == null)
+			return null;
+		bundle.uninstall();
+		return bundle;
+	}
+	
+	synchronized public void uninstallBundle(Bundle b) throws BundleException {
+		if (bundles == null)
+			return;
+		if (bundles.containsValue(b)) {
+			for (Iterator it = bundles.entrySet().iterator(); it.hasNext();) {
+				Map.Entry entry = (Map.Entry) it.next();
+				if (entry.getValue().equals(b)) {
+					bundles.remove(entry.getKey());
+					break;
+				}
+			}
+		}
+		b.uninstall();
+	}
+
+	synchronized public Bundle[] uninstallAllBundles() throws BundleException {
+		if (bundles == null)
+			return null;
+		ArrayList result = new ArrayList(bundles.size());
+		for (Iterator iter = bundles.values().iterator(); iter.hasNext();) {
+			Bundle bundle = (Bundle) iter.next();
+			try {
+				bundle.uninstall();
+			} catch (IllegalStateException e) {
+				// ignore; bundle probably already uninstalled
+			}
+			result.add(bundle);
+		}
+		bundles.clear();
+		return (Bundle[]) result.toArray(new Bundle[result.size()]);
+	}
+
+	synchronized public Bundle getBundle(String name) {
+		if (bundles == null)
+			return null;
+		return (Bundle) bundles.get(name);
+	}
+	
+	synchronized public Bundle[] shutdown() throws BundleException {
+		if (bundles == null)
+			return null;
+		Bundle[] result = uninstallAllBundles();
+		converter.close();
+		bundles = null;
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/ServletRequestAdvisor.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/ServletRequestAdvisor.java
new file mode 100644
index 0000000..e007fce
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/ServletRequestAdvisor.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.http.servlet.tests.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/*
+ * The ServletRequestAdvisor is responsible for composing URLs and using them
+ * to performing servlet requests. 
+ */
+public class ServletRequestAdvisor extends Object {
+	private final String port;
+
+	public ServletRequestAdvisor(String port) {
+		super();
+		if (port == null)
+			throw new IllegalArgumentException("port must not be null"); //$NON-NLS-1$
+		this.port = port;
+	}
+
+	private String createUrlSpec(String value) {
+		StringBuffer buffer = new StringBuffer(100);
+		String protocol = "http://"; //$NON-NLS-1$
+		String host = "localhost"; //$NON-NLS-1$
+		buffer.append(protocol);
+		buffer.append(host);
+		buffer.append(':');
+		buffer.append(port);
+		if (value != null) {
+			buffer.append('/');
+			buffer.append(value);
+		}
+		return buffer.toString();
+	}
+
+	private String drain(InputStream stream) throws IOException {
+		byte[] bytes = new byte[100];
+		StringBuffer buffer = new StringBuffer(500);
+		int length;
+		while ((length = stream.read(bytes)) != -1) {
+			String chunk = new String(bytes, 0, length);
+			buffer.append(chunk);
+		}
+		return buffer.toString();
+	}
+
+	private void log(String message) {
+		String value = this + ": " + message; //$NON-NLS-1$
+		System.out.println(value);
+	}
+	
+	public String request(String value) throws IOException {
+		String spec = createUrlSpec(value);
+		log("Requesting " + spec); //$NON-NLS-1$
+		URL url = new URL(spec);
+		InputStream stream = url.openStream();
+		try {
+			return drain(stream);
+		} finally {
+			stream.close();
+		}
+	}
+}