aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Schmidt2011-10-26 10:32:53 (EDT)
committerSebastian Schmidt2011-10-26 10:32:53 (EDT)
commitec8bbb9eddb27c213914fef58d4b2c163cdbe5c3 (patch)
tree047aac446170737d09c616d8f58818046c01a2c1
parent655d0515dce1c444a2bb1ff545da4399666b4e6e (diff)
downloadorg.eclipse.rtp-ec8bbb9eddb27c213914fef58d4b2c163cdbe5c3.zip
org.eclipse.rtp-ec8bbb9eddb27c213914fef58d4b2c163cdbe5c3.tar.gz
org.eclipse.rtp-ec8bbb9eddb27c213914fef58d4b2c163cdbe5c3.tar.bz2
NEW - Bug 355604 - Introduce a HTTP Deployer
This commit includes the HTTP Deployer as approved by CQ 5531.
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/.classpath7
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/.gitignore1
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/.project28
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/.settings/org.eclipse.jdt.core.prefs8
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/META-INF/MANIFEST.MF19
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/build.properties5
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/images/cloud.pngbin0 -> 757 bytes
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/plugin.xml43
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/CloudApplicationServerTab.java135
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/CloudApplicationTabGroup.java23
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/FeatureSelectionListener.java38
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/shortcut/CloudApplicationShortcut.java30
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/launch/ui/Activator.java69
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/.classpath7
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/.gitignore1
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/.project28
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/.settings/org.eclipse.jdt.core.prefs8
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/META-INF/MANIFEST.MF24
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/build.properties5
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/plugin.xml13
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/DeleteMethodRequestEntity.java20
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/HttpDeployerClient.java123
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/JdomRequestEntity.java47
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/CloudApplication.java52
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishConfig.java158
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishOperation.java115
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/Activator.java34
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfig.java64
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigValidator.java31
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/CloudApplicationLaunchUtils.java36
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/ZipUtils.java60
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.releng/.project17
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.releng/build.properties3
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.releng/category.xml7
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer.releng/feature.xml119
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/.classpath7
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/.gitignore1
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/.project33
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/.settings/org.eclipse.jdt.core.prefs8
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/.settings/org.eclipse.pde.core.prefs4
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/HTTP Deployer.launch24
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/META-INF/MANIFEST.MF30
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/OSGI-INF/httpdeployer-component.xml7
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/build.properties6
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleModificationResult.java47
-rwxr-xr-xbundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServlet.java147
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureInstallException.java23
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureManager.java137
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureModificationResult.java50
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureServlet.java111
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/AbstractHttpDeployerServlet.java87
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/CommonConstants.java22
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerComponent.java61
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerInitializer.java84
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerUtils.java52
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/IModificationResult.java17
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/RequestResults.java32
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/SystemServlet.java52
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/XmlConstants.java32
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/InvalidRepositoryException.java18
-rwxr-xr-xbundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryManager.java158
-rw-r--r--bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryModificationResult.java42
-rwxr-xr-xbundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryServlet.java109
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/.classpath7
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/.gitignore1
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/.project28
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/.settings/org.eclipse.jdt.core.prefs8
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/META-INF/MANIFEST.MF17
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/build.properties4
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/fixtures/zip/folder1/folder1.txt1
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/fixtures/zip/root.txt1
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/CloudApplicationTest.java80
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishConfigTest.java40
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigTest.java52
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigValidatorTest.java41
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/CloudApplicationLaunchUtilsTest.java39
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/ZipUtilsTest.java64
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/.classpath7
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/.gitignore1
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/.project28
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/.settings/org.eclipse.jdt.core.prefs8
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/.settings/org.eclipse.pde.core.prefs4
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/All httpdeployer Tests.launch43
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/META-INF/MANIFEST.MF14
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/build.properties5
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/build.xml343
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/fixtures/invalidRepositoryPackage.zipbin0 -> 316 bytes
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/fixtures/validRepositoryPackage.zipbin0 -> 3227 bytes
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServletOperationsTest.java208
-rwxr-xr-xtests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServletTest.java131
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureManagerTest.java112
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureServletTest.java114
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerComponentTest.java80
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryManagerTest.java121
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryServletTest.java207
-rw-r--r--tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/util/MockServletInputStream.java70
96 files changed, 4658 insertions, 0 deletions
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.classpath b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.classpath
@@ -0,0 +1,7 @@
+<?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/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.gitignore b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.gitignore
new file mode 100644
index 0000000..36f971e
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.gitignore
@@ -0,0 +1 @@
+bin/*
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.project b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.project
new file mode 100644
index 0000000..5f9e107
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.rtp.httpdeployer.launch.ui</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>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..37caf98
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Sat Jul 16 17:07:51 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..b07d09e
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Ui
+Bundle-SymbolicName: org.eclipse.rtp.httpdeployer.launch.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.eclipse.rtp.httpdeployer.launch.ui.Activator
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.debug.core,
+ org.eclipse.pde.core,
+ org.eclipse.rtp.httpdeployer.launch
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Import-Package: org.eclipse.debug.ui,
+ org.eclipse.pde.internal.core,
+ org.eclipse.pde.internal.ui,
+ org.eclipse.pde.internal.ui.dialogs,
+ org.eclipse.pde.ui.launcher,
+ org.eclipse.rtp.httpdeployer.launch
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/build.properties b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/build.properties
new file mode 100644
index 0000000..2b0d95b
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+ META-INF/,\
+ .
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/images/cloud.png b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/images/cloud.png
new file mode 100644
index 0000000..58bc9c9
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/images/cloud.png
Binary files differ
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/plugin.xml b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/plugin.xml
new file mode 100644
index 0000000..aec0594
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/plugin.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+<extension point="org.eclipse.debug.ui.launchConfigurationTypeImages">
+ <launchConfigurationTypeImage
+ icon="images/cloud.png"
+ configTypeID="org.eclipse.rtp.launch.CloudApplication"
+ id="org.eclipse.jdt.debug.ui.launchConfigurationTypeImage.cloudApplication">
+ </launchConfigurationTypeImage>
+</extension>
+<extension point="org.eclipse.debug.ui.launchConfigurationTabGroups">
+ <launchConfigurationTabGroup
+ type="org.eclipse.rtp.launch.CloudApplication"
+ class="org.eclipse.rtp.httpdeployer.internal.ui.launcher.CloudApplicationTabGroup"
+ id="org.eclipse.jdt.debug.ui.launchConfigurationTabGroup.javaApplet">
+ </launchConfigurationTabGroup>
+</extension>
+
+ <extension
+ point="org.eclipse.debug.ui.launchShortcuts">
+ <shortcut
+ class="org.eclipse.rtp.httpdeployer.internal.ui.shortcut.CloudApplicationShortcut"
+ description="Launches this feature at a remote OSGi runtime"
+ id="org.eclipse.rtp.launch.CloudApplicationShortcut"
+ label="Cloud Application"
+ modes="run">
+ <configurationType
+ id="org.eclipse.rtp.launch.CloudApplication">
+ </configurationType>
+ <description
+ description="Launches this feature at a remote OSGi runtime"
+ mode="run">
+ </description>
+ <contextualLaunch>
+ <enablement>
+ <with variable="selection">
+ <count value="1"></count>
+ </with>
+ </enablement>
+ </contextualLaunch>
+ </shortcut>
+ </extension>
+</plugin>
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/CloudApplicationServerTab.java b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/CloudApplicationServerTab.java
new file mode 100644
index 0000000..4798660
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/CloudApplicationServerTab.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal.ui.launcher;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
+import org.eclipse.pde.internal.ui.SWTFactory;
+import org.eclipse.rtp.httpdeployer.launch.CloudApplicationLaunchConfig;
+import org.eclipse.rtp.httpdeployer.launch.CloudApplicationLaunchConfigValidator;
+import org.eclipse.rtp.httpdeployer.launch.utils.CloudApplicationLaunchUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+@SuppressWarnings("restriction")
+public class CloudApplicationServerTab extends AbstractLaunchConfigurationTab {
+
+ private Text featureText;
+ private IFeatureModel feature;
+ private Composite comp;
+ private Text server;
+
+ @Override
+ public void createControl(final Composite parent) {
+ comp = new Composite(parent, SWT.NONE);
+ setControl(comp);
+ comp.setLayout(new GridLayout(1, true));
+ comp.setFont(parent.getFont());
+
+ createFeatureSelectBox();
+ createServerBox();
+ }
+
+ private void createServerBox() {
+ String text = "Server";
+ Group group = SWTFactory.createGroup(comp, text, 2, 1, GridData.FILL_HORIZONTAL);
+ server = SWTFactory.createSingleText(group, 1);
+ server.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ setDirty(true);
+ updateLaunchConfigurationDialog();
+ }
+ });
+ }
+
+ private void createFeatureSelectBox() {
+ String text = "Select Feature";
+ Group group = SWTFactory.createGroup(comp, text, 2, 1, GridData.FILL_HORIZONTAL);
+ featureText = SWTFactory.createSingleText(group, 1);
+ featureText.setEditable(false);
+
+ Button featureSearchButton = createPushButton(group, "Select Feature", null);
+ featureSearchButton.addSelectionListener(new FeatureSelectionListener(this));
+ }
+
+ @Override
+ public void setDefaults(ILaunchConfigurationWorkingCopy rootConfiguration) {
+ //CloudApplicationLaunchConfig config = new CloudApplicationLaunchConfig(rootConfiguration);
+ //config.setServerUri("http://localhost:8080/");
+ }
+
+ @Override
+ public void initializeFrom(ILaunchConfiguration rootConfiguration) {
+ CloudApplicationLaunchConfig config = new CloudApplicationLaunchConfig(rootConfiguration);
+ try {
+ if (!config.getFeatureId().equals("")) {
+ featureText.setText(config.getFeatureId() + " (" + config.getFeatureVersion() + ")");
+ feature = CloudApplicationLaunchUtils.getFeatureModel(config.getFeatureId(), config.getFeatureVersion());
+ }
+ server.setText(config.getServerUri());
+ } catch (CoreException e) {
+ DebugPlugin.log(e);
+ }
+ }
+
+ @Override
+ public void performApply(ILaunchConfigurationWorkingCopy workingCopy) {
+ CloudApplicationLaunchConfig config = new CloudApplicationLaunchConfig(workingCopy);
+
+ if (feature != null && feature.getFeature() != null) {
+ config.setFeatureId(feature.getFeature().getId());
+ config.setFeatureVersion(feature.getFeature().getVersion());
+ }
+
+ config.setServerUri(server.getText());
+ }
+
+ @Override
+ public boolean isValid(ILaunchConfiguration launchConfig) {
+ try {
+ return CloudApplicationLaunchConfigValidator.validate(launchConfig);
+ } catch (CoreException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "Server";
+ }
+
+ public Display getDisplay() {
+ return comp.getDisplay();
+ }
+
+ public Shell getShell() {
+ return comp.getShell();
+ }
+
+ public void setFeature(IFeatureModel iFeatureModel) {
+ setDirty(true);
+ feature = iFeatureModel;
+ featureText.setText(feature.getFeature().getId() + " (" + feature.getFeature().getVersion() + ")");
+ updateLaunchConfigurationDialog();
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/CloudApplicationTabGroup.java b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/CloudApplicationTabGroup.java
new file mode 100644
index 0000000..e194df1
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/CloudApplicationTabGroup.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal.ui.launcher;
+
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+
+public class CloudApplicationTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+ @Override
+ public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+ ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] { new CloudApplicationServerTab(), new CommonTab() };
+ setTabs(tabs);
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/FeatureSelectionListener.java b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/FeatureSelectionListener.java
new file mode 100644
index 0000000..d01dbaf
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/launcher/FeatureSelectionListener.java
@@ -0,0 +1,38 @@
+package org.eclipse.rtp.httpdeployer.internal.ui.launcher;
+
+import org.eclipse.jface.window.Window;
+import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
+import org.eclipse.pde.internal.ui.dialogs.FeatureSelectionDialog;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+
+@SuppressWarnings("restriction")
+public class FeatureSelectionListener implements SelectionListener {
+
+ private final CloudApplicationServerTab tab;
+
+ public FeatureSelectionListener(CloudApplicationServerTab tab) {
+ this.tab = tab;
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ BusyIndicator.showWhile(tab.getDisplay(), new Runnable() {
+
+ public void run() {
+ IFeatureModel[] models = PDECore.getDefault().getFeatureModelManager().getModels();
+ FeatureSelectionDialog dialog = new FeatureSelectionDialog(tab.getShell(), models, false);
+ if (dialog.open() == Window.OK) {
+ Object[] result = dialog.getResult();
+ if (result.length == 1) {
+ tab.setFeature((IFeatureModel) result[0]);
+ }
+ }
+ }
+ });
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/shortcut/CloudApplicationShortcut.java b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/shortcut/CloudApplicationShortcut.java
new file mode 100644
index 0000000..979a9b2
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/internal/ui/shortcut/CloudApplicationShortcut.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal.ui.shortcut;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.pde.ui.launcher.OSGiLaunchShortcut;
+import org.eclipse.ui.IEditorPart;
+
+public class CloudApplicationShortcut extends OSGiLaunchShortcut {
+
+ @Override
+ public void launch(ISelection selection, String mode) {
+ launch(mode);
+ }
+
+ @Override
+ public void launch(IEditorPart editor, String mode) {
+ launch(mode);
+ }
+
+ protected String getLaunchConfigurationTypeName() {
+ return "org.eclipse.rtp.launch.CloudApplication"; //$NON-NLS-N$
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/launch/ui/Activator.java b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/launch/ui/Activator.java
new file mode 100644
index 0000000..d598c62
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch.ui/src/org/eclipse/rtp/httpdeployer/launch/ui/Activator.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.launch.ui;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.rtp.httpdeployer.launch.ui"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns an image descriptor for the image file at the given
+ * plug-in relative path
+ *
+ * @param path the path
+ * @return the image descriptor
+ */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return imageDescriptorFromPlugin(PLUGIN_ID, path);
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/.classpath b/bundles/org.eclipse.rtp.httpdeployer.launch/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/.classpath
@@ -0,0 +1,7 @@
+<?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/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/.gitignore b/bundles/org.eclipse.rtp.httpdeployer.launch/.gitignore
new file mode 100644
index 0000000..36f971e
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/.gitignore
@@ -0,0 +1 @@
+bin/*
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/.project b/bundles/org.eclipse.rtp.httpdeployer.launch/.project
new file mode 100644
index 0000000..c094f5c
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.rtp.httpdeployer.launch</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>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.rtp.httpdeployer.launch/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..6bba0e5
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Sat Jul 16 17:33:17 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/META-INF/MANIFEST.MF b/bundles/org.eclipse.rtp.httpdeployer.launch/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..0d806ba
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/META-INF/MANIFEST.MF
@@ -0,0 +1,24 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Cloud Application Launcher
+Bundle-SymbolicName: org.eclipse.rtp.httpdeployer.launch;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.eclipse.rtp.httpdeployer.launch.Activator
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.pde.core
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Import-Package: org.apache.commons.httpclient;version="3.1.0",
+ org.apache.commons.httpclient.methods;version="3.1.0",
+ org.apache.commons.httpclient.methods.multipart;version="3.1.0",
+ org.eclipse.core.resources,
+ org.eclipse.debug.core,
+ org.eclipse.debug.core.model,
+ org.eclipse.equinox.p2.publisher,
+ org.eclipse.equinox.p2.publisher.eclipse,
+ org.eclipse.pde.internal.core.exports,
+ org.eclipse.pde.internal.core.feature,
+ org.jdom,
+ org.jdom.output;version="1.0.0"
+Export-Package: org.eclipse.rtp.httpdeployer.launch,
+ org.eclipse.rtp.httpdeployer.launch.utils
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/build.properties b/bundles/org.eclipse.rtp.httpdeployer.launch/build.properties
new file mode 100644
index 0000000..2b0d95b
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+ META-INF/,\
+ .
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/plugin.xml b/bundles/org.eclipse.rtp.httpdeployer.launch/plugin.xml
new file mode 100644
index 0000000..7288732
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/plugin.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+<extension point="org.eclipse.debug.core.launchConfigurationTypes">
+ <launchConfigurationType
+ name="Cloud Application"
+ delegate="org.eclipse.rtp.httpdeployer.internal.launch.CloudApplication"
+ modes="run"
+ id="org.eclipse.rtp.launch.CloudApplication">
+ </launchConfigurationType>
+</extension>
+
+</plugin>
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/DeleteMethodRequestEntity.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/DeleteMethodRequestEntity.java
new file mode 100644
index 0000000..15f2afb
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/DeleteMethodRequestEntity.java
@@ -0,0 +1,20 @@
+package org.eclipse.rtp.httpdeployer.client;
+
+import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
+
+public class DeleteMethodRequestEntity extends EntityEnclosingMethod {
+
+ public DeleteMethodRequestEntity(String uri) {
+ super(uri);
+ }
+
+ public DeleteMethodRequestEntity() {
+ super();
+ }
+
+ @Override
+ public String getName() {
+ return "DELETE";
+ }
+
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/HttpDeployerClient.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/HttpDeployerClient.java
new file mode 100644
index 0000000..7513bb9
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/HttpDeployerClient.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.client;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.output.XMLOutputter;
+
+// TODO: move to own package
+// TODO: remove Strings
+// TODO: Test
+public class HttpDeployerClient {
+ public static final String FEATURE_GROUP_SUFFIX = ".feature.group";
+ public static final String REPOSITORY_PATH = "/repository"; //$NON-NLS-N$
+ public static final String BUNDLE_PATH = "/bundle"; //$NON-NLS-N$
+ public static final String FEATURE_PATH = "/feature"; //$NON-NLS-N$
+
+ private final String serviceUri;
+ private final HttpClient client;
+
+ public HttpDeployerClient(String serviceUri) {
+ // strip last /
+ if (serviceUri.endsWith("/")) {
+ serviceUri = serviceUri.substring(0, serviceUri.length() - 1);
+ }
+ this.serviceUri = serviceUri;
+ client = new HttpClient();
+ }
+
+ public void installFeature(File repository, String id, String version) throws HttpException, IOException {
+ deleteFeature(id, version);
+
+ PostMethod method = new PostMethod(serviceUri + FEATURE_PATH);
+ XMLOutputter outputter = new XMLOutputter();
+ String featureInstall = outputter.outputString(getFeatureOperation(id, version));
+
+ Part[] parts = new Part[] { new FilePart("repository", repository), new StringPart("feature", featureInstall) };
+ MultipartRequestEntity entity = new MultipartRequestEntity(parts, method.getParams());
+ method.setRequestEntity(entity);
+
+ executeMethod(method);
+ }
+
+ private Document getFeatureOperation(String id, String version) {
+ Document document = new Document();
+ Element features = new Element("features");
+ Element featureXml = new Element("feature");
+ featureXml.addContent(new Element("name").addContent(id + FEATURE_GROUP_SUFFIX));
+ featureXml.addContent(new Element("version").addContent(version));
+ features.addContent(featureXml);
+ document.setRootElement(features);
+
+ return document;
+ }
+
+ public void uploadRepository(File repository) throws HttpException, IOException {
+ PostMethod method = new PostMethod(serviceUri + REPOSITORY_PATH);
+ Part[] parts = new Part[] { new FilePart("repository", repository) };
+ MultipartRequestEntity entity = new MultipartRequestEntity(parts, method.getParams());
+ method.setRequestEntity(entity);
+
+ executeMethod(method);
+ }
+
+ public void installFeature(String id, String version) throws IOException {
+ PostMethod post = new PostMethod(serviceUri + FEATURE_PATH);
+ DeleteMethodRequestEntity delete = new DeleteMethodRequestEntity(serviceUri + FEATURE_PATH);
+ Document document = getFeatureOperation(id, version);
+ delete.setRequestEntity(new JdomRequestEntity(document));
+ post.setRequestEntity(new JdomRequestEntity(document));
+
+ executeMethod(delete);
+ executeMethod(post);
+ }
+
+ public void deleteFeature(String id, String version) throws IOException {
+ DeleteMethodRequestEntity delete = new DeleteMethodRequestEntity(serviceUri + FEATURE_PATH);
+ Document document = getFeatureOperation(id, version);
+ delete.setRequestEntity(new JdomRequestEntity(document));
+
+ executeMethod(delete);
+ }
+
+ private void executeMethod(HttpMethod method) throws IOException {
+ int result = client.executeMethod(method);
+ if (result > 299) {
+ throw new HttpException("invalid response code: HTTP " + result);
+ }
+ }
+
+ public void startPlugin(String id, String version) throws IOException {
+ PostMethod post = new PostMethod(serviceUri + BUNDLE_PATH);
+ Document document = new Document();
+ Element features = new Element("bundles");
+ Element featureXml = new Element("bundle");
+ featureXml.addContent(new Element("name").addContent(id));
+ featureXml.addContent(new Element("version").addContent(version));
+ features.addContent(featureXml);
+ document.setRootElement(features);
+ post.setRequestEntity(new JdomRequestEntity(document));
+
+ executeMethod(post);
+ }
+
+ // TODO: extend, move to own project
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/JdomRequestEntity.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/JdomRequestEntity.java
new file mode 100644
index 0000000..1d6dfcd
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/client/JdomRequestEntity.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.client;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.jdom.Document;
+import org.jdom.output.XMLOutputter;
+
+public class JdomRequestEntity implements RequestEntity {
+
+ private String result;
+
+ public JdomRequestEntity(Document document) {
+ XMLOutputter outputter = new XMLOutputter();
+ result = outputter.outputString(document);
+ }
+
+ @Override
+ public boolean isRepeatable() {
+ return false;
+ }
+
+ @Override
+ public void writeRequest(OutputStream out) throws IOException {
+ out.write(result.getBytes());
+ }
+
+ @Override
+ public long getContentLength() {
+ return result.length();
+ }
+
+ @Override
+ public String getContentType() {
+ return "text/xml";
+ }
+
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/CloudApplication.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/CloudApplication.java
new file mode 100644
index 0000000..4709527
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/CloudApplication.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal.launch;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.model.ILaunchConfigurationDelegate;
+import org.eclipse.rtp.httpdeployer.launch.CloudApplicationLaunchConfig;
+import org.eclipse.rtp.httpdeployer.launch.utils.CloudApplicationLaunchUtils;
+
+public class CloudApplication implements ILaunchConfigurationDelegate {
+
+ private static final String HTTP_DEPLOYER_JOB_NAME = "Http Deployer Job";
+
+ @Override
+ public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
+ throws CoreException {
+ HttpPublishConfig deployerConfiguration = createDeployerConfiguration(configuration);
+ HttpPublishOperation operation = createOperation(monitor, deployerConfiguration);
+ IStatus status = operation.run(monitor);
+ if (!status.isOK()) {
+ throw new CoreException(status);
+ }
+ }
+
+ protected HttpPublishConfig createDeployerConfiguration(ILaunchConfiguration configuration) throws CoreException {
+ CloudApplicationLaunchConfig launchConfiguration = new CloudApplicationLaunchConfig(configuration);
+ String featureId = launchConfiguration.getFeatureId();
+ String featureVersion = launchConfiguration.getFeatureVersion();
+ String serverUri = launchConfiguration.getServerUri();
+ HttpPublishConfig deployerConfiguration = HttpPublishConfig.createDefaultConfiguration(serverUri);
+ deployerConfiguration.setItems(new Object[] { CloudApplicationLaunchUtils.getFeatureModel(featureId, featureVersion) });
+ return deployerConfiguration;
+ }
+
+ protected HttpPublishOperation createOperation(IProgressMonitor monitor, HttpPublishConfig config) {
+ HttpPublishOperation job = new HttpPublishOperation(config, HTTP_DEPLOYER_JOB_NAME);
+ job.setUser(true);
+ job.setRule(ResourcesPlugin.getWorkspace().getRoot());
+ return job;
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishConfig.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishConfig.java
new file mode 100644
index 0000000..361a503
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishConfig.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal.launch;
+
+import org.eclipse.pde.internal.core.exports.FeatureExportInfo;
+import org.eclipse.rtp.httpdeployer.launch.utils.CloudApplicationLaunchUtils;
+
+@SuppressWarnings("restriction")
+public class HttpPublishConfig extends FeatureExportInfo {
+
+ public String httpDeployerServiceUrl;
+
+ public boolean isToDirectory() {
+ return toDirectory;
+ }
+
+ public void setToDirectory(boolean toDirectory) {
+ this.toDirectory = toDirectory;
+ }
+
+ public boolean isUseJarFormat() {
+ return useJarFormat;
+ }
+
+ public void setUseJarFormat(boolean useJarFormat) {
+ this.useJarFormat = useJarFormat;
+ }
+
+ public boolean isExportSource() {
+ return exportSource;
+ }
+
+ public void setExportSource(boolean exportSource) {
+ this.exportSource = exportSource;
+ }
+
+ public boolean isExportSourceBundle() {
+ return exportSourceBundle;
+ }
+
+ public void setExportSourceBundle(boolean exportSourceBundle) {
+ this.exportSourceBundle = exportSourceBundle;
+ }
+
+ public boolean isExportMetadata() {
+ return exportMetadata;
+ }
+
+ public void setExportMetadata(boolean exportMetadata) {
+ this.exportMetadata = exportMetadata;
+ }
+
+ public boolean isAllowBinaryCycles() {
+ return allowBinaryCycles;
+ }
+
+ public void setAllowBinaryCycles(boolean allowBinaryCycles) {
+ this.allowBinaryCycles = allowBinaryCycles;
+ }
+
+ public boolean isUseWorkspaceCompiledClasses() {
+ return useWorkspaceCompiledClasses;
+ }
+
+ public void setUseWorkspaceCompiledClasses(boolean useWorkspaceCompiledClasses) {
+ this.useWorkspaceCompiledClasses = useWorkspaceCompiledClasses;
+ }
+
+ public String getDestinationDirectory() {
+ return destinationDirectory;
+ }
+
+ public void setDestinationDirectory(String destinationDirectory) {
+ this.destinationDirectory = destinationDirectory;
+ }
+
+ public String getQualifier() {
+ return qualifier;
+ }
+
+ public void setQualifier(String qualifier) {
+ this.qualifier = qualifier;
+ }
+
+ public Object[] getItems() {
+ return items;
+ }
+
+ public void setItems(Object[] items) {
+ this.items = items;
+ }
+
+ public String[] getSigningInfo() {
+ return signingInfo;
+ }
+
+ public void setSigningInfo(String[] signingInfo) {
+ this.signingInfo = signingInfo;
+ }
+
+ public String[] getJnlpInfo() {
+ return jnlpInfo;
+ }
+
+ public void setJnlpInfo(String[] jnlpInfo) {
+ this.jnlpInfo = jnlpInfo;
+ }
+
+ public String[][] getTargets() {
+ return targets;
+ }
+
+ public void setTargets(String[][] targets) {
+ this.targets = targets;
+ }
+
+ public String getCategoryDefinition() {
+ return categoryDefinition;
+ }
+
+ public void setCategoryDefinition(String categoryDefinition) {
+ this.categoryDefinition = categoryDefinition;
+ }
+
+ public String getHttpDeployerServiceUrl() {
+ return httpDeployerServiceUrl;
+ }
+
+ public void setHttpDeployerServiceUrl(String httpDeployerServiceUrl) {
+ this.httpDeployerServiceUrl = httpDeployerServiceUrl;
+ }
+
+ public static HttpPublishConfig createDefaultConfiguration(String serverUri) {
+ HttpPublishConfig config = new HttpPublishConfig();
+ config.setAllowBinaryCycles(true);
+ config.setJnlpInfo(null);
+ config.setQualifier(String.valueOf(Math.round(System.currentTimeMillis() + Math.random() * 10000000)));
+ config.setToDirectory(true);
+ config.setSigningInfo(null);
+ config.setTargets(null);
+ config.setUseJarFormat(true);
+ config.setUseWorkspaceCompiledClasses(false);
+ config.setExportMetadata(true);
+ config.setExportSource(true);
+ config.setExportSourceBundle(true);
+ config.setCategoryDefinition(null);
+ config.setDestinationDirectory(CloudApplicationLaunchUtils.getTempDir());
+ config.setHttpDeployerServiceUrl(serverUri);
+ return config;
+ }
+
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishOperation.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishOperation.java
new file mode 100644
index 0000000..5930f7e
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishOperation.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal.launch;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.httpclient.HttpException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.PDECoreMessages;
+import org.eclipse.pde.internal.core.exports.FeatureExportOperation;
+import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
+import org.eclipse.pde.internal.core.ifeature.IFeaturePlugin;
+import org.eclipse.pde.internal.core.util.CoreUtility;
+import org.eclipse.rtp.httpdeployer.client.HttpDeployerClient;
+import org.eclipse.rtp.httpdeployer.launch.utils.ZipUtils;
+
+@SuppressWarnings("restriction")
+public class HttpPublishOperation extends FeatureExportOperation {
+
+ protected final HttpPublishConfig info;
+ private File repositoryZip = null;
+
+ public HttpPublishOperation(HttpPublishConfig info, String name) {
+ super(info, name);
+ this.info = info;
+ }
+
+ @Override
+ public IStatus run(IProgressMonitor monitor) {
+ monitor.beginTask("", 80);
+ IStatus status = super.run(new SubProgressMonitor(monitor, 20));
+
+ if (status.isOK()) {
+ try {
+ installFeature(monitor, new SubProgressMonitor(monitor, 20));
+ startBundles(monitor, new SubProgressMonitor(monitor, 20));
+ } catch (HttpException e) {
+ status = new Status(IStatus.ERROR, PDECore.PLUGIN_ID,
+ PDECoreMessages.FeatureBasedExportOperation_ProblemDuringExport, e);
+ } catch (IOException e) {
+ status = new Status(IStatus.ERROR, PDECore.PLUGIN_ID,
+ PDECoreMessages.FeatureBasedExportOperation_ProblemDuringExport, e);
+ } finally {
+ deleteBuildFiles();
+ monitor.done();
+ }
+ }
+
+ return status;
+ }
+
+ private void startBundles(IProgressMonitor monitor, SubProgressMonitor subProgressMonitor) throws IOException {
+ HttpDeployerClient service = createHttpDeployerClient();
+ for (Object item : info.getItems()) {
+ if (item instanceof IFeatureModel) {
+ IFeatureModel feature = (IFeatureModel) item;
+ IFeaturePlugin[] plugins = feature.getFeature().getPlugins();
+ for (IFeaturePlugin plugin : plugins) {
+ String version = plugin.getVersion().replaceAll("qualifier", info.getQualifier());
+ service.startPlugin(plugin.getId(), version);
+ }
+ }
+ }
+ }
+
+ private void installFeature(IProgressMonitor monitor, SubProgressMonitor subProgressMonitor) throws IOException {
+ monitor.beginTask("", 20);
+ monitor.setTaskName("Upload repository to " + info.getHttpDeployerServiceUrl());
+ repositoryZip = zipRepositoryToFile();
+ HttpDeployerClient service = createHttpDeployerClient();
+ monitor.worked(10);
+ for (Object item : info.getItems()) {
+ if (item instanceof IFeatureModel) {
+ IFeatureModel feature = (IFeatureModel) item;
+ String version = feature.getFeature().getVersion();
+ String id = feature.getFeature().getId();
+ version = version.replaceAll("qualifier", info.getQualifier());
+ service.installFeature(repositoryZip, id, version);
+ }
+ }
+ monitor.worked(10);
+ monitor.done();
+ }
+
+ private void deleteBuildFiles() {
+ CoreUtility.deleteContent(new File(info.getDestinationDirectory()));
+ if (repositoryZip != null) {
+ repositoryZip.delete();
+ }
+ }
+
+ private HttpDeployerClient createHttpDeployerClient() {
+ String targetUrl = info.getHttpDeployerServiceUrl();
+ HttpDeployerClient service = new HttpDeployerClient(targetUrl);
+ return service;
+ }
+
+ private File zipRepositoryToFile() throws IOException {
+ String destinationDirectory = info.getDestinationDirectory();
+ File repository = File.createTempFile("repository", ".zip"); //$NON-NLS-N$
+ ZipUtils.zip(new File(destinationDirectory), repository);
+ return repository;
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/Activator.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/Activator.java
new file mode 100644
index 0000000..41bda0a
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/Activator.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.launch;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+ public static BundleContext context;
+
+ /*
+ * (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext bundleContext) throws Exception {
+ Activator.context = bundleContext;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext bundleContext) throws Exception {
+ Activator.context = null;
+ }
+
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfig.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfig.java
new file mode 100644
index 0000000..981c881
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfig.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.launch;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+
+public class CloudApplicationLaunchConfig {
+
+ public static final String ATTR_PREFIX = "org.eclipse.rtp.httpdeployer.launch.";
+ public static final String ATTR_FEATURE_ID = ATTR_PREFIX + "featureId";
+ public static final String ATTR_FEATURE_VERSION = ATTR_PREFIX + "featureVersion";
+ public static final String ATTR_SERVER_URI = ATTR_PREFIX + "serverUri";
+
+ private final ILaunchConfiguration config;
+ private final ILaunchConfigurationWorkingCopy workingCopy;
+
+ public CloudApplicationLaunchConfig(final ILaunchConfiguration config) {
+ this.config = config;
+ if (config instanceof ILaunchConfigurationWorkingCopy) {
+ workingCopy = (ILaunchConfigurationWorkingCopy) config;
+ } else {
+ workingCopy = null;
+ }
+ }
+
+ public String getFeatureId() throws CoreException {
+ return config.getAttribute(ATTR_FEATURE_ID, "");
+ }
+
+ public String getFeatureVersion() throws CoreException {
+ return config.getAttribute(ATTR_FEATURE_VERSION, "");
+ }
+
+ public void setFeatureId(String featureId) {
+ setAttribute(ATTR_FEATURE_ID, featureId);
+ }
+
+ public void setFeatureVersion(String featureVersion) {
+ setAttribute(ATTR_FEATURE_VERSION, featureVersion);
+ }
+
+ protected void setAttribute(String attribute, String value) {
+ if (workingCopy != null) {
+ workingCopy.setAttribute(attribute, value);
+ }
+ }
+
+ public String getServerUri() throws CoreException {
+ return config.getAttribute(ATTR_SERVER_URI, "");
+ }
+
+ public void setServerUri(String server) {
+ setAttribute(ATTR_SERVER_URI, server);
+ }
+
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigValidator.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigValidator.java
new file mode 100644
index 0000000..2a335a8
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigValidator.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.launch;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+
+public final class CloudApplicationLaunchConfigValidator {
+
+ private CloudApplicationLaunchConfigValidator() {
+ // prevent instantiation
+ }
+
+ public static boolean validate(ILaunchConfiguration config) throws CoreException {
+ return validate(new CloudApplicationLaunchConfig(config));
+ }
+
+ public static boolean validate(CloudApplicationLaunchConfig config) throws CoreException {
+ if (!config.getFeatureId().equals("") && !config.getServerUri().equals("")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/CloudApplicationLaunchUtils.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/CloudApplicationLaunchUtils.java
new file mode 100644
index 0000000..2ea1798
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/CloudApplicationLaunchUtils.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.rtp.httpdeployer.launch.utils;
+
+import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
+
+@SuppressWarnings("restriction")
+public final class CloudApplicationLaunchUtils {
+
+ private CloudApplicationLaunchUtils() {
+ // prevent instantiation
+ }
+
+ public static IFeatureModel getFeatureModel(String featureId, String featureVersion) {
+ IFeatureModel[] models = PDECore.getDefault().getFeatureModelManager().getModels();
+ for (IFeatureModel model : models) {
+ if (model.getFeature().getId().equals(featureId) && model.getFeature().getVersion().equals(featureVersion)) {
+ return model;
+ }
+ }
+
+ return null;
+ }
+
+ public static String getTempDir() {
+ return System.getProperty("java.io.tmpdir") + "/build_" + Long.toString(System.nanoTime());
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/ZipUtils.java b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/ZipUtils.java
new file mode 100644
index 0000000..5167c7d
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/ZipUtils.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.launch.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+public final class ZipUtils {
+
+ private ZipUtils() {
+ }
+
+ public static void zip(File file, File output) throws IOException {
+ FileOutputStream outputStream = new FileOutputStream(output);
+ ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
+
+ String rootDirectory;
+ if (file.isDirectory()) {
+ rootDirectory = file.getPath();
+ } else {
+ rootDirectory = file.getParentFile().getPath();
+ }
+
+ zip(file, rootDirectory, zipOutputStream);
+ zipOutputStream.close();
+ }
+
+ private static void zip(File currentFile, String directory, ZipOutputStream zipOutputStream) throws IOException {
+ if (currentFile.isDirectory()) {
+ for (File file : currentFile.listFiles()) {
+ zip(file, directory, zipOutputStream);
+ }
+ } else {
+ ZipEntry entry = new ZipEntry(currentFile.getPath().substring(directory.length() + 1));
+ zipOutputStream.putNextEntry(entry);
+ copyFileToStream(currentFile, zipOutputStream);
+ }
+ }
+
+ private static void copyFileToStream(File currentFile, OutputStream outputStream) throws IOException {
+ int read = 0;
+ byte[] buffer = new byte[8192];
+ FileInputStream in = new FileInputStream(currentFile);
+ while (-1 != (read = in.read(buffer))) {
+ outputStream.write(buffer, 0, read);
+ }
+ in.close();
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.rtp.httpdeployer.releng/.project b/bundles/org.eclipse.rtp.httpdeployer.releng/.project
new file mode 100644
index 0000000..7c72030
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.releng/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.rtp.httpdeployer.releng</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.FeatureBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.FeatureNature</nature>
+ </natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.rtp.httpdeployer.releng/build.properties b/bundles/org.eclipse.rtp.httpdeployer.releng/build.properties
new file mode 100644
index 0000000..524c2d6
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.releng/build.properties
@@ -0,0 +1,3 @@
+bin.includes = feature.xml
+runPackager = true
+p2.gathering = true \ No newline at end of file
diff --git a/bundles/org.eclipse.rtp.httpdeployer.releng/category.xml b/bundles/org.eclipse.rtp.httpdeployer.releng/category.xml
new file mode 100644
index 0000000..3e9b190
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.releng/category.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<site>
+ <feature url="features/org.eclipse.rtp.httpdeployer.releng_0.1.0.jar" id="org.eclipse.rtp.httpdeployer.releng" version="0.1">
+ <category name="org.eclipse.rtp.httpdeployer"/>
+ </feature>
+ <category-def name="org.eclipse.rtp.httpdeployer" label="Http Deployer"/>
+</site>
diff --git a/bundles/org.eclipse.rtp.httpdeployer.releng/feature.xml b/bundles/org.eclipse.rtp.httpdeployer.releng/feature.xml
new file mode 100644
index 0000000..69df4e2
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer.releng/feature.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+ id="org.eclipse.rtp.httpdeployer"
+ label="Http Deployer"
+ version="0.2.3">
+
+ <description url="http://www.example.com/description">
+ [Enter Feature Description here.]
+ </description>
+
+ <copyright url="http://www.example.com/copyright">
+ [Enter Copyright Description here.]
+ </copyright>
+
+ <license url="http://www.example.com/license">
+ [Enter License Description here.]
+ </license>
+
+ <requires>
+ <import plugin="org.jdom"/>
+ <import plugin="org.eclipse.osgi.services"/>
+ <import plugin="org.eclipse.osgi" version="3.7.0" match="compatible"/>
+ <import plugin="org.eclipse.core.jobs" version="3.2.0" match="compatible"/>
+ <import plugin="org.eclipse.equinox.preferences" version="3.4.0" match="compatible"/>
+ <import plugin="org.eclipse.core.contenttype" version="3.3.0" match="compatible"/>
+ <import plugin="org.eclipse.equinox.app" version="1.0.0" match="greaterOrEqual"/>
+ <import plugin="org.sat4j.core" version="2.2.0"/>
+ <import plugin="org.sat4j.pb" version="2.2.0"/>
+ <import plugin="org.eclipse.equinox.p2.metadata" version="2.0.0" match="compatible"/>
+ <import plugin="org.eclipse.equinox.p2.metadata.repository"/>
+ <import plugin="org.eclipse.equinox.p2.core" version="2.0.0" match="compatible"/>
+ <import plugin="org.eclipse.equinox.common" version="3.6.0" match="greaterOrEqual"/>
+ </requires>
+
+ <plugin
+ id="org.eclipse.rtp.httpdeployer"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="javax.servlet"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.mortbay.jetty.server"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.mortbay.jetty.util"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.apache.commons.fileupload"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.apache.commons.io"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.core.jobs"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.core.runtime"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.core.contenttype"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.equinox.http.jetty"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.equinox.http.servlet"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.jdom"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+</feature>
diff --git a/bundles/org.eclipse.rtp.httpdeployer/.classpath b/bundles/org.eclipse.rtp.httpdeployer/.classpath
new file mode 100644
index 0000000..16d067f
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.rtp.httpdeployer/.gitignore b/bundles/org.eclipse.rtp.httpdeployer/.gitignore
new file mode 100644
index 0000000..36f971e
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/.gitignore
@@ -0,0 +1 @@
+bin/*
diff --git a/bundles/org.eclipse.rtp.httpdeployer/.project b/bundles/org.eclipse.rtp.httpdeployer/.project
new file mode 100644
index 0000000..4021627
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.rtp.httpdeployer</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.rtp.httpdeployer/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.rtp.httpdeployer/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3214c06
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Mon May 09 17:01:10 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/bundles/org.eclipse.rtp.httpdeployer/.settings/org.eclipse.pde.core.prefs b/bundles/org.eclipse.rtp.httpdeployer/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000..c98777a
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,4 @@
+#Mon May 09 17:01:12 CEST 2011
+eclipse.preferences.version=1
+pluginProject.extensions=false
+resolve.requirebundle=false
diff --git a/bundles/org.eclipse.rtp.httpdeployer/HTTP Deployer.launch b/bundles/org.eclipse.rtp.httpdeployer/HTTP Deployer.launch
new file mode 100644
index 0000000..87eb163
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/HTTP Deployer.launch
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.pde.ui.EquinoxLauncher">
+<booleanAttribute key="append.args" value="true"/>
+<booleanAttribute key="automaticAdd" value="false"/>
+<booleanAttribute key="automaticValidate" value="true"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="false"/>
+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/HTTP Deployer"/>
+<booleanAttribute key="default" value="true"/>
+<booleanAttribute key="default_auto_start" value="true"/>
+<intAttribute key="default_start_level" value="4"/>
+<booleanAttribute key="includeOptional" value="false"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dorg.osgi.service.http.port=9090"/>
+<stringAttribute key="pde.version" value="3.3"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<stringAttribute key="target_bundles" value="javax.servlet@default:default,org.apache.commons.codec@default:default,org.apache.commons.fileupload@default:default,org.apache.commons.httpclient@default:default,org.apache.commons.io@default:default,org.apache.commons.logging@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.net@default:default,org.eclipse.core.runtime@default:true,org.eclipse.ecf.filetransfer@default:default,org.eclipse.ecf.identity@default:default,org.eclipse.ecf.provider.filetransfer.httpclient.ssl@default:false,org.eclipse.ecf.provider.filetransfer.httpclient@default:default,org.eclipse.ecf.provider.filetransfer@default:default,org.eclipse.ecf@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.concurrent@default:default,org.eclipse.equinox.ds@1:true,org.eclipse.equinox.frameworkadmin.equinox@default:default,org.eclipse.equinox.frameworkadmin@default:default,org.eclipse.equinox.http.jetty@default:default,org.eclipse.equinox.http.registry@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.equinox.launcher.gtk.linux.x86@default:false,org.eclipse.equinox.launcher@default:default,org.eclipse.equinox.p2.artifact.repository@default:default,org.eclipse.equinox.p2.console@default:default,org.eclipse.equinox.p2.core@default:default,org.eclipse.equinox.p2.director@default:default,org.eclipse.equinox.p2.engine@default:default,org.eclipse.equinox.p2.garbagecollector@default:default,org.eclipse.equinox.p2.jarprocessor@default:default,org.eclipse.equinox.p2.metadata.repository@default:default,org.eclipse.equinox.p2.metadata@default:default,org.eclipse.equinox.p2.operations@default:default,org.eclipse.equinox.p2.publisher.eclipse@default:default,org.eclipse.equinox.p2.publisher@default:default,org.eclipse.equinox.p2.ql@default:default,org.eclipse.equinox.p2.repository@default:default,org.eclipse.equinox.p2.touchpoint.eclipse@default:default,org.eclipse.equinox.p2.touchpoint.natives@default:default,org.eclipse.equinox.p2.transport.ecf@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.security@default:default,org.eclipse.equinox.simpleconfigurator.manipulator@default:default,org.eclipse.equinox.simpleconfigurator@1:true,org.eclipse.equinox.util@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi@-1:true,org.jdom@default:default,org.mortbay.jetty.server@default:default,org.mortbay.jetty.util@default:default,org.sat4j.core@default:default,org.sat4j.pb@default:default"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useCustomFeatures" value="false"/>
+<booleanAttribute key="useDefaultConfigArea" value="true"/>
+<stringAttribute key="workspace_bundles" value="org.eclipse.rtp.httpdeployer*0.1.0@default:default"/>
+</launchConfiguration>
diff --git a/bundles/org.eclipse.rtp.httpdeployer/META-INF/MANIFEST.MF b/bundles/org.eclipse.rtp.httpdeployer/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..ff9ab73
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/META-INF/MANIFEST.MF
@@ -0,0 +1,30 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: HttpDeployer
+Bundle-SymbolicName: org.eclipse.rtp.httpdeployer
+Bundle-Version: 0.2.2
+Bundle-ActivationPolicy: lazy
+Import-Package: javax.servlet;version="[2.5.0,3.0.0)",
+ javax.servlet.http;version="[2.5.0,3.0.0)",
+ org.apache.commons.fileupload;version="[1.0.0,2.0.0)",
+ org.apache.commons.fileupload.disk;version="[1.0.0,2.0.0)",
+ org.apache.commons.fileupload.servlet;version="[1.0.0,2.0.0)",
+ org.apache.commons.io;version="[2.0.0,3.0.0)",
+ org.eclipse.core.runtime,
+ org.eclipse.core.runtime.jobs,
+ org.eclipse.equinox.internal.provisional.configurator,
+ org.eclipse.equinox.p2.core;version="[2.0.0,3.0.0)",
+ org.eclipse.equinox.p2.engine;version="[2.0.0,3.0.0)",
+ org.eclipse.equinox.p2.metadata;version="[2.0.0,3.0.0)",
+ org.eclipse.equinox.p2.operations,
+ org.eclipse.equinox.p2.query;version="[2.0.0,3.0.0)",
+ org.eclipse.equinox.p2.repository;version="2.0.0",
+ org.eclipse.equinox.p2.repository.artifact;version="[2.0.0,3.0.0)",
+ org.eclipse.equinox.p2.repository.metadata;version="[2.0.0,3.0.0)",
+ org.jdom,
+ org.jdom.input,
+ org.jdom.output,
+ org.osgi.framework;version="1.6.0",
+ org.osgi.service.http;version="1.2.1"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Service-Component: OSGI-INF/httpdeployer-component.xml
diff --git a/bundles/org.eclipse.rtp.httpdeployer/OSGI-INF/httpdeployer-component.xml b/bundles/org.eclipse.rtp.httpdeployer/OSGI-INF/httpdeployer-component.xml
new file mode 100644
index 0000000..43efd6e
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/OSGI-INF/httpdeployer-component.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="startService" deactivate="shutdownService" name="org.eclipse.rtp.httpdeployer.component">
+ <implementation class="org.eclipse.rtp.httpdeployer.internal.HttpDeployerComponent" />
+ <reference name="httpService" bind="setHttpService" unbind="unsetHttpService" interface="org.osgi.service.http.HttpService" />
+ <reference name="provisioningAgent" bind="setProvisioningAgent" unbind="unsetProvisioningAgent" interface="org.eclipse.equinox.p2.core.IProvisioningAgent" />
+ <reference bind="setConfigurator" cardinality="1..1" interface="org.eclipse.equinox.internal.provisional.configurator.Configurator" name="Configurator" policy="static" unbind="unsetConfigurator"/>
+</scr:component>
diff --git a/bundles/org.eclipse.rtp.httpdeployer/build.properties b/bundles/org.eclipse.rtp.httpdeployer/build.properties
new file mode 100644
index 0000000..35e7e80
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ ,\
+ OSGI-INF/
+
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleModificationResult.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleModificationResult.java
new file mode 100644
index 0000000..15c21d2
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleModificationResult.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.bundle;
+
+import org.eclipse.rtp.httpdeployer.internal.CommonConstants.Action;
+import org.eclipse.rtp.httpdeployer.internal.IModificationResult;
+import org.eclipse.rtp.httpdeployer.internal.XmlConstants;
+import org.jdom.Element;
+
+public class BundleModificationResult implements IModificationResult {
+
+ private final String name;
+ private final Action action;
+ private final String reason;
+
+ public BundleModificationResult(String name, Action action) {
+ this(name, action, null);
+ }
+
+ public BundleModificationResult(String name, Action action, String reason) {
+ this.name = name;
+ this.action = action;
+ this.reason = reason;
+ }
+
+ @Override
+ public Element getDocument() {
+ Element xmlResult = new Element(XmlConstants.XML_ELEMENT_BUNDLE);
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_NAME).addContent(name));
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_ACTION).addContent(action.toString()));
+ if (reason == null) {
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_STATUS)
+ .addContent(XmlConstants.XML_VALUE_STATUS_SUCCESSFUL));
+ } else {
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_STATUS).addContent(XmlConstants.XML_VALUE_STATUS_FAILED));
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_REASON).addContent(reason));
+ }
+
+ return xmlResult;
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServlet.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServlet.java
new file mode 100755
index 0000000..ded2791
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServlet.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.bundle;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.rtp.httpdeployer.internal.AbstractHttpDeployerServlet;
+import org.eclipse.rtp.httpdeployer.internal.CommonConstants.Action;
+import org.eclipse.rtp.httpdeployer.internal.HttpDeployerUtils;
+import org.eclipse.rtp.httpdeployer.internal.RequestResults;
+import org.eclipse.rtp.httpdeployer.internal.XmlConstants;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkUtil;
+
+public class BundleServlet extends AbstractHttpDeployerServlet {
+
+ private static final long serialVersionUID = 3749930485862030632L;
+ protected static final String REQUEST_PATH_RESOLVED_BUNDLES = "/resolved"; //$NON-NLS-N$
+ protected static final String REQUEST_PATH_ACTIVE_BUNDLES = "/active"; //$NON-NLS-N$
+ protected static final int ALL_BUNDLES = 0;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ String requestPath = request.getPathInfo();
+ Document document;
+
+ if (requestPath == null) {
+ document = generateBundleList(ALL_BUNDLES);
+ } else if (requestPath.startsWith(REQUEST_PATH_ACTIVE_BUNDLES)) {
+ document = generateBundleList(Bundle.ACTIVE);
+ } else if (requestPath.startsWith(REQUEST_PATH_RESOLVED_BUNDLES)) {
+ document = generateBundleList(Bundle.RESOLVED);
+ } else {
+ document = generateBundleList(ALL_BUNDLES);
+ }
+
+ HttpDeployerUtils.outputDocument(response, document);
+ }
+
+ @Override
+ public Document parseDeleteRequest(Document request) {
+ return parseRequest(request, XmlConstants.XML_ELEMENT_BUNDLE, Action.UNINSTALL);
+ }
+
+ @Override
+ public Document parsePostRequest(Document request) {
+ return parseRequest(request, XmlConstants.XML_ELEMENT_BUNDLE, Action.START);
+ }
+
+ @Override
+ public Document parseMultipartPostRequest(HttpServletRequest request) throws Exception {
+ throw new IllegalAccessException();
+ }
+
+ @Override
+ public void handleOperation(RequestResults result, Element currentElement, Action action) {
+ String name = currentElement.getChildText(XmlConstants.XML_ELEMENT_NAME);
+ String actionName = currentElement.getChildText(XmlConstants.XML_ELEMENT_ACTION);
+ if (actionName != null && actionName.equalsIgnoreCase("stop")) {
+ action = Action.STOP;
+ }
+ Bundle bundle = searchBundle(name);
+ handleOperation(result, name, bundle, action);
+ }
+
+ private Document generateBundleList(int requestType) {
+ Bundle[] bundles = receiveBundles(requestType);
+ Element root = new Element(XmlConstants.XML_ELEMENT_BUNDLES);
+ for (Bundle bundle : bundles) {
+ Element bundleXml = new Element(XmlConstants.XML_ELEMENT_BUNDLE);
+ bundleXml.addContent(new Element(XmlConstants.XML_ELEMENT_NAME).addContent(bundle.getSymbolicName()));
+ bundleXml.addContent(new Element(XmlConstants.XML_ELEMENT_VERSION).addContent(bundle.getVersion().toString()));
+ root.addContent(bundleXml);
+ }
+ return new Document(root);
+ }
+
+ private void handleOperation(RequestResults result, String name, Bundle bundle, Action action) {
+ if (bundle == null) {
+ result.addResult(new BundleModificationResult(name, action, "bundle not found"));
+ } else {
+ try {
+ switch (action) {
+ case START:
+ bundle.start();
+ break;
+ case STOP:
+ bundle.stop();
+ break;
+ case UNINSTALL:
+ bundle.uninstall();
+ break;
+ }
+ result.addResult(new BundleModificationResult(name, action));
+ } catch (BundleException e) {
+ result.addResult(new BundleModificationResult(name, action, e.getMessage()));
+ }
+ }
+ }
+
+ protected Bundle[] receiveBundles() {
+ Bundle currentBundle = FrameworkUtil.getBundle(HttpDeployerUtils.class);
+ BundleContext context = currentBundle.getBundleContext();
+ Bundle[] bundles = context.getBundles();
+ return bundles;
+ }
+
+ private Bundle[] receiveBundles(int requestType) {
+ Bundle[] bundles = receiveBundles();
+
+ List<Bundle> validBundles = new ArrayList<Bundle>();
+ for (Bundle bundle : bundles) {
+ if (bundle.getState() == requestType || requestType == 0) {
+ validBundles.add(bundle);
+ }
+ }
+
+ return validBundles.toArray(new Bundle[0]);
+ }
+
+ private Bundle searchBundle(String searchedBundle) {
+ Bundle[] bundles = receiveBundles();
+ for (Bundle bundle : bundles) {
+ if (bundle.getSymbolicName().equalsIgnoreCase(searchedBundle)) {
+ return bundle;
+ }
+ }
+
+ return null;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureInstallException.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureInstallException.java
new file mode 100644
index 0000000..f10713a
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureInstallException.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.feature;
+
+public class FeatureInstallException extends Exception {
+
+ private static final long serialVersionUID = 7654279780139556052L;
+
+ public FeatureInstallException(Exception e) {
+ // TODO: Not tested
+ super(e);
+ }
+
+ public FeatureInstallException(String message) {
+ super(message);
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureManager.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureManager.java
new file mode 100644
index 0000000..94fa38d
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureManager.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.feature;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.provisional.configurator.Configurator;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.engine.ProvisioningContext;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.metadata.Version;
+import org.eclipse.equinox.p2.operations.InstallOperation;
+import org.eclipse.equinox.p2.operations.ProfileChangeOperation;
+import org.eclipse.equinox.p2.operations.ProvisioningJob;
+import org.eclipse.equinox.p2.operations.ProvisioningSession;
+import org.eclipse.equinox.p2.operations.UninstallOperation;
+import org.eclipse.equinox.p2.query.QueryUtil;
+import org.eclipse.rtp.httpdeployer.repository.RepositoryManager;
+
+@SuppressWarnings("restriction")
+public class FeatureManager {
+
+ public enum Action {
+ UNINSTALL, INSTALL
+ }
+
+ private final IProvisioningAgent provisioningAgent;
+ private final RepositoryManager repositoryManager;
+ private final Configurator configurator;
+
+ public FeatureManager(IProvisioningAgent provisioningAgent, RepositoryManager repositoryManager, Configurator configurator) {
+ this.provisioningAgent = provisioningAgent;
+ this.repositoryManager = repositoryManager;
+ this.configurator = configurator;
+ }
+
+ // TODO: Not tested
+ public void installFeature(String featureId, String version) throws FeatureInstallException {
+ ProfileChangeOperation operation = resolveProfileChangeOperation(featureId, version, Action.INSTALL);
+ executeProfileChangeOperation(operation);
+ applyChanges();
+ }
+
+ // TODO: Not tested
+ public void uninstallFeature(String featureId, String version) throws FeatureInstallException {
+ ProfileChangeOperation operation = resolveProfileChangeOperation(featureId, version, Action.UNINSTALL);
+ executeProfileChangeOperation(operation);
+ applyChanges();
+ }
+
+ // TODO: Not tested
+ private ProfileChangeOperation resolveProfileChangeOperation(String featureId, String version, Action action)
+ throws FeatureInstallException {
+ ProvisioningSession session = new ProvisioningSession(provisioningAgent);
+ ProvisioningContext context = createProvisioningContext();
+
+ Collection<IInstallableUnit> units = getInstallableUnits(context, featureId, version);
+ ProfileChangeOperation operation = getOperation(session, units, action);
+ operation.setProvisioningContext(context);
+ resolveOperation(operation);
+
+ return operation;
+ }
+
+ private ProfileChangeOperation getOperation(ProvisioningSession session, Collection<IInstallableUnit> units, Action action)
+ throws FeatureInstallException {
+ ProfileChangeOperation operation;
+ if (action.equals(Action.UNINSTALL)) {
+ operation = new UninstallOperation(session, units);
+ } else {
+ operation = new InstallOperation(session, units);
+ }
+
+ return operation;
+ }
+
+ private void resolveOperation(ProfileChangeOperation operation) throws FeatureInstallException {
+ IStatus result = operation.resolveModal(null);
+
+ if (!result.isOK()) {
+ String errorMessage = generateErrorMessage(result);
+ throw new FeatureInstallException(errorMessage);
+ }
+ }
+
+ private void applyChanges() throws FeatureInstallException {
+ try {
+ configurator.applyConfiguration();
+ } catch (IOException e) {
+ throw new FeatureInstallException(e);
+ }
+ }
+
+ protected ProvisioningContext createProvisioningContext() {
+ ProvisioningContext context = new ProvisioningContext(provisioningAgent);
+ context.setArtifactRepositories(repositoryManager.getRepositories());
+ context.setArtifactRepositories(repositoryManager.getRepositories());
+ return context;
+ }
+
+ protected void executeProfileChangeOperation(ProfileChangeOperation operation) throws FeatureInstallException {
+ ProvisioningJob provisioningJob = operation.getProvisioningJob(new NullProgressMonitor());
+ if (provisioningJob == null) {
+ return;
+ }
+
+ IStatus result = provisioningJob.runModal(new NullProgressMonitor());
+
+ if (!result.isOK()) {
+ throw new FeatureInstallException(result.getMessage());
+ }
+ }
+
+ private String generateErrorMessage(IStatus result) {
+ IStatus[] children = result.getChildren();
+ String message = "";
+ for (int i = 0; i < children.length; i++) {
+ message = children[i].getMessage() + "\n";
+ }
+ return message;
+ }
+
+ protected Collection<IInstallableUnit> getInstallableUnits(ProvisioningContext context, String id, String version) {
+ Collection<IInstallableUnit> toInstall = context.getMetadata(null)
+ .query(QueryUtil.createIUQuery(id, Version.create(version)), null).toUnmodifiableSet();
+ return toInstall;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureModificationResult.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureModificationResult.java
new file mode 100644
index 0000000..6925878
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureModificationResult.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.feature;
+
+import org.eclipse.rtp.httpdeployer.internal.CommonConstants.Action;
+import org.eclipse.rtp.httpdeployer.internal.IModificationResult;
+import org.eclipse.rtp.httpdeployer.internal.XmlConstants;
+import org.jdom.Element;
+
+public class FeatureModificationResult implements IModificationResult {
+
+ private final String name;
+ private final String version;
+ private final Action action;
+ private final FeatureInstallException e;
+
+ public FeatureModificationResult(String name, String version, Action action, FeatureInstallException e) {
+ this.name = name;
+ this.version = version;
+ this.action = action;
+ this.e = e;
+ }
+
+ public FeatureModificationResult(String name, String version, Action action) {
+ this(name, version, action, null);
+ }
+
+ public Element getDocument() {
+ Element xmlResult = new Element(XmlConstants.XML_ELEMENT_FEATURE);
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_NAME).addContent(name));
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_VERSION).addContent(version));
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_ACTION).addContent(action.toString()));
+ if (e == null) {
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_STATUS)
+ .addContent(XmlConstants.XML_VALUE_STATUS_SUCCESSFUL));
+ } else {
+ // TODO: Not tested
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_STATUS).addContent(XmlConstants.XML_VALUE_STATUS_FAILED));
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_REASON).addContent(e.getMessage()));
+ }
+
+ return xmlResult;
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureServlet.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureServlet.java
new file mode 100644
index 0000000..5169dbc
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureServlet.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.feature;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUploadException;
+import org.eclipse.rtp.httpdeployer.internal.AbstractHttpDeployerServlet;
+import org.eclipse.rtp.httpdeployer.internal.CommonConstants.Action;
+import org.eclipse.rtp.httpdeployer.internal.HttpDeployerUtils;
+import org.eclipse.rtp.httpdeployer.internal.RequestResults;
+import org.eclipse.rtp.httpdeployer.internal.XmlConstants;
+import org.eclipse.rtp.httpdeployer.repository.RepositoryManager;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+
+public class FeatureServlet extends AbstractHttpDeployerServlet {
+
+ private static final long serialVersionUID = 8439160853108236583L;
+ private final FeatureManager featureManager;
+ private final RepositoryManager repositoryManager;
+
+ public FeatureServlet(FeatureManager featureManager, RepositoryManager repositoryManager) {
+ this.featureManager = featureManager;
+ this.repositoryManager = repositoryManager;
+ }
+
+ @Override
+ public Document parsePostRequest(Document requestDocument) {
+ return parseRequest(requestDocument, XmlConstants.XML_ELEMENT_FEATURE, Action.INSTALL);
+ }
+
+ @Override
+ public Document parseDeleteRequest(Document requestDocument) {
+ return parseRequest(requestDocument, XmlConstants.XML_ELEMENT_FEATURE, Action.UNINSTALL);
+ }
+
+ @Override
+ public Document parseMultipartPostRequest(HttpServletRequest request) throws Exception {
+ List<FileItem> files = HttpDeployerUtils.parseMultipartRequest(request);
+ if (files.size() != 2) {
+ throw new FileUploadException("Files not found");
+ }
+
+ InputStream repository = getRepositoryFromMultipart(files);
+ repositoryManager.addRepository(repository);
+ Document feature = getFeatureRequestFromMultipart(files);
+ Document installRequest = parseRequest(feature, XmlConstants.XML_ELEMENT_FEATURE, Action.INSTALL);
+
+ return installRequest;
+ }
+
+ private Document getFeatureRequestFromMultipart(List<FileItem> files) throws JDOMException, IOException {
+ String feature;
+ if (files.get(0).isFormField()) {
+ feature = files.get(0).getString();
+ } else {
+ feature = files.get(1).getString();
+ }
+ SAXBuilder builder = new SAXBuilder();
+ return builder.build(new StringReader(feature));
+ }
+
+ private InputStream getRepositoryFromMultipart(List<FileItem> files) throws IOException {
+ if (files.get(0).isFormField()) {
+ return files.get(1).getInputStream();
+ } else {
+ return files.get(0).getInputStream();
+ }
+ }
+
+ @Override
+ public void handleOperation(RequestResults result, Element currentElement, Action action) {
+ String name = currentElement.getChildText(XmlConstants.XML_ELEMENT_NAME);
+ String version = currentElement.getChildText(XmlConstants.XML_ELEMENT_VERSION);
+ if (action == Action.UNINSTALL) {
+ version = null;
+ }
+
+ handleOperation(result, name, version, action);
+ }
+
+ private void handleOperation(RequestResults result, String name, String version, Action action) {
+ try {
+ if (action.equals(Action.INSTALL)) {
+ featureManager.installFeature(name, version);
+ result.addResult(new FeatureModificationResult(name, version, action));
+ } else if (action.equals(Action.UNINSTALL)) {
+ featureManager.uninstallFeature(name, version);
+ result.addResult(new FeatureModificationResult(name, version, action));
+ }
+ } catch (FeatureInstallException e) {
+ // TODO: Not tested
+ result.addResult(new FeatureModificationResult(name, version, action, e));
+ }
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/AbstractHttpDeployerServlet.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/AbstractHttpDeployerServlet.java
new file mode 100644
index 0000000..ef1bd98
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/AbstractHttpDeployerServlet.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.eclipse.rtp.httpdeployer.internal.CommonConstants.Action;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+
+public abstract class AbstractHttpDeployerServlet extends HttpServlet {
+
+ private static final long serialVersionUID = -1882775409591126187L;
+
+ @Override
+ public void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ try {
+ Document requestDocument = HttpDeployerUtils.parseXmlRequest(request);
+ Document responseDocument = parseDeleteRequest(requestDocument);
+ HttpDeployerUtils.outputDocument(response, responseDocument);
+ } catch (JDOMException e) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ }
+ }
+
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ Document responseDocument = null;
+
+ // create repository by URI
+ if (!ServletFileUpload.isMultipartContent(request)) {
+ try {
+ responseDocument = parsePostRequest(HttpDeployerUtils.parseXmlRequest(request));
+ } catch (JDOMException e) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ } else { // create repository by file upload
+ try {
+ responseDocument = parseMultipartPostRequest(request);
+ } catch (Exception e) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ }
+
+ HttpDeployerUtils.outputDocument(response, responseDocument);
+ }
+
+ protected Document parseRequest(Document request, String searchedElement, Action action) {
+ Element rootElement = request.getRootElement();
+ RequestResults result = new RequestResults();
+
+ for (Object child : rootElement.getChildren()) {
+ if (child instanceof Element) {
+ Element currentElement = (Element) child;
+ if (currentElement.getName().equals(searchedElement)) {
+ handleOperation(result, currentElement, action);
+ }
+ }
+ }
+
+ return result.getDocument();
+ }
+
+ public abstract void handleOperation(RequestResults result, Element currentElement, Action action);
+
+ public abstract Document parseDeleteRequest(Document requestDocument);
+
+ public abstract Document parsePostRequest(Document requestDocument);
+
+ public abstract Document parseMultipartPostRequest(HttpServletRequest request) throws Exception;
+
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/CommonConstants.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/CommonConstants.java
new file mode 100644
index 0000000..94e1b95
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/CommonConstants.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal;
+
+public final class CommonConstants {
+ public static final String RESPONSE_CONTENT_TYPE = "text/xml"; //$NON-NLS-N$
+ public static final String DIR_SEPARATOR = "/"; //$NON-NLS-N$
+
+ public enum Action {
+ START, STOP, INSTALL, UNINSTALL, ADD, REMOVE
+ }
+
+ private CommonConstants() {
+ // prevent instantiation
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerComponent.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerComponent.java
new file mode 100644
index 0000000..e28ab04
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerComponent.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal;
+
+import javax.servlet.ServletException;
+
+import org.eclipse.equinox.internal.provisional.configurator.Configurator;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.NamespaceException;
+
+@SuppressWarnings("restriction")
+public class HttpDeployerComponent {
+
+ private HttpDeployerInitializer initializer = new HttpDeployerInitializer();
+
+ protected HttpService httpService;
+ protected IProvisioningAgent provisioningAgent;
+ protected Configurator configurator;
+
+ public void setHttpService(HttpService httpService) {
+ this.httpService = httpService;
+ }
+
+ public void unsetHttpService(HttpService httpService) {
+ this.httpService = null;
+ }
+
+ public void setConfigurator(Configurator configurator) {
+ this.configurator = configurator;
+ }
+
+ public void unsetConfigurator(Configurator configurator) {
+ this.configurator = null;
+ }
+
+ public void setProvisioningAgent(IProvisioningAgent provisioningAgent) {
+ this.provisioningAgent = provisioningAgent;
+ }
+
+ public void unsetProvisioningAgent(IProvisioningAgent provisioningAgent) {
+ this.provisioningAgent = null;
+ }
+
+ protected void startService() throws ServletException, NamespaceException {
+ initializer.setProvisioningAgent(provisioningAgent);
+ initializer.setConfigurator(configurator);
+ initializer.setHttpService(httpService);
+ initializer.init();
+ }
+
+ protected void shutdownService() {
+ initializer.unregister();
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerInitializer.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerInitializer.java
new file mode 100644
index 0000000..08293b6
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerInitializer.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal;
+
+import javax.servlet.ServletException;
+
+import org.eclipse.equinox.internal.provisional.configurator.Configurator;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.rtp.httpdeployer.bundle.BundleServlet;
+import org.eclipse.rtp.httpdeployer.feature.FeatureManager;
+import org.eclipse.rtp.httpdeployer.feature.FeatureServlet;
+import org.eclipse.rtp.httpdeployer.repository.RepositoryManager;
+import org.eclipse.rtp.httpdeployer.repository.RepositoryServlet;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.NamespaceException;
+
+@SuppressWarnings("restriction")
+public class HttpDeployerInitializer {
+
+ public static final String ALIAS_BUNDLE = "/bundle"; //$NON-NLS-N$
+ public static final String ALIAS_REPOSITORY = "/repository"; //$NON-NLS-N$
+ public static final String ALIAS_FEATURE = "/feature"; //$NON-NLS-N$
+ public static final String ALIAS_SYSTEM = "/system"; //$NON-NLS-N$
+
+ private HttpService httpService;
+ private Configurator configurator;
+ private IProvisioningAgent provisioningAgent;
+ private BundleServlet bundleServlet;
+ private RepositoryServlet repositoryServlet;
+ private FeatureServlet featureServlet;
+ private SystemServlet systemServlet;
+ private RepositoryManager repositoryManager;
+ private FeatureManager featureManager;
+
+ public void init() throws ServletException, NamespaceException {
+ createManager();
+ createServlets();
+ registerServlets();
+ }
+
+ private void createManager() {
+ repositoryManager = new RepositoryManager(provisioningAgent);
+ featureManager = new FeatureManager(provisioningAgent, repositoryManager, configurator);
+ }
+
+ private void createServlets() {
+ bundleServlet = new BundleServlet();
+ repositoryServlet = new RepositoryServlet(repositoryManager);
+ featureServlet = new FeatureServlet(featureManager, repositoryManager);
+ systemServlet = new SystemServlet();
+ }
+
+ private void registerServlets() throws ServletException, NamespaceException {
+ httpService.registerServlet(ALIAS_BUNDLE, bundleServlet, null, null);
+ httpService.registerServlet(ALIAS_REPOSITORY, repositoryServlet, null, null);
+ httpService.registerServlet(ALIAS_FEATURE, featureServlet, null, null);
+ httpService.registerServlet(ALIAS_SYSTEM, systemServlet, null, null);
+ }
+
+ public void setHttpService(HttpService httpService) {
+ this.httpService = httpService;
+ }
+
+ public void setConfigurator(Configurator configurator) {
+ this.configurator = configurator;
+ }
+
+ public void setProvisioningAgent(IProvisioningAgent provisioningAgent) {
+ this.provisioningAgent = provisioningAgent;
+ }
+
+ public void unregister() {
+ httpService.unregister(ALIAS_BUNDLE);
+ httpService.unregister(ALIAS_REPOSITORY);
+ httpService.unregister(ALIAS_FEATURE);
+ httpService.unregister(ALIAS_SYSTEM);
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerUtils.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerUtils.java
new file mode 100644
index 0000000..cdd2d5f
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerUtils.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.jdom.Document;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.XMLOutputter;
+
+public class HttpDeployerUtils {
+
+ private HttpDeployerUtils() {
+ // prevent instantiation
+ }
+
+
+ public static Document parseXmlRequest(HttpServletRequest request) throws JDOMException, IOException {
+ SAXBuilder builder = new SAXBuilder();
+ Document xmlDocument = builder.build(request.getReader());
+ return xmlDocument;
+ }
+
+ public static void outputDocument(HttpServletResponse response, Document document) throws IOException {
+ response.setContentType(CommonConstants.RESPONSE_CONTENT_TYPE);
+ XMLOutputter out = new XMLOutputter();
+ out.output(document, response.getWriter());
+ }
+
+ @SuppressWarnings("unchecked")
+ public static List<FileItem> parseMultipartRequest(HttpServletRequest request) throws FileUploadException {
+ FileItemFactory factory = new DiskFileItemFactory();
+ ServletFileUpload upload = new ServletFileUpload(factory);
+ return upload.parseRequest(request);
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/IModificationResult.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/IModificationResult.java
new file mode 100644
index 0000000..406ea34
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/IModificationResult.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal;
+
+import org.jdom.Element;
+
+public interface IModificationResult {
+
+ public Element getDocument();
+
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/RequestResults.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/RequestResults.java
new file mode 100644
index 0000000..19ef6c4
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/RequestResults.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jdom.Document;
+import org.jdom.Element;
+
+public class RequestResults {
+ private final List<IModificationResult> results = new ArrayList<IModificationResult>();
+
+ public void addResult(IModificationResult result) {
+ results.add(result);
+ }
+
+ public Document getDocument() {
+ Element root = new Element(XmlConstants.XML_ELEMENT_BUNDLES);
+ for (IModificationResult result : results) {
+ root.addContent(result.getDocument());
+ }
+
+ return new Document(root);
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/SystemServlet.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/SystemServlet.java
new file mode 100644
index 0000000..40398c9
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/SystemServlet.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.Version;
+
+public class SystemServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 3404658151450270259L;
+ private static final String REQUEST_PATH_VERSION = "/-version"; //$NON-NLS-N$
+
+ // TODO: Not tested
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ if (req.getPathInfo() != null && req.getPathInfo().startsWith(REQUEST_PATH_VERSION)) {
+ printVersion(resp);
+ }
+ }
+
+ private void printVersion(HttpServletResponse resp) throws IOException {
+ Element root = new Element(XmlConstants.XML_ELEMENT_SYSTEM);
+ Element bundleXml = new Element(XmlConstants.XML_ELEMENT_FEATURE);
+ bundleXml.addContent(new Element(XmlConstants.XML_ELEMENT_NAME).addContent(getHttpDeployerName()));
+ bundleXml.addContent(new Element(XmlConstants.XML_ELEMENT_VERSION).addContent(getHttpDeployerVersion().toString()));
+ root.addContent(bundleXml);
+ HttpDeployerUtils.outputDocument(resp, new Document(root));
+ }
+
+ protected Version getHttpDeployerVersion() {
+ return FrameworkUtil.getBundle(getClass()).getVersion();
+ }
+
+ protected String getHttpDeployerName() {
+ return FrameworkUtil.getBundle(getClass()).getSymbolicName();
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/XmlConstants.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/XmlConstants.java
new file mode 100644
index 0000000..bfcb260
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/XmlConstants.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal;
+
+public final class XmlConstants {
+ public static final String XML_ELEMENT_BUNDLES = "bundles"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_BUNDLE = "bundle"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_NAME = "name"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_VERSION = "version"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_REPOSITORY = "repository"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_URI = "uri"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_REPOSITORIES = "repositories"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_STATUS = "status"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_REASON = "reason"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_FEATURE = "feature"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_FEATURES = "features"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_ACTION = "action"; //$NON-NLS-N$
+ public static final String XML_VALUE_STATUS_FAILED = "failed"; //$NON-NLS-N$
+ public static final String XML_VALUE_STATUS_SUCCESSFUL = "successful"; //$NON-NLS-N$
+ public static final String XML_ELEMENT_SYSTEM = "system"; //$NON-NLS-N$
+
+ private XmlConstants() {
+ // prevent instantiation
+ }
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/InvalidRepositoryException.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/InvalidRepositoryException.java
new file mode 100644
index 0000000..8070859
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/InvalidRepositoryException.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.repository;
+
+public class InvalidRepositoryException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public InvalidRepositoryException(String string) {
+ super(string);
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryManager.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryManager.java
new file mode 100755
index 0000000..39ba064
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryManager.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.repository;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.commons.io.FileUtils;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
+import org.eclipse.rtp.httpdeployer.internal.CommonConstants;
+
+public class RepositoryManager {
+
+ private static final String LOCAL_REPOSITORY_PREFIX = "repo_"; //$NON-NLS-N$
+ private static final String FILENAME_CONTENT = "content.jar"; //$NON-NLS-N$
+ private static final String FILENAME_ARTIFACTS = "artifacts.jar"; //$NON-NLS-N$
+ private static final int FILE_BUFFER = 8192;
+ private final IProvisioningAgent provisioningAgent;
+
+ public RepositoryManager(IProvisioningAgent provisioningAgent) {
+ this.provisioningAgent = provisioningAgent;
+ }
+
+ public URI[] getRepositories() {
+ IMetadataRepositoryManager metaRepoManager = getMetadataRepositoryManager();
+
+ return metaRepoManager.getKnownRepositories(IMetadataRepositoryManager.REPOSITORIES_ALL);
+ }
+
+ public void addRepository(URI repository) {
+ IMetadataRepositoryManager metaRepoManager = getMetadataRepositoryManager();
+ IArtifactRepositoryManager artiRepoManager = getArtifactRepositoryManager();
+
+ metaRepoManager.addRepository(repository);
+ artiRepoManager.addRepository(repository);
+ }
+
+ public URI addRepository(InputStream inputStream) throws InvalidRepositoryException, FileNotFoundException, IOException {
+ ZipInputStream zis = new ZipInputStream(inputStream);
+ File repository = createLocalRepository(zis);
+ URI repositoryURI = repository.toURI();
+ addRepository(repositoryURI);
+
+ return repositoryURI;
+ }
+
+ private File createLocalRepository(ZipInputStream zis) throws InvalidRepositoryException, IOException, FileNotFoundException {
+ File repository = new File(System.getProperty("java.io.tmpdir") + CommonConstants.DIR_SEPARATOR + LOCAL_REPOSITORY_PREFIX
+ + Long.toString(System.nanoTime()));
+ repository.mkdirs();
+ createLocalRepositoryStructure(zis, repository);
+
+ try {
+ validateLocalRepository(repository);
+ } catch (InvalidRepositoryException e) {
+ FileUtils.deleteDirectory(repository);
+ throw e;
+ }
+
+ return repository;
+ }
+
+ public void removeRepository(URI repository) {
+ IMetadataRepositoryManager metaRepoManager = getMetadataRepositoryManager();
+ IArtifactRepositoryManager artiRepoManager = getArtifactRepositoryManager();
+
+ metaRepoManager.removeRepository(repository);
+ artiRepoManager.removeRepository(repository);
+ }
+
+ private void createLocalRepositoryStructure(ZipInputStream zis, File repository) throws IOException, FileNotFoundException {
+ ZipEntry currentFile;
+ while ((currentFile = zis.getNextEntry()) != null) {
+ if (currentFile.isDirectory()) {
+ createLocalDirectory(repository, currentFile);
+ } else {
+ createLocalFile(zis, repository, currentFile);
+ }
+ }
+ }
+
+ private void createLocalDirectory(File repository, ZipEntry currentFile) {
+ File file = new File(repository.getAbsolutePath() + CommonConstants.DIR_SEPARATOR + currentFile.getName());
+ file.mkdirs();
+ }
+
+ private void createLocalFile(ZipInputStream zis, File repository, ZipEntry currentFile) throws IOException,
+ FileNotFoundException {
+ File file = new File(repository.getAbsolutePath() + CommonConstants.DIR_SEPARATOR + currentFile.getName());
+ file.getParentFile().mkdirs();
+ file.createNewFile();
+ FileOutputStream fos = new FileOutputStream(file);
+ BufferedOutputStream bfos = new BufferedOutputStream(fos, FILE_BUFFER);
+ saveFileData(zis, bfos);
+ }
+
+ private void saveFileData(ZipInputStream zis, BufferedOutputStream bfos) throws IOException {
+ int resultLength;
+ byte[] data = new byte[FILE_BUFFER];
+ while ((resultLength = zis.read(data, 0, FILE_BUFFER)) != -1) {
+ bfos.write(data, 0, resultLength);
+ }
+ bfos.flush();
+ bfos.close();
+ }
+
+ public void validateLocalRepository(File repository) throws InvalidRepositoryException {
+ File[] files = repository.listFiles();
+ boolean artifactsFound = false;
+ boolean contentFound = false;
+
+ for (File file : files) {
+ if (file.getName().equals(FILENAME_ARTIFACTS)) {
+ artifactsFound = true;
+ } else if (file.getName().equals(FILENAME_CONTENT)) {
+ contentFound = true;
+ }
+ }
+
+ if (!artifactsFound || !contentFound) {
+ throw new InvalidRepositoryException("invalid repository: required files not found");
+ }
+ }
+
+ public IMetadataRepositoryManager getMetadataRepositoryManager() {
+ IMetadataRepositoryManager service = (IMetadataRepositoryManager) provisioningAgent
+ .getService(IMetadataRepositoryManager.SERVICE_NAME);
+
+ return service;
+ }
+
+ public IArtifactRepositoryManager getArtifactRepositoryManager() {
+ IArtifactRepositoryManager service = (IArtifactRepositoryManager) provisioningAgent
+ .getService(IArtifactRepositoryManager.SERVICE_NAME);
+
+ return service;
+ }
+
+ public void removeLocalRepository(URI repository) throws IOException {
+ FileUtils.deleteDirectory(new File(repository));
+ removeRepository(repository);
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryModificationResult.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryModificationResult.java
new file mode 100644
index 0000000..f383c63
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryModificationResult.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.repository;
+
+import org.eclipse.rtp.httpdeployer.internal.CommonConstants.Action;
+import org.eclipse.rtp.httpdeployer.internal.IModificationResult;
+import org.eclipse.rtp.httpdeployer.internal.XmlConstants;
+import org.jdom.Element;
+
+public class RepositoryModificationResult implements IModificationResult {
+
+ private final Action action;
+ private final String repository;
+ private final String reason;
+
+ public RepositoryModificationResult(String repository, String reason, Action action) {
+ this.repository = repository;
+ this.reason = reason;
+ this.action = action;
+ }
+
+ public Element getDocument() {
+ Element xmlResult = new Element(XmlConstants.XML_ELEMENT_REPOSITORY);
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_URI).addContent(repository));
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_ACTION).addContent(action.toString()));
+ if (reason == null) {
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_STATUS)
+ .addContent(XmlConstants.XML_VALUE_STATUS_SUCCESSFUL));
+ } else {
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_STATUS).addContent(XmlConstants.XML_VALUE_STATUS_FAILED));
+ xmlResult.addContent(new Element(XmlConstants.XML_ELEMENT_REASON).addContent(reason));
+ }
+
+ return xmlResult;
+ }
+}
diff --git a/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryServlet.java b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryServlet.java
new file mode 100755
index 0000000..7fceeeb
--- /dev/null
+++ b/bundles/org.eclipse.rtp.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryServlet.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.repository;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUploadException;
+import org.eclipse.rtp.httpdeployer.internal.AbstractHttpDeployerServlet;
+import org.eclipse.rtp.httpdeployer.internal.CommonConstants.Action;
+import org.eclipse.rtp.httpdeployer.internal.HttpDeployerUtils;
+import org.eclipse.rtp.httpdeployer.internal.RequestResults;
+import org.eclipse.rtp.httpdeployer.internal.XmlConstants;
+import org.jdom.Document;
+import org.jdom.Element;
+
+public class RepositoryServlet extends AbstractHttpDeployerServlet {
+
+ private static final long serialVersionUID = -4190823339335383710L;
+ private final RepositoryManager repositoryManager;
+
+ public RepositoryServlet(RepositoryManager repositoryManager) {
+ this.repositoryManager = repositoryManager;
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ URI[] repositories = repositoryManager.getRepositories();
+ Element root = new Element(XmlConstants.XML_ELEMENT_REPOSITORIES);
+
+ for (URI repository : repositories) {
+ Element bundleXml = new Element(XmlConstants.XML_ELEMENT_REPOSITORY);
+ bundleXml.addContent(new Element(XmlConstants.XML_ELEMENT_URI).addContent(repository.toString()));
+ root.addContent(bundleXml);
+ }
+
+ HttpDeployerUtils.outputDocument(resp, new Document(root));
+ }
+
+ @Override
+ public Document parseMultipartPostRequest(HttpServletRequest req) throws FileUploadException, IOException {
+ RequestResults result = new RequestResults();
+ List<FileItem> files = HttpDeployerUtils.parseMultipartRequest(req);
+
+ if (files.size() != 1) {
+ throw new FileUploadException("File not found");
+ }
+
+ try {
+ InputStream repository = files.get(0).getInputStream();
+ result.addResult(new RepositoryModificationResult(repositoryManager.addRepository(repository).toString(), null,
+ Action.ADD));
+ } catch (InvalidRepositoryException e) {
+ result.addResult(new RepositoryModificationResult("local", e.getMessage(), Action.ADD));
+ }
+
+ // delete temporary files
+ for (FileItem item : files) {
+ item.delete();
+ }
+
+ return result.getDocument();
+ }
+
+ @Override
+ public Document parseDeleteRequest(Document request) {
+ return parseRequest(request, XmlConstants.XML_ELEMENT_REPOSITORY, Action.REMOVE);
+ }
+
+ @Override
+ public Document parsePostRequest(Document request) {
+ return parseRequest(request, XmlConstants.XML_ELEMENT_REPOSITORY, Action.ADD);
+ }
+
+ @Override
+ public void handleOperation(RequestResults result, Element currentElement, Action action) {
+ String repositoryPath = currentElement.getChildText(XmlConstants.XML_ELEMENT_URI);
+ try {
+ URI repository = new URI(repositoryPath);
+ performRepositoryAction(repository, action);
+ result.addResult(new RepositoryModificationResult(repositoryPath, null, action));
+ } catch (URISyntaxException e) {
+ // TODO: Not tested
+ result.addResult(new RepositoryModificationResult(repositoryPath, e.getMessage(), action));
+ }
+ }
+
+ private void performRepositoryAction(URI repository, Action action) {
+ if (action.equals(Action.ADD)) {
+ repositoryManager.addRepository(repository);
+ } else {
+ repositoryManager.removeRepository(repository);
+ }
+ }
+
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/.classpath b/tests/org.eclipse.rtp.tests.httpdeployer.launch/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/.classpath
@@ -0,0 +1,7 @@
+<?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/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/.gitignore b/tests/org.eclipse.rtp.tests.httpdeployer.launch/.gitignore
new file mode 100644
index 0000000..36f971e
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/.gitignore
@@ -0,0 +1 @@
+bin/*
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/.project b/tests/org.eclipse.rtp.tests.httpdeployer.launch/.project
new file mode 100644
index 0000000..725a2e2
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.rtp.tests.httpdeployer.launch</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>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/.settings/org.eclipse.jdt.core.prefs b/tests/org.eclipse.rtp.tests.httpdeployer.launch/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..6fc0420
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Sat Jul 23 01:04:18 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/META-INF/MANIFEST.MF b/tests/org.eclipse.rtp.tests.httpdeployer.launch/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..cb7f68d
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/META-INF/MANIFEST.MF
@@ -0,0 +1,17 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Launch Configuration Tests
+Bundle-SymbolicName: org.eclipse.rtp.tests.httpdeployer.launch
+Bundle-Version: 1.0.0
+Require-Bundle: org.eclipse.core.runtime
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Fragment-Host: org.eclipse.rtp.httpdeployer.launch
+Import-Package: org.eclipse.equinox.internal.p2.director,
+ org.eclipse.equinox.p2.planner;version="2.0.0",
+ org.hamcrest,
+ org.junit,
+ org.mockito,
+ org.mockito.invocation;version="1.8.4",
+ org.mockito.stubbing,
+ org.objenesis
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/build.properties b/tests/org.eclipse.rtp.tests.httpdeployer.launch/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/fixtures/zip/folder1/folder1.txt b/tests/org.eclipse.rtp.tests.httpdeployer.launch/fixtures/zip/folder1/folder1.txt
new file mode 100644
index 0000000..018c5bd
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/fixtures/zip/folder1/folder1.txt
@@ -0,0 +1 @@
+file in folder 1 \ No newline at end of file
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/fixtures/zip/root.txt b/tests/org.eclipse.rtp.tests.httpdeployer.launch/fixtures/zip/root.txt
new file mode 100644
index 0000000..89210c2
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/fixtures/zip/root.txt
@@ -0,0 +1 @@
+file in root folder \ No newline at end of file
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/CloudApplicationTest.java b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/CloudApplicationTest.java
new file mode 100644
index 0000000..1a545c3
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/CloudApplicationTest.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal.launch;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.rtp.httpdeployer.launch.CloudApplicationLaunchConfig;
+import org.junit.Test;
+
+public class CloudApplicationTest {
+
+ private static final String SERVER_URI = "localhost";
+
+ @Test
+ public void launchTest() throws CoreException {
+ CloudApplication app = spy(new CloudApplication());
+ ILaunchConfiguration conf = mock(ILaunchConfiguration.class);
+ HttpPublishOperation operation = mock(HttpPublishOperation.class);
+ doReturn(operation).when(app).createOperation(any(IProgressMonitor.class), any(HttpPublishConfig.class));
+
+ IProgressMonitor monitor = mock(IProgressMonitor.class);
+ when(operation.run(monitor)).thenReturn(new Status(Status.OK, "cloudapplication", "ok"));
+ app.launch(conf, "run", null, monitor);
+
+ verify(app).createDeployerConfiguration(conf);
+ verify(app).createOperation(eq(monitor), any(HttpPublishConfig.class));
+ }
+
+ @Test(expected=CoreException.class)
+ public void invalidLaunchTest() throws CoreException {
+ CloudApplication app = spy(new CloudApplication());
+ ILaunchConfiguration conf = mock(ILaunchConfiguration.class);
+ HttpPublishOperation operation = mock(HttpPublishOperation.class);
+ doReturn(operation).when(app).createOperation(any(IProgressMonitor.class), any(HttpPublishConfig.class));
+
+ IProgressMonitor monitor = mock(IProgressMonitor.class);
+ when(operation.run(monitor)).thenReturn(new Status(Status.ERROR, "error", "error"));
+ app.launch(conf, "run", null, monitor);
+ }
+
+ @Test
+ public void createConfigurationTest() throws CoreException {
+ CloudApplication app = new CloudApplication();
+ ILaunchConfiguration configuration = mock(ILaunchConfiguration.class);
+ when(configuration.getAttribute(CloudApplicationLaunchConfig.ATTR_SERVER_URI, "")).thenReturn(SERVER_URI);
+
+ HttpPublishConfig publishConfig = app.createDeployerConfiguration(configuration);
+ assertEquals(SERVER_URI, publishConfig.getHttpDeployerServiceUrl());
+ }
+
+ @Test
+ public void createDeployerConfigurationTest() {
+ CloudApplication app = new CloudApplication();
+ HttpPublishConfig config = spy(new HttpPublishConfig());
+ config.setQualifier("foo");
+ HttpPublishOperation createOperation = app.createOperation(mock(IProgressMonitor.class), config);
+ assertEquals(true, createOperation.isUser());
+ assertEquals(ResourcesPlugin.getWorkspace().getRoot(), createOperation.getRule());
+ assertEquals("Http Deployer Job", createOperation.getName());
+ }
+
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishConfigTest.java b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishConfigTest.java
new file mode 100644
index 0000000..f208951
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/internal/launch/HttpPublishConfigTest.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal.launch;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class HttpPublishConfigTest {
+
+ private static final String VALID_SERVER_URI = "http://localhost";
+
+ @Test
+ public void createDefaultConfigurationTest() {
+ HttpPublishConfig config = HttpPublishConfig.createDefaultConfiguration(VALID_SERVER_URI);
+
+ assertEquals(VALID_SERVER_URI, config.getHttpDeployerServiceUrl());
+ assertEquals(true, config.isAllowBinaryCycles());
+ assertArrayEquals(null, config.getJnlpInfo());
+ assertEquals(null, config.getQualifier());
+ assertEquals(true, config.isToDirectory());
+ assertArrayEquals(null, config.getSigningInfo());
+ assertArrayEquals(null, config.getTargets());
+ assertEquals(true, config.isUseJarFormat());
+ assertEquals(false, config.isUseWorkspaceCompiledClasses());
+ assertEquals(true, config.isExportMetadata());
+ assertEquals(true, config.isExportSource());
+ assertEquals(true, config.isExportSourceBundle());
+ assertEquals(null, config.getCategoryDefinition());
+ assertArrayEquals(null, config.getItems());
+
+ String destinationDirectory = config.getDestinationDirectory();
+ assertTrue(destinationDirectory.startsWith(System.getProperty("java.io.tmpdir") + "/build_"));
+ }
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigTest.java b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigTest.java
new file mode 100644
index 0000000..8af71a8
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigTest.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.launch;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.junit.Test;
+
+public class CloudApplicationLaunchConfigTest {
+
+ private static final String FEATURE_ID = "according to jim";
+ private static final String FEATURE_VERSION = "S01E12";
+ private static final String SERVER_URI = "localhost";
+
+ @Test
+ public void launchConfigTest() throws CoreException {
+ ILaunchConfiguration conf = mock(ILaunchConfiguration.class);
+ CloudApplicationLaunchConfig cloudApp = new CloudApplicationLaunchConfig(conf);
+
+ when(conf.getAttribute(CloudApplicationLaunchConfig.ATTR_FEATURE_ID, "")).thenReturn(FEATURE_ID);
+ when(conf.getAttribute(CloudApplicationLaunchConfig.ATTR_FEATURE_VERSION, "")).thenReturn(FEATURE_VERSION);
+ when(conf.getAttribute(CloudApplicationLaunchConfig.ATTR_SERVER_URI, "")).thenReturn(SERVER_URI);
+
+ assertEquals(FEATURE_ID, cloudApp.getFeatureId());
+ assertEquals(FEATURE_VERSION, cloudApp.getFeatureVersion());
+ assertEquals(SERVER_URI, cloudApp.getServerUri());
+ }
+
+ @Test
+ public void launchConfigSetterTest() {
+ ILaunchConfigurationWorkingCopy conf = mock(ILaunchConfigurationWorkingCopy.class);
+ CloudApplicationLaunchConfig cloudApp = new CloudApplicationLaunchConfig(conf);
+ cloudApp.setFeatureId(FEATURE_ID);
+ verify(conf).setAttribute(CloudApplicationLaunchConfig.ATTR_FEATURE_ID, FEATURE_ID);
+ cloudApp.setFeatureVersion(FEATURE_VERSION);
+ verify(conf).setAttribute(CloudApplicationLaunchConfig.ATTR_FEATURE_VERSION, FEATURE_VERSION);
+ cloudApp.setServerUri(SERVER_URI);
+ verify(conf).setAttribute(CloudApplicationLaunchConfig.ATTR_SERVER_URI, SERVER_URI);
+ }
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigValidatorTest.java b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigValidatorTest.java
new file mode 100644
index 0000000..5bc54ee
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/CloudApplicationLaunchConfigValidatorTest.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.launch;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.junit.Test;
+
+public class CloudApplicationLaunchConfigValidatorTest {
+
+ @Test
+ public void launchConfigValidatorTest() throws CoreException {
+ ILaunchConfiguration config = mock(ILaunchConfiguration.class);
+ when(config.getAttribute(CloudApplicationLaunchConfig.ATTR_FEATURE_ID, "")).thenReturn("test");
+ when(config.getAttribute(CloudApplicationLaunchConfig.ATTR_FEATURE_VERSION, "")).thenReturn("foo");
+ when(config.getAttribute(CloudApplicationLaunchConfig.ATTR_SERVER_URI, "")).thenReturn("localhost");
+
+ assertTrue(CloudApplicationLaunchConfigValidator.validate(config));
+ }
+
+ @Test
+ public void launchConfigValidatorInvalidTest() throws CoreException {
+ ILaunchConfiguration config = mock(ILaunchConfiguration.class);
+ when(config.getAttribute(CloudApplicationLaunchConfig.ATTR_FEATURE_ID, "")).thenReturn("");
+ when(config.getAttribute(CloudApplicationLaunchConfig.ATTR_FEATURE_VERSION, "")).thenReturn("");
+ when(config.getAttribute(CloudApplicationLaunchConfig.ATTR_SERVER_URI, "")).thenReturn("");
+
+ assertFalse(CloudApplicationLaunchConfigValidator.validate(config));
+ }
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/CloudApplicationLaunchUtilsTest.java b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/CloudApplicationLaunchUtilsTest.java
new file mode 100644
index 0000000..084a8fc
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/CloudApplicationLaunchUtilsTest.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.launch.utils;
+
+import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
+import org.junit.Test;
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+@SuppressWarnings("restriction")
+public class CloudApplicationLaunchUtilsTest {
+
+ @Test
+ public void getFeatureModelTest() {
+ IFeatureModel[] models = PDECore.getDefault().getFeatureModelManager().getModels();
+ if (models.length == 0) {
+ fail("this test requires a valid feature in the target platform");
+ }
+
+ IFeatureModel featureModel = models[0];
+ String id = featureModel.getFeature().getId();
+ String version = featureModel.getFeature().getVersion();
+
+ IFeatureModel model = CloudApplicationLaunchUtils.getFeatureModel(id, version);
+ assertEquals(featureModel, model);
+
+ version = version + "not available version number";
+ model = CloudApplicationLaunchUtils.getFeatureModel(id, version);
+ assertNull(model);
+ }
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/ZipUtilsTest.java b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/ZipUtilsTest.java
new file mode 100644
index 0000000..1bb8ff4
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer.launch/src/org/eclipse/rtp/httpdeployer/launch/utils/ZipUtilsTest.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.launch.utils;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.junit.Test;
+
+public class ZipUtilsTest {
+
+ private HashSet<String> FIXTURE_FILES = new HashSet<String>();
+
+ @Test
+ public void zipRecursiveDirectoryTest() throws IOException {
+ FIXTURE_FILES.add("root.txt");
+ FIXTURE_FILES.add("folder1/folder1.txt");
+
+ File input = new File("fixtures/zip");
+ File output = new File(CloudApplicationLaunchUtils.getTempDir());
+ ZipUtils.zip(input, output);
+
+ ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(output)));
+ ZipEntry zipEntry;
+ while((zipEntry = zis.getNextEntry()) != null) {
+ FIXTURE_FILES.remove(zipEntry.getName());
+ }
+ output.delete();
+
+ assertEquals(0, FIXTURE_FILES.size());
+ }
+
+
+ @Test
+ public void zipFileTest() throws IOException {
+ FIXTURE_FILES.add("root.txt");
+
+ File input = new File("fixtures/zip/root.txt");
+ File output = new File(CloudApplicationLaunchUtils.getTempDir());
+ ZipUtils.zip(input, output);
+
+ ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(output)));
+ ZipEntry zipEntry;
+ while((zipEntry = zis.getNextEntry()) != null) {
+ FIXTURE_FILES.remove(zipEntry.getName());
+ }
+ output.delete();
+
+ assertEquals(0, FIXTURE_FILES.size());
+ }
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/.classpath b/tests/org.eclipse.rtp.tests.httpdeployer/.classpath
new file mode 100644
index 0000000..16d067f
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/.gitignore b/tests/org.eclipse.rtp.tests.httpdeployer/.gitignore
new file mode 100644
index 0000000..36f971e
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/.gitignore
@@ -0,0 +1 @@
+bin/*
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/.project b/tests/org.eclipse.rtp.tests.httpdeployer/.project
new file mode 100644
index 0000000..b248cb1
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.rtp.tests.httpdeployer</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>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/.settings/org.eclipse.jdt.core.prefs b/tests/org.eclipse.rtp.tests.httpdeployer/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..dad8b47
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Tue May 10 15:14:49 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/.settings/org.eclipse.pde.core.prefs b/tests/org.eclipse.rtp.tests.httpdeployer/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000..338fdfd
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,4 @@
+#Tue May 10 15:14:49 CEST 2011
+eclipse.preferences.version=1
+pluginProject.extensions=false
+resolve.requirebundle=false
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/All httpdeployer Tests.launch b/tests/org.eclipse.rtp.tests.httpdeployer/All httpdeployer Tests.launch
new file mode 100644
index 0000000..83e0739
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/All httpdeployer Tests.launch
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
+<stringAttribute key="application" value="org.eclipse.pde.junit.runtime.coretestapplication"/>
+<booleanAttribute key="askclear" value="true"/>
+<booleanAttribute key="automaticAdd" value="true"/>
+<booleanAttribute key="automaticValidate" value="false"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="false"/>
+<booleanAttribute key="clearws" value="false"/>
+<booleanAttribute key="clearwslog" value="false"/>
+<booleanAttribute key="com.mountainminds.eclemma.core.INPLACE_INSTRUMENTATION" value="true"/>
+<listAttribute key="com.mountainminds.eclemma.core.INSTRUMENTATION_PATHS">
+<listEntry value="/org.eclipse.rtp.tests.httpdeployer/bin"/>
+<listEntry value="/org.eclipse.rtp.httpdeployer/bin"/>
+</listAttribute>
+<stringAttribute key="configLocation" value=""/>
+<booleanAttribute key="default" value="true"/>
+<booleanAttribute key="includeOptional" value="true"/>
+<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.rtp.tests.httpdeployer"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.rtp.tests.httpdeployer"/>
+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.rtp.tests.httpdeployer"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="pde.version" value="3.3"/>
+<stringAttribute key="product" value="org.eclipse.equinox.p2.director.app.product"/>
+<booleanAttribute key="run_in_ui_thread" value="false"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useCustomFeatures" value="false"/>
+<booleanAttribute key="useDefaultConfig" value="true"/>
+<booleanAttribute key="useDefaultConfigArea" value="true"/>
+<booleanAttribute key="useProduct" value="false"/>
+</launchConfiguration>
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/META-INF/MANIFEST.MF b/tests/org.eclipse.rtp.tests.httpdeployer/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..a5ec9c6
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/META-INF/MANIFEST.MF
@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Httpdeployer Testbundle
+Bundle-SymbolicName: org.eclipse.rtp.tests.httpdeployer;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Fragment-Host: org.eclipse.rtp.httpdeployer
+Import-Package: org.eclipse.equinox.internal.p2.director,
+ org.eclipse.equinox.p2.planner;version="2.0.0",
+ org.hamcrest,
+ org.junit,
+ org.mockito,
+ org.mockito.stubbing,
+ org.objenesis
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/build.properties b/tests/org.eclipse.rtp.tests.httpdeployer/build.properties
new file mode 100644
index 0000000..e6dc08b
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ fixtures/
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/build.xml b/tests/org.eclipse.rtp.tests.httpdeployer/build.xml
new file mode 100644
index 0000000..5118f78
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/build.xml
@@ -0,0 +1,343 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.rtp.tests.httpdeployer" default="build.jars" basedir=".">
+
+ <property name="p2.build.repo" value="file:${buildDirectory}/buildRepo"/>
+ <property name="basews" value="${ws}"/>
+ <property name="baseos" value="${os}"/>
+ <property name="basearch" value="${arch}"/>
+ <property name="basenl" value="${nl}"/>
+ <property name="bundleId" value="org.eclipse.rtp.tests.httpdeployer"/>
+ <property name="bundleVersion" value="1.0.0.201108091510"/>
+ <property name="p2.publishonerror" value="false"/>
+
+ <!-- Compiler settings. -->
+ <property name="javacFailOnError" value="false"/>
+ <property name="javacDebugInfo" value="on"/>
+ <property name="javacVerbose" value="false"/>
+ <property name="logExtension" value=".log"/>
+ <property name="compilerArg" value=""/>
+ <property name="compilation.prereq.log" value="${buildDirectory}/prereqErrors.log"/>
+ <property name="javacSource" value="1.3"/>
+ <property name="javacTarget" value="1.2"/>
+ <condition property="dir_bootclasspath" value="${java.home}/../Classes">
+ <os family="mac"/>
+ </condition>
+ <property name="dir_bootclasspath" value="${java.home}/lib"/>
+ <path id="path_bootclasspath">
+ <fileset dir="${dir_bootclasspath}">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+ <property name="bootclasspath" refid="path_bootclasspath"/>
+ <condition property="bundleBootClasspath" value="${JavaSE-1.6}" >
+ <isset property="JavaSE-1.6"/>
+ </condition>
+ <condition property="bundleJavacSource" value="1.6" >
+ <isset property="JavaSE-1.6"/>
+ </condition>
+ <condition property="bundleJavacTarget" value="1.6" >
+ <isset property="JavaSE-1.6"/>
+ </condition>
+ <property name="bundleJavacSource" value="${javacSource}"/>
+ <property name="bundleJavacTarget" value="${javacTarget}"/>
+ <property name="bundleBootClasspath" value="${bootclasspath}"/>
+
+ <target name="init" depends="properties">
+ <condition property="pluginTemp" value="${buildTempFolder}/plugins" >
+ <isset property="buildTempFolder"/>
+ </condition>
+ <property name="pluginTemp" value="${basedir}"/>
+ <condition property="build.result.folder" value="${pluginTemp}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510" >
+ <isset property="buildTempFolder"/>
+ </condition>
+ <property name="build.result.folder" value="${basedir}"/>
+ <property name="temp.folder" value="${basedir}/temp.folder"/>
+ <property name="plugin.destination" value="${basedir}"/>
+ <condition property="p2.publish.parts" value="true" >
+ <istrue value="${p2.gathering}"/>
+ </condition>
+ <property name="compilation.problem.marker" value="${build.result.folder}/compilation.problem"/>
+ <condition property="compilation.problem.marker.exists" value="true" >
+ <and>
+ <available file="${compilation.problem.marker}"/>
+ <isfalse value="${p2.publishonerror}"/>
+ </and>
+ </condition>
+ </target>
+
+ <target name="properties" if="eclipse.running">
+ <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
+
+ </target>
+
+ <target name="build.update.jar" depends="init" description="Build the plug-in: org.eclipse.rtp.tests.httpdeployer for an update site.">
+ <delete dir="${temp.folder}"/>
+ <mkdir dir="${temp.folder}"/>
+ <antcall target="build.jars"/>
+ <antcall target="gather.bin.parts">
+ <param name="destination.temp.folder" value="${temp.folder}/"/>
+ </antcall>
+ <jar destfile="${plugin.destination}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510.jar" basedir="${temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510" filesetmanifest="merge"/>
+ <delete dir="${temp.folder}"/>
+ </target>
+
+ <target name="@dot.nestedJars">
+ <mkdir dir="${buildDirectory}/nestedJars/org.eclipse.equinox.registry_3.5.100.v20110502"/>
+ <unzip src="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.registry_3.5.100.v20110502.jar" dest="${buildDirectory}/nestedJars/org.eclipse.equinox.registry_3.5.100.v20110502" overwrite="false">
+ <patternset includes="runtime_registry_compatibility.jar"/>
+ </unzip>
+ </target>
+ <target name="@dot" depends="init,@dot.nestedJars" unless="@dot" description="Create jar: org.eclipse.rtp.tests.httpdeployer @dot.">
+ <delete dir="${build.result.folder}/@dot"/>
+ <mkdir dir="${build.result.folder}/@dot"/>
+ <path id="@dot.classpath">
+ <pathelement path="../../bundles/org.eclipse.rtp.httpdeployer/bin"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/javax.servlet_2.5.0.v201103041518.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.commons.fileupload_1.2.0.v20080604-1500.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.commons.io_2.0.1.v201105210651.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.core.runtime_3.7.0.v20110110.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.osgi_3.7.0.v20110613.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/javax.transaction_1.1.1.v201105210645.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.servletbridge.extensionbundle_1.2.0.v20100503.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.transforms.hook_1.0.300.v20100719.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.weaving.hook_1.0.100.v20110502.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.common_3.6.0.v20110523.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.core.jobs_3.5.100.v20110404.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.core.runtime.compatibility.registry_3.5.0.v20110505/runtime_registry_compatibility.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.core.runtime.compatibility.registry_3.5.0.v20110505"/>
+ <pathelement path="${buildDirectory}/nestedJars/org.eclipse.equinox.registry_3.5.100.v20110502/runtime_registry_compatibility.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.registry_3.5.100.v20110502.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.preferences_3.4.0.v20110502.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.core.contenttype_3.4.100.v20110423-0524.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.core.runtime.compatibility.auth_3.2.200.v20110110.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.app_1.3.100.v20110321.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.osgi.services_3.3.0.v20110513.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.simpleconfigurator_1.0.200.v20110502-1955.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.p2.core_2.1.0.v20110502-1955.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.p2.engine_2.1.0.v20110511.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.p2.metadata_2.1.0.v20110510.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.p2.metadata.repository_1.2.0.v20110511-1359.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.p2.repository_2.1.0.v20110601.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.security_1.1.0.v20110502.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.p2.operations_2.1.0.v20110511-1821.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.eclipse.equinox.p2.director_2.1.0.v20110504-1715.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.sat4j.core_2.3.0.v20110329.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.sat4j.pb_2.3.0.v20110329.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.jdom_1.0.0.v201005080400.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.xerces_2.9.0.v201101211617.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/javax.xml_1.3.4.v201005080400.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.xml.resolver_1.2.0.v201005080400.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.xml.serializer_2.7.1.v201005080400.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.hamcrest_1.1.0.v20090501071000.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.hamcrest.core_1.1.0.v20090501071000.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.hamcrest.library_1.1.0.v20090501071000.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.hamcrest.generator_1.1.0.v20090501071000.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/com.thoughtworks.qdox_1.6.3.v20081201-1400.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.junit_3.8.2.v3_8_2_v20100427-1100/junit.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.hamcrest.integration_1.1.0.v20090501071000.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.easymock_2.4.0.v20090202-0900.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.hamcrest.text_1.1.0.v20090501071000.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.junit_4.8.2.v4_8_2_v20110321-1705/junit.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.mockito_1.8.4.v201102171835.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.objenesis_1.0.0.v201105211943.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-antlr.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-apache-bcel.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-apache-bsf.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-apache-log4j.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-apache-oro.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-apache-regexp.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-apache-resolver.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-apache-xalan2.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-commons-logging.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-commons-net.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-jai.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-javamail.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-jdepend.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-jmf.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-jsch.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-junit.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-junit4.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-launcher.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-netrexx.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-swing.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant-testutil.jar"/>
+ <pathelement path="../../../../Applications/eclipse-indigo/plugins/org.apache.ant_1.8.2.v20110505-1300/lib/ant.jar"/>
+ <pathelement path="bin"/>
+ <pathelement path="${build.result.folder}/../org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510/bin"/>
+ </path>
+ <!-- compile the source code -->
+ <javac destdir="${build.result.folder}/@dot" failonerror="${javacFailOnError}" verbose="${javacVerbose}" debug="${javacDebugInfo}" includeAntRuntime="no" bootclasspath="${bundleBootClasspath}" source="${bundleJavacSource}" target="${bundleJavacTarget}" >
+ <compilerarg line="${compilerArg}" compiler="${build.compiler}"/>
+ <classpath refid="@dot.classpath" />
+ <src path="src/" />
+ <compilerarg value="@${basedir}/javaCompiler...args" compiler="org.eclipse.jdt.core.JDTCompilerAdapter" />
+ <compilerarg line="-log &apos;${build.result.folder}/@dot${logExtension}&apos;" compiler="org.eclipse.jdt.core.JDTCompilerAdapter" />
+ </javac>
+ <antcall target="checkCompilationResults"/>
+ <!-- Copy necessary resources -->
+ <copy todir="${build.result.folder}/@dot" failonerror="true" overwrite="false">
+ <fileset dir="src/">
+ <exclude name="**/*.java"/>
+ <exclude name="**/package.htm*"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="src.zip" depends="init" unless="src.zip">
+ <mkdir dir="${build.result.folder}"/>
+ <antcall target="zip.src.zip"/>
+ </target>
+ <target name="zip.src.zip">
+ <zip destfile="${build.result.folder}/src.zip" filesonly="false" whenempty="skip" update="false">
+ <fileset dir="src/">
+ <include name="**/*.java"/>
+ </fileset>
+ </zip>
+ </target>
+ <target name="copy.src.zip">
+ <copy todir="${source.destination.folder}/" failonerror="true" overwrite="true">
+ <fileset dir="src/">
+ <include name="**/*.java"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="build.jars" depends="init" description="Compile classes and build nested jars for the plug-in: org.eclipse.rtp.tests.httpdeployer.">
+ <delete file="${compilation.problem.marker}" quiet="true"/>
+ <available property="@dot" file="${build.result.folder}/@dot"/>
+ <antcall target="@dot"/>
+ </target>
+
+ <target name="checkCompilationResults" if="compilation.error.occured">
+ <echo file="${compilation.problem.marker}" message="org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510${line.separator}compilation.error.occured=${compilation.error.occured}"/>
+ <eclipse.logCompileError bundle="org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510" log="${compilation.prereq.log}">
+ <include name="/home/sebs/gsoc2011/webdeployer/bundles/org.eclipse.rtp.httpdeployer/compilation.problem"/>
+ <include name="${pluginTemp}/org.eclipse.rtp.httpdeployer_0.2.0/compilation.problem"/>
+ </eclipse.logCompileError>
+ </target>
+
+ <target name="build.sources" depends="init">
+ <available property="src.zip" file="${build.result.folder}/src.zip"/>
+ <antcall target="src.zip"/>
+ </target>
+
+ <target name="publish.bin.parts" depends="init" if="p2.publish.parts" unless="compilation.problem.marker.exists">
+ <mkdir dir="${build.result.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510"/>
+ <copy todir="${build.result.folder}" failonerror="true" overwrite="true">
+ <fileset dir="${basedir}">
+ <include name="META-INF/MANIFEST.MF"/>
+ <include name="plugin.xml"/>
+ <include name="fragment.xml"/>
+ </fileset>
+ </copy>
+ <eclipse.versionReplacer path="${build.result.folder}" version="1.0.0.201108091510"/>
+ <antcall target="apitools.generation">
+ <param name="target.folder" value="${build.result.folder}"/>
+ <param name="extraManifests" value="${basedir}/../../bundles/org.eclipse.rtp.httpdeployer/META-INF/MANIFEST.MF"/>
+ <param name="projectLocation" value="${basedir}"/>
+ <param name="binary.folders" value="${build.result.folder}/@dot:/home/sebs/gsoc2011/webdeployer/tests/org.eclipse.rtp.tests.httpdeployer/bin"/>
+ <param name="projectName" value="${bundleId}_${bundleVersion}"/>
+ </antcall>
+ <eclipse.gatherBundle
+ metadataRepository="${p2.build.repo}"
+ artifactRepository="${p2.build.repo}"
+ buildResultFolder="${build.result.folder}"
+ unpack="true"
+ baseDirectory="${basedir}"
+ />
+ </target>
+
+ <target name="gather.bin.parts" depends="init" if="destination.temp.folder">
+ <mkdir dir="${destination.temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510"/>
+ <copy todir="${destination.temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510" failonerror="true" overwrite="false">
+ <fileset dir="${build.result.folder}/@dot">
+ <include name="**"/>
+ </fileset>
+ </copy>
+ <copy todir="${destination.temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510" failonerror="true" overwrite="true">
+ <fileset dir="${basedir}">
+ <include name="META-INF/"/>
+ <include name="fixtures/"/>
+ </fileset>
+ </copy>
+ <eclipse.versionReplacer path="${destination.temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510" version="1.0.0.201108091510"/>
+ <antcall target="apitools.generation">
+ <param name="target.folder" value="${destination.temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510"/>
+ <param name="extraManifests" value="${basedir}/../../bundles/org.eclipse.rtp.httpdeployer/META-INF/MANIFEST.MF"/>
+ <param name="projectLocation" value="${basedir}"/>
+ <param name="binary.folders" value="${build.result.folder}/@dot:/home/sebs/gsoc2011/webdeployer/tests/org.eclipse.rtp.tests.httpdeployer/bin"/>
+ <param name="projectName" value="${bundleId}_${bundleVersion}"/>
+ </antcall>
+ </target>
+
+ <target name="build.zips" depends="init">
+ </target>
+
+ <target name="gather.sources" depends="init" if="destination.temp.folder">
+ <mkdir dir="${destination.temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510"/>
+ <copy file="${build.result.folder}/src.zip" todir="${destination.temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510" failonerror="false" overwrite="false"/>
+ <antcall target="copy.src.includes">
+ <param name="source.destination.folder" value="${destination.temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510"/>
+ </antcall>
+ </target>
+
+ <target name="gather.individual.sources" depends="init">
+ <antcall target="copy.src.zip">
+ <param name="source.destination.folder" value="${destination.temp.folder}"/>
+ </antcall>
+ <antcall target="copy.src.includes">
+ <param name="source.destination.folder" value="${destination.temp.folder}"/>
+ </antcall>
+ </target>
+
+ <target name="copy.src.includes" depends="init">
+ </target>
+
+ <target name="gather.logs" depends="init" if="destination.temp.folder">
+ <mkdir dir="${destination.temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510"/>
+ <copy todir="${destination.temp.folder}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510" failonerror="false" overwrite="false">
+ <fileset dir="${build.result.folder}">
+ <include name="@dot${logExtension}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="clean" depends="init" description="Clean the plug-in: org.eclipse.rtp.tests.httpdeployer of all the zips, jars and logs created.">
+ <delete dir="${build.result.folder}/@dot"/>
+ <delete file="${build.result.folder}/src.zip"/>
+ <delete file="${plugin.destination}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510.jar"/>
+ <delete file="${plugin.destination}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510.zip"/>
+ <delete dir="${temp.folder}"/>
+ <delete file="${compilation.problem.marker}" quiet="true"/>
+ </target>
+
+ <target name="refresh" depends="init" if="eclipse.running" description="Refresh this folder.">
+ <eclipse.convertPath fileSystemPath="/home/sebs/gsoc2011/webdeployer/tests/org.eclipse.rtp.tests.httpdeployer" property="resourcePath"/>
+ <eclipse.refreshLocal resource="${resourcePath}" depth="infinite"/>
+ </target>
+
+ <target name="zip.plugin" depends="init" description="Create a zip containing all the elements for the plug-in: org.eclipse.rtp.tests.httpdeployer.">
+ <delete dir="${temp.folder}"/>
+ <mkdir dir="${temp.folder}"/>
+ <antcall target="build.jars"/>
+ <antcall target="build.sources"/>
+ <antcall target="gather.bin.parts">
+ <param name="destination.temp.folder" value="${temp.folder}/"/>
+ </antcall>
+ <antcall target="gather.sources">
+ <param name="destination.temp.folder" value="${temp.folder}/"/>
+ </antcall>
+ <delete>
+ <fileset dir="${temp.folder}">
+ <include name="**/*.bin${logExtension}"/>
+ </fileset>
+ </delete>
+ <zip destfile="${plugin.destination}/org.eclipse.rtp.tests.httpdeployer_1.0.0.201108091510.zip" basedir="${temp.folder}" filesonly="true" whenempty="skip" update="false"/>
+ <delete dir="${temp.folder}"/>
+ </target>
+
+ <target name="apitools.generation" if="generateAPIDescription">
+ <apitooling.apigeneration projectName="${projectName}" project="${projectLocation}" binary="${binary.folders}" target="${target.folder}" extramanifests="${extraManifests}" allownonapiproject="${allowNonApiProject}" />
+ </target>
+
+</project>
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/fixtures/invalidRepositoryPackage.zip b/tests/org.eclipse.rtp.tests.httpdeployer/fixtures/invalidRepositoryPackage.zip
new file mode 100644
index 0000000..22710ce
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/fixtures/invalidRepositoryPackage.zip
Binary files differ
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/fixtures/validRepositoryPackage.zip b/tests/org.eclipse.rtp.tests.httpdeployer/fixtures/validRepositoryPackage.zip
new file mode 100644
index 0000000..e7d961d
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/fixtures/validRepositoryPackage.zip
Binary files differ
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServletOperationsTest.java b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServletOperationsTest.java
new file mode 100644
index 0000000..0d88cc2
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServletOperationsTest.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.bundle;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+
+public class BundleServletOperationsTest {
+ @Mock
+ private Bundle bundle;
+
+ @Mock
+ private HttpServletResponse response;
+
+ @Mock
+ private HttpServletRequest request;
+
+ private BundleServlet objectUnderTest;
+
+ private Writer responseWriter = new StringWriter();
+
+ private PrintWriter responsePrintWriter = new PrintWriter(responseWriter);
+
+ private static final String VALID_DELETE_REQUEST = "<bundles><bundle><name>bundle</name></bundle></bundles>";
+
+ private static final String VALID_START_REQUEST = "<bundles><bundle><action>start</action><name>bundle</name></bundle></bundles>";
+
+ private static final String VALID_STOP_REQUEST = "<bundles><bundle><action>stop</action><name>bundle</name></bundle></bundles>";
+
+ @Before
+ public void setUp() throws IOException {
+ MockitoAnnotations.initMocks(this);
+ this.objectUnderTest = new MockBundleServlet();
+ when(response.getWriter()).thenReturn(responsePrintWriter);
+ }
+
+ @Test
+ public void startUnknownBundleTest() throws IOException, ServletException, JDOMException {
+ when(bundle.getSymbolicName()).thenReturn("bundle1");
+ when(request.getReader()).thenReturn(new BufferedReader(new StringReader(VALID_START_REQUEST)));
+ // return stupid http method to break multiform-check in this test
+ when(request.getMethod()).thenReturn("fooo");
+
+ objectUnderTest.doPost(request, response);
+
+ BundleManageResponse response = parseResponse();
+ assertEquals("bundle", response.getName());
+ assertEquals("START", response.getAction());
+ assertEquals("bundle not found", response.getReason());
+ }
+
+ @Test
+ public void startBundleTest() throws IOException, ServletException, JDOMException, BundleException {
+ when(bundle.getSymbolicName()).thenReturn("bundle");
+ when(request.getReader()).thenReturn(new BufferedReader(new StringReader(VALID_START_REQUEST)));
+ // return stupid http method to break multiform-check in this test
+ when(request.getMethod()).thenReturn("fooo");
+
+ objectUnderTest.doPost(request, response);
+
+ BundleManageResponse response = parseResponse();
+ assertEquals("bundle", response.getName());
+ assertEquals("START", response.getAction());
+ assertEquals(null, response.getReason());
+ verify(bundle).start();
+ }
+
+ @Test
+ public void startBundleExceptionTest() throws IOException, ServletException, JDOMException, BundleException {
+ when(bundle.getSymbolicName()).thenReturn("bundle");
+ doThrow(new BundleException("fancy exception")).when(bundle).start();
+ when(request.getReader()).thenReturn(new BufferedReader(new StringReader(VALID_START_REQUEST)));
+ // return stupid http method to break multiform-check in this test
+ when(request.getMethod()).thenReturn("fooo");
+
+ objectUnderTest.doPost(request, response);
+
+ BundleManageResponse response = parseResponse();
+ assertEquals("bundle", response.getName());
+ assertEquals("START", response.getAction());
+ assertEquals("fancy exception", response.getReason());
+ verify(bundle).start();
+ }
+
+ @Test
+ public void stopBundleTest() throws IOException, ServletException, JDOMException, BundleException {
+ when(bundle.getSymbolicName()).thenReturn("bundle");
+ when(request.getReader()).thenReturn(new BufferedReader(new StringReader(VALID_STOP_REQUEST)));
+ // return stupid http method to break multiform-check in this test
+ when(request.getMethod()).thenReturn("fooo");
+
+ objectUnderTest.doPost(request, response);
+
+ BundleManageResponse response = parseResponse();
+ assertEquals("bundle", response.getName());
+ assertEquals("STOP", response.getAction());
+ assertEquals(null, response.getReason());
+ verify(bundle).stop();
+ }
+
+ @Test
+ public void deleteBundleTest() throws IOException, ServletException, JDOMException, BundleException {
+ when(bundle.getSymbolicName()).thenReturn("bundle");
+ when(request.getReader()).thenReturn(new BufferedReader(new StringReader(VALID_DELETE_REQUEST)));
+
+ objectUnderTest.doDelete(request, response);
+
+ BundleManageResponse response = parseResponse();
+ assertEquals("bundle", response.getName());
+ assertEquals("UNINSTALL", response.getAction());
+ assertEquals(null, response.getReason());
+ verify(bundle).uninstall();
+ }
+
+ @Test
+ public void deleteInvalidRequestTest() throws IOException, ServletException, JDOMException, BundleException {
+ when(request.getReader()).thenReturn(new BufferedReader(new StringReader("according to jim")));
+ // return stupid http method to break multiform-check in this test
+ when(request.getMethod()).thenReturn("fooo");
+ objectUnderTest.doDelete(request, response);
+ verify(response).sendError(HttpServletResponse.SC_BAD_REQUEST);
+ }
+
+ @Test
+ public void startInvalidRequestTest() throws IOException, ServletException, JDOMException, BundleException {
+ when(request.getReader()).thenReturn(new BufferedReader(new StringReader("according to jim")));
+ // return stupid http method to break multiform-check in this test
+ when(request.getMethod()).thenReturn("fooo");
+
+ objectUnderTest.doPost(request, response);
+ verify(response).sendError(HttpServletResponse.SC_BAD_REQUEST);
+ }
+
+ private BundleManageResponse parseResponse() throws JDOMException, IOException {
+ SAXBuilder builder = new SAXBuilder();
+
+ Document request = builder.build(new ByteArrayInputStream(responseWriter.toString().getBytes()));
+ Element response = (Element) request.getRootElement().getChildren().get(0);
+
+ return new BundleManageResponse(response.getChildText("name"), response.getChildText("action"),
+ response.getChildText("reason"));
+ }
+
+ private class BundleManageResponse {
+
+ private final String name;
+ private final String action;
+ private final String reason;
+
+ public BundleManageResponse(String name, String action, String reason) {
+ this.name = name;
+ this.action = action;
+ this.reason = reason;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ public class MockBundleServlet extends BundleServlet {
+ private static final long serialVersionUID = 1L;
+
+ protected Bundle[] receiveBundles() {
+ return new Bundle[] { bundle };
+ }
+ }
+
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServletTest.java b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServletTest.java
new file mode 100755
index 0000000..fe21073
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/bundle/BundleServletTest.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.bundle;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.rtp.httpdeployer.internal.XmlConstants;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+
+public class BundleServletTest {
+
+ private static final String MOCK_RESOLVED_BUNDLE_NAME = "resolvedBundle";
+ private static final String MOCK_ACTIVE_BUNDLE_NAME = "activeBundle";
+
+ @Mock
+ private HttpServletResponse response;
+
+ @Mock
+ private HttpServletRequest request;
+
+ private OutputStream responseStream;
+
+ @Before
+ public void setUp() throws IOException {
+ MockitoAnnotations.initMocks(this);
+
+ responseStream = new ByteArrayOutputStream();
+
+ when(response.getWriter()).thenReturn(new PrintWriter(responseStream));
+ }
+
+ @Test
+ public void listAllBundlesTest() throws Exception {
+ when(request.getPathInfo()).thenReturn("/");
+ List<Element> children = executeGetBundles();
+ assertEquals(2, children.size());
+ assertEquals(MOCK_ACTIVE_BUNDLE_NAME, children.get(0).getChild(XmlConstants.XML_ELEMENT_NAME).getValue());
+ assertEquals(MOCK_RESOLVED_BUNDLE_NAME, children.get(1).getChild(XmlConstants.XML_ELEMENT_NAME).getValue());
+ }
+
+ @Test
+ public void listAllBundles2Test() throws Exception {
+ when(request.getPathInfo()).thenReturn(null);
+ List<Element> children = executeGetBundles();
+ assertEquals(2, children.size());
+ assertEquals(MOCK_ACTIVE_BUNDLE_NAME, children.get(0).getChild(XmlConstants.XML_ELEMENT_NAME).getValue());
+ assertEquals(MOCK_RESOLVED_BUNDLE_NAME, children.get(1).getChild(XmlConstants.XML_ELEMENT_NAME).getValue());
+ }
+
+ @Test
+ public void listActiveBundlesTest() throws Exception {
+ when(request.getPathInfo()).thenReturn(BundleServlet.REQUEST_PATH_ACTIVE_BUNDLES);
+ List<Element> children = executeGetBundles();
+ assertEquals(1, children.size());
+ assertEquals(MOCK_ACTIVE_BUNDLE_NAME, children.get(0).getChild(XmlConstants.XML_ELEMENT_NAME).getValue());
+ }
+
+ @Test
+ public void listResolvedBundlesTest() throws Exception {
+ when(request.getPathInfo()).thenReturn(BundleServlet.REQUEST_PATH_RESOLVED_BUNDLES);
+ List<Element> children = executeGetBundles();
+ assertEquals(1, children.size());
+ assertEquals(MOCK_RESOLVED_BUNDLE_NAME, children.get(0).getChild(XmlConstants.XML_ELEMENT_NAME).getValue());
+ }
+
+ @SuppressWarnings("unchecked")
+ private List<Element> executeGetBundles() throws ServletException, IOException, JDOMException {
+ BundleServlet servletUnderTest = new MockBundleServlet();
+ servletUnderTest.doGet(request, response);
+
+ SAXBuilder builder = new SAXBuilder();
+ Document result = builder.build(new StringReader(responseStream.toString()));
+
+ assertEquals(XmlConstants.XML_ELEMENT_BUNDLES, result.getRootElement().getName());
+ List<Element> children = result.getRootElement().getChildren(XmlConstants.XML_ELEMENT_BUNDLE);
+
+ Element firstBundle = children.get(0);
+ assertNotNull(firstBundle);
+ assertNotNull(firstBundle.getChild(XmlConstants.XML_ELEMENT_NAME));
+ assertNotNull(firstBundle.getChild(XmlConstants.XML_ELEMENT_VERSION));
+
+ return children;
+ }
+
+ public class MockBundleServlet extends BundleServlet {
+ private static final long serialVersionUID = 1L;
+
+ protected Bundle[] receiveBundles() {
+ Bundle mockActiveBundle = mock(Bundle.class);
+ when(mockActiveBundle.getState()).thenReturn(Bundle.ACTIVE);
+ when(mockActiveBundle.getVersion()).thenReturn(new Version(0, 0, 0));
+ when(mockActiveBundle.getSymbolicName()).thenReturn(MOCK_ACTIVE_BUNDLE_NAME);
+
+ Bundle mockResolvedBundle = mock(Bundle.class);
+ when(mockResolvedBundle.getState()).thenReturn(Bundle.RESOLVED);
+ when(mockResolvedBundle.getVersion()).thenReturn(new Version(0, 0, 0));
+ when(mockResolvedBundle.getSymbolicName()).thenReturn(MOCK_RESOLVED_BUNDLE_NAME);
+
+ return new Bundle[] { mockActiveBundle, mockResolvedBundle };
+ }
+ }
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureManagerTest.java b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureManagerTest.java
new file mode 100644
index 0000000..c415918
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureManagerTest.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.feature;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import java.net.URI;
+
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.equinox.internal.provisional.configurator.Configurator;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.engine.IProfile;
+import org.eclipse.equinox.p2.engine.IProfileRegistry;
+import org.eclipse.equinox.p2.engine.IProvisioningPlan;
+import org.eclipse.equinox.p2.engine.ProvisioningContext;
+import org.eclipse.equinox.p2.planner.IPlanner;
+import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
+import org.eclipse.equinox.p2.repository.IRepositoryManager;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
+import org.eclipse.rtp.httpdeployer.repository.RepositoryManager;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SuppressWarnings("restriction")
+public class FeatureManagerTest {
+
+ @Mock
+ IProvisioningAgent provisioningAgent;
+
+ @Mock
+ RepositoryManager repositoryManager;
+
+ @Mock
+ Configurator configurator;
+
+ @Mock
+ IMetadataRepositoryManager metadataRepositoryMock;
+
+ @Mock
+ IProfileRegistry profileRegistry;
+
+ @Mock
+ IProfile profile;
+
+ @Mock
+ IPlanner planner;
+
+ @Mock
+ IProvisioningPlan provisioningPlan;
+
+ FeatureManager objectUnderTest;
+
+ static final String FEATURE_NAME = "testFeature";
+ static final String FEATURE_VERSION = "1.0.0";
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ this.objectUnderTest = new FeatureManager(provisioningAgent, repositoryManager, configurator);
+ when(repositoryManager.getRepositories()).thenReturn(null);
+ when(provisioningAgent.getService(IMetadataRepositoryManager.SERVICE_NAME)).thenReturn(metadataRepositoryMock);
+ when(metadataRepositoryMock.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL)).thenReturn(new URI[] {});
+ when(provisioningAgent.getService(IProfileRegistry.SERVICE_NAME)).thenReturn(profileRegistry);
+ when(profileRegistry.getProfile(IProfileRegistry.SELF)).thenReturn(profile);
+ when(provisioningAgent.getService(IPlanner.SERVICE_NAME)).thenReturn(planner);
+ }
+
+ @Test
+ public void testInstallUnknownFeature() throws FeatureInstallException {
+ when(provisioningPlan.getStatus()).thenReturn(new Status(Status.ERROR, FEATURE_NAME, "some error message"));
+ when(planner.getProvisioningPlan(any(IProfileChangeRequest.class), any(ProvisioningContext.class), any(SubMonitor.class)))
+ .thenReturn(provisioningPlan);
+
+ try {
+ this.objectUnderTest.installFeature(FEATURE_NAME, FEATURE_VERSION);
+ fail();
+ } catch (FeatureInstallException e) {
+ assertEquals("Cannot complete the request. See the error log for details.\n", e.getMessage());
+ }
+
+ verifyZeroInteractions(configurator);
+ }
+
+ @Test
+ public void testUninstallUnknownFeature() throws FeatureInstallException {
+ when(provisioningPlan.getStatus()).thenReturn(new Status(Status.ERROR, FEATURE_NAME, "some error message"));
+ when(planner.getProvisioningPlan(any(IProfileChangeRequest.class), any(ProvisioningContext.class), any(SubMonitor.class)))
+ .thenReturn(provisioningPlan);
+
+ try {
+ this.objectUnderTest.uninstallFeature(FEATURE_NAME, FEATURE_VERSION);
+ fail();
+ } catch (FeatureInstallException e) {
+ assertEquals("Cannot complete the request. See the error log for details.\n", e.getMessage());
+ }
+
+ verifyZeroInteractions(configurator);
+ }
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureServletTest.java b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureServletTest.java
new file mode 100644
index 0000000..534917e
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/feature/FeatureServletTest.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.feature;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.rtp.httpdeployer.internal.XmlConstants;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class FeatureServletTest {
+
+ @Mock
+ private FeatureManager featureManager;
+
+ @Mock
+ private HttpServletResponse responseMock;
+
+ @Mock
+ private HttpServletRequest requestMock;
+
+ private static final String VALID_INSTALL_REQUEST = "<features><feature><name>installMock</name><version>1.0</version>"
+ + "</feature></features>";
+
+ private FeatureServlet featureServlet;
+ private Writer responseWriter = new StringWriter();
+ private PrintWriter responsePrintWriter = new PrintWriter(responseWriter);
+
+ @Before
+ public void setUp() throws IOException {
+ MockitoAnnotations.initMocks(this);
+
+ featureServlet = new FeatureServlet(featureManager, null);
+ when(responseMock.getWriter()).thenReturn(responsePrintWriter);
+ }
+
+ @Test
+ public void doInstallFeatureTest() throws ServletException, IOException, JDOMException, FeatureInstallException {
+ when(requestMock.getReader()).thenReturn(new BufferedReader(new StringReader(VALID_INSTALL_REQUEST)));
+ // return stupid http method to break multiform-check in this test
+ when(requestMock.getMethod()).thenReturn("fooo");
+
+ featureServlet.doPost(requestMock, responseMock);
+
+ SAXBuilder builder = new SAXBuilder();
+ Document request = builder.build(new ByteArrayInputStream(responseWriter.toString().getBytes()));
+ Element response = (Element) request.getRootElement().getChildren().get(0);
+
+ verify(featureManager).installFeature("installMock", "1.0");
+ assertEquals(XmlConstants.XML_VALUE_STATUS_SUCCESSFUL, response.getChildText("status"));
+ assertEquals("1.0", response.getChildText("version"));
+ assertEquals("installMock", response.getChildText("name"));
+ }
+
+ @Test
+ public void doInvalidInstallFeatureTest() throws ServletException, IOException, JDOMException, FeatureInstallException {
+ when(requestMock.getReader()).thenReturn(new BufferedReader(new StringReader("really not valid...")));
+ // return stupid http method to break multiform-check in this test
+ when(requestMock.getMethod()).thenReturn("fooo");
+
+ featureServlet.doPost(requestMock, responseMock);
+
+ verify(responseMock).sendError(HttpServletResponse.SC_BAD_REQUEST);
+ }
+
+ @Test
+ public void doInvalidUninstallFeatureTest() throws ServletException, IOException, JDOMException, FeatureInstallException {
+ when(requestMock.getReader()).thenReturn(new BufferedReader(new StringReader("really not valid...")));
+ featureServlet.doDelete(requestMock, responseMock);
+
+ verify(responseMock).sendError(HttpServletResponse.SC_BAD_REQUEST);
+ }
+
+ @Test
+ public void doValidUninstallFeatureTest() throws ServletException, IOException, JDOMException, FeatureInstallException {
+ when(requestMock.getReader()).thenReturn(new BufferedReader(new StringReader(VALID_INSTALL_REQUEST)));
+ featureServlet.doDelete(requestMock, responseMock);
+
+ SAXBuilder builder = new SAXBuilder();
+ Document request = builder.build(new ByteArrayInputStream(responseWriter.toString().getBytes()));
+ Element response = (Element) request.getRootElement().getChildren().get(0);
+
+ verify(featureManager).uninstallFeature("installMock", null);
+ assertEquals(XmlConstants.XML_VALUE_STATUS_SUCCESSFUL, response.getChildText("status"));
+ assertEquals("", response.getChildText("version"));
+ assertEquals("installMock", response.getChildText("name"));
+ }
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerComponentTest.java b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerComponentTest.java
new file mode 100644
index 0000000..d4ec5a8
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/internal/HttpDeployerComponentTest.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+
+import java.util.Dictionary;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import org.eclipse.equinox.internal.provisional.configurator.Configurator;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.NamespaceException;
+
+@SuppressWarnings("restriction")
+public class HttpDeployerComponentTest {
+
+ @Mock
+ IProvisioningAgent agent;
+
+ @Mock
+ HttpService service;
+
+ @Mock
+ Configurator configurator;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void deployerComponentTest() throws ServletException, NamespaceException {
+ HttpDeployerComponent component = new HttpDeployerComponent();
+ component.setHttpService(service);
+ component.setProvisioningAgent(agent);
+ component.setConfigurator(configurator);
+ component.startService();
+
+ verify(service).registerServlet(eq(HttpDeployerInitializer.ALIAS_REPOSITORY), any(Servlet.class), any(Dictionary.class),
+ any(HttpContext.class));
+ verify(service).registerServlet(eq(HttpDeployerInitializer.ALIAS_BUNDLE), any(Servlet.class), any(Dictionary.class),
+ any(HttpContext.class));
+ verify(service).registerServlet(eq(HttpDeployerInitializer.ALIAS_FEATURE), any(Servlet.class), any(Dictionary.class),
+ any(HttpContext.class));
+ verify(service).registerServlet(eq(HttpDeployerInitializer.ALIAS_SYSTEM), any(Servlet.class), any(Dictionary.class),
+ any(HttpContext.class));
+ assertEquals(configurator, component.configurator);
+
+ component.shutdownService();
+ verify(service).unregister(HttpDeployerInitializer.ALIAS_BUNDLE);
+ verify(service).unregister(HttpDeployerInitializer.ALIAS_REPOSITORY);
+ verify(service).unregister(HttpDeployerInitializer.ALIAS_FEATURE);
+ verify(service).unregister(HttpDeployerInitializer.ALIAS_SYSTEM);
+
+ component.unsetHttpService(service);
+ component.unsetProvisioningAgent(agent);
+ component.unsetConfigurator(configurator);
+
+ assertEquals(null, component.configurator);
+ assertEquals(null, component.httpService);
+ assertEquals(null, component.provisioningAgent);
+ }
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryManagerTest.java b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryManagerTest.java
new file mode 100644
index 0000000..b5f2ede
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryManagerTest.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.repository;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.commons.io.FileUtils;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
+import org.eclipse.rtp.httpdeployer.internal.CommonConstants;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class RepositoryManagerTest {
+
+ @Mock
+ private IProvisioningAgent paMock;
+ @Mock
+ private IMetadataRepositoryManager mrmMock;
+ @Mock
+ private IArtifactRepositoryManager armMock;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(paMock.getService(IMetadataRepositoryManager.SERVICE_NAME)).thenReturn(mrmMock);
+ when(paMock.getService(IArtifactRepositoryManager.SERVICE_NAME)).thenReturn(armMock);
+ }
+
+ @Test
+ public void addRemoteRepositoryTest() throws URISyntaxException {
+ RepositoryManager manager = new RepositoryManager(paMock);
+ URI repository = new URI("file:/tmp");
+ manager.addRepository(repository);
+
+ verify(mrmMock).addRepository(repository);
+ verify(armMock).addRepository(repository);
+ }
+
+ @Test
+ public void removeRemoteRepositoryTest() throws URISyntaxException {
+ RepositoryManager manager = new RepositoryManager(paMock);
+ URI repository = new URI("file:/tmp");
+ manager.removeRepository(repository);
+
+ verify(mrmMock).removeRepository(repository);
+ verify(armMock).removeRepository(repository);
+ }
+
+ @Test
+ public void getAllRepositoriesTest() {
+ RepositoryManager manager = new RepositoryManager(paMock);
+ manager.getRepositories();
+
+ verify(mrmMock).getKnownRepositories(IMetadataRepositoryManager.REPOSITORIES_ALL);
+ }
+
+ @Test(expected = InvalidRepositoryException.class)
+ public void addEmptyLocalRepositoryTest() throws InvalidRepositoryException, FileNotFoundException, IOException {
+ RepositoryManager manager = new RepositoryManager(paMock);
+ InputStream stream = new ByteArrayInputStream(new byte[1]);
+ manager.addRepository(stream);
+ }
+
+ @Test(expected = InvalidRepositoryException.class)
+ public void addInvalidLocalRepositoryTest() throws InvalidRepositoryException, IOException {
+ RepositoryManager manager = new RepositoryManager(paMock);
+ InputStream stream = new FileInputStream("fixtures/invalidRepositoryPackage.zip");
+ manager.addRepository(stream);
+ }
+
+ @Test
+ public void addValidLocalRepository() throws InvalidRepositoryException, IOException {
+ RepositoryManager manager = new RepositoryManager(paMock);
+ InputStream stream = new FileInputStream("fixtures/validRepositoryPackage.zip");
+ URI uri = manager.addRepository(stream);
+
+ assertNotNull(uri);
+ verify(mrmMock).addRepository(uri);
+ verify(armMock).addRepository(uri);
+
+ FileUtils.deleteDirectory(new File(uri));
+ }
+
+ @Test
+ public void removeLocalRepositoryTest() throws URISyntaxException, IOException {
+ RepositoryManager manager = new RepositoryManager(paMock);
+ File repository = new File(System.getProperty("java.io.tmpdir") + CommonConstants.DIR_SEPARATOR + "repo_"
+ + Long.toString(System.nanoTime()));
+ repository.mkdirs();
+ URI repo = repository.toURI();
+ manager.removeLocalRepository(repo);
+
+ assertFalse(repository.exists());
+ verify(mrmMock).removeRepository(repo);
+ verify(armMock).removeRepository(repo);
+ }
+
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryServletTest.java b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryServletTest.java
new file mode 100644
index 0000000..07b413c
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/repository/RepositoryServletTest.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.repository;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.eclipse.rtp.httpdeployer.util.MockServletInputStream;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class RepositoryServletTest {
+
+ private static final String TEST_REPOSITORY_URI = "file:/tmp/playyard";
+
+ private static final String VALID_DELETE_CREATE_REQUEST = "<repositories><repository><uri>" + TEST_REPOSITORY_URI
+ + "</uri></repository></repositories>";
+
+ private static final String VALID_DELETE_REQUEST_INVALID_URI = "<repositories><repository><uri>not an uri</uri></repository></repositories>";
+
+ private RepositoryServlet repositoryServlet;
+
+ @Mock
+ private RepositoryManager repoManagerMock;
+
+ @Mock
+ private HttpServletResponse responseMock;
+
+ @Mock
+ private HttpServletRequest requestMock;
+
+ private Writer responseWriter = new StringWriter();
+ private PrintWriter responsePrintWriter = new PrintWriter(responseWriter);
+
+ private URI[] repositories = null;
+
+ @Before
+ public void setUp() throws URISyntaxException, IOException {
+ MockitoAnnotations.initMocks(this);
+
+ repositoryServlet = new RepositoryServlet(repoManagerMock);
+
+ repositories = new URI[2];
+ repositories[0] = new URI("file:/tmp");
+ repositories[1] = new URI("file:/tmp/foo");
+
+ when(repoManagerMock.getRepositories()).thenReturn(repositories);
+ when(responseMock.getWriter()).thenReturn(responsePrintWriter);
+ }
+
+ @Test
+ public void doGetTest() throws ServletException, IOException, JDOMException {
+ repositoryServlet.doGet(null, responseMock);
+ SAXBuilder builder = new SAXBuilder();
+ Document request = builder.build(new ByteArrayInputStream(responseWriter.toString().getBytes()));
+ Element repo1 = (Element) request.getRootElement().getChildren().get(0);
+ Element repo2 = (Element) request.getRootElement().getChildren().get(1);
+
+ assertEquals(repositories[0].toString(), repo1.getChildText("uri"));
+ assertEquals(repositories[1].toString(), repo2.getChildText("uri"));
+ }
+
+ @Test
+ public void doValidDeleteTest() throws ServletException, IOException, JDOMException, URISyntaxException {
+ when(requestMock.getReader()).thenReturn(new BufferedReader(new StringReader(VALID_DELETE_CREATE_REQUEST)));
+ repositoryServlet.doDelete(requestMock, responseMock);
+
+ SAXBuilder builder = new SAXBuilder();
+ Document request = builder.build(new ByteArrayInputStream(responseWriter.toString().getBytes()));
+ Element repo = (Element) request.getRootElement().getChildren().get(0);
+ assertEquals(TEST_REPOSITORY_URI, repo.getChildText("uri"));
+ assertEquals("successful", repo.getChildText("status"));
+
+ verify(repoManagerMock).removeRepository(new URI(TEST_REPOSITORY_URI));
+ }
+
+ @Test
+ public void doValidDeleteInvalidUriTest() throws ServletException, IOException, JDOMException, URISyntaxException {
+ when(requestMock.getReader()).thenReturn(new BufferedReader(new StringReader(VALID_DELETE_REQUEST_INVALID_URI)));
+ repositoryServlet.doDelete(requestMock, responseMock);
+
+ SAXBuilder builder = new SAXBuilder();
+ Document request = builder.build(new ByteArrayInputStream(responseWriter.toString().getBytes()));
+ Element repo = (Element) request.getRootElement().getChildren().get(0);
+ assertEquals("not an uri", repo.getChildText("uri"));
+ assertEquals("failed", repo.getChildText("status"));
+ }
+
+ @Test
+ public void doInvalidDeleteTest() throws ServletException, IOException, JDOMException {
+ when(requestMock.getReader()).thenReturn(new BufferedReader(new StringReader("not valid :-)")));
+ repositoryServlet.doDelete(requestMock, responseMock);
+
+ verify(responseMock).sendError(HttpServletResponse.SC_BAD_REQUEST);
+ }
+
+ @Test
+ public void doInvalidCreateRemoteRepositoryTest() throws ServletException, IOException, JDOMException {
+ when(requestMock.getReader()).thenReturn(new BufferedReader(new StringReader("not valid :-)")));
+ // return stupid http method to break multiform-check in this test
+ when(requestMock.getMethod()).thenReturn("fooo");
+ repositoryServlet.doPost(requestMock, responseMock);
+
+ verify(responseMock).sendError(HttpServletResponse.SC_BAD_REQUEST);
+ }
+
+ @Test
+ public void doValidCreateRemoteRepositoryTest() throws ServletException, IOException, JDOMException,
+ URISyntaxException {
+ when(requestMock.getReader()).thenReturn(new BufferedReader(new StringReader(VALID_DELETE_CREATE_REQUEST)));
+ // return stupid http method to break multiform-check in this test
+ when(requestMock.getMethod()).thenReturn("fooo");
+
+ repositoryServlet.doPost(requestMock, responseMock);
+
+ SAXBuilder builder = new SAXBuilder();
+ Document request = builder.build(new ByteArrayInputStream(responseWriter.toString().getBytes()));
+ Element repo = (Element) request.getRootElement().getChildren().get(0);
+
+ assertEquals(TEST_REPOSITORY_URI, repo.getChildText("uri"));
+ assertEquals("successful", repo.getChildText("status"));
+
+ verify(repoManagerMock).addRepository(new URI(TEST_REPOSITORY_URI));
+ }
+
+ @Test
+ public void doInvalidMultipartUploadTest() throws ServletException, IOException {
+ when(requestMock.getMethod()).thenReturn("POST");
+ when(requestMock.getContentType()).thenReturn(ServletFileUpload.MULTIPART_FORM_DATA + ";NO_BOUNDARY!!!!!!");
+ repositoryServlet.doPost(requestMock, responseMock);
+ verify(responseMock).sendError(400);
+ }
+
+ @Test
+ public void doInvalidMultipartRequestTest() throws ServletException, IOException {
+ when(requestMock.getMethod()).thenReturn("POST");
+ when(requestMock.getContentType()).thenReturn(ServletFileUpload.MULTIPART_FORM_DATA + ";boundary=boundary");
+ when(requestMock.getInputStream()).thenReturn(new MockServletInputStream(null));
+ repositoryServlet.doPost(requestMock, responseMock);
+ verify(responseMock).sendError(400);
+ }
+
+ @Test
+ public void doValidMultipartUploadTest() throws Exception {
+ when(requestMock.getMethod()).thenReturn("POST");
+ when(requestMock.getContentType()).thenReturn(ServletFileUpload.MULTIPART_FORM_DATA + ";boundary=boundary");
+ when(requestMock.getInputStream()).thenReturn(new MockServletInputStream(new FileInputStream("fixtures/validRepositoryPackage.zip")));
+ URI uri = new URI("tmp://foo/bar");
+ when(repoManagerMock.addRepository(any(InputStream.class))).thenReturn(uri);
+ repositoryServlet.doPost(requestMock, responseMock);
+
+ SAXBuilder builder = new SAXBuilder();
+ Document request = builder.build(new ByteArrayInputStream(responseWriter.toString().getBytes()));
+ Element repo = (Element) request.getRootElement().getChildren().get(0);
+
+ assertEquals(uri.toString(), repo.getChildText("uri"));
+ assertEquals("successful", repo.getChildText("status"));
+ }
+
+ @Test
+ public void doValidMultipartUploadWithInvalidRepoTest() throws Exception {
+ when(requestMock.getMethod()).thenReturn("POST");
+ when(requestMock.getContentType()).thenReturn(ServletFileUpload.MULTIPART_FORM_DATA + ";boundary=boundary");
+ when(requestMock.getInputStream()).thenReturn(new MockServletInputStream(new FileInputStream("fixtures/invalidRepositoryPackage.zip")));
+ when(repoManagerMock.addRepository(any(InputStream.class))).thenThrow(new InvalidRepositoryException(""));
+ repositoryServlet.doPost(requestMock, responseMock);
+
+ SAXBuilder builder = new SAXBuilder();
+ Document request = builder.build(new ByteArrayInputStream(responseWriter.toString().getBytes()));
+ Element repo = (Element) request.getRootElement().getChildren().get(0);
+
+ URI uri = new URI("local");
+ assertEquals(uri.toString(), repo.getChildText("uri"));
+ assertEquals("failed", repo.getChildText("status"));
+ }
+}
diff --git a/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/util/MockServletInputStream.java b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/util/MockServletInputStream.java
new file mode 100644
index 0000000..0eca7f8
--- /dev/null
+++ b/tests/org.eclipse.rtp.tests.httpdeployer/src/org/eclipse/rtp/httpdeployer/util/MockServletInputStream.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sebastian Schmidt 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: Sebastian Schmidt - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rtp.httpdeployer.util;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import javax.servlet.ServletInputStream;
+
+public class MockServletInputStream extends ServletInputStream {
+
+ private static final String BOUNDARY = "boundary";
+ private final InputStream is;
+
+ public MockServletInputStream(InputStream is) throws IOException {
+ StringBuilder builder = new StringBuilder();
+ if (is != null) {
+ BufferedReader inputReader = new BufferedReader(new InputStreamReader(is));
+ builder.append("\r\n--" + BOUNDARY + "\r\n");
+ builder.append("Content-Disposition: form-data; name=\"name\"\r\n\r\n");
+ String current;
+ while ((current = inputReader.readLine()) != null) {
+ builder.append(current + "\n");
+ }
+
+ builder.append("\r\n--" + BOUNDARY + "--\r\n");
+ }
+
+ this.is = new ByteArrayInputStream(builder.toString().getBytes());
+ }
+
+ @Override
+ public int read() throws IOException {
+ return is.read();
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return is.read(b);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ return is.read(b, off, len);
+ }
+
+ @Override
+ public int available() throws IOException {
+ return is.available();
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ return is.skip(n);
+ }
+
+ @Override
+ public boolean markSupported() {
+ return is.markSupported();
+ }
+}