diff --git a/openbis/dist/server/jetty.xml b/openbis/dist/server/jetty.xml
index 21f54a0b1815e67470fa04c50164450ace1df47a..e781e6adce575cd0f9869bb2cead98c230a32f8b 100644
--- a/openbis/dist/server/jetty.xml
+++ b/openbis/dist/server/jetty.xml
@@ -56,6 +56,14 @@
               </New>
             </Arg>
           </Call>
+          <Call name="addAppProvider">
+            <Arg>
+              <New class="org.eclipse.jetty.deploy.providers.ContextProvider">
+                <Set name="monitoredDir"><Property name="jetty.home" default="." />/contexts</Set>
+                <Set name="scanInterval">1</Set>
+              </New>
+            </Arg>
+          </Call>
         </New>
       </Arg>
     </Call>
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/coreplugin/CorePluginsInjectingPropertyPlaceholderConfigurer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/coreplugin/CorePluginsInjectingPropertyPlaceholderConfigurer.java
index b9f04ef2e8b26df6988c55f5b051f63bd257fe08..94b47e491dec9ea56ef6112e070ae07f501ae28b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/coreplugin/CorePluginsInjectingPropertyPlaceholderConfigurer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/coreplugin/CorePluginsInjectingPropertyPlaceholderConfigurer.java
@@ -22,6 +22,7 @@ import java.util.Properties;
 import ch.systemsx.cisd.common.maintenance.MaintenanceTaskUtils;
 import ch.systemsx.cisd.common.spring.ExposablePropertyPlaceholderConfigurer;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.DataStoreServerBasedDataSourceProvider;
+import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.CustomImport;
 import ch.systemsx.cisd.openbis.generic.shared.coreplugin.CorePluginScanner.ScannerType;
 import ch.systemsx.cisd.openbis.generic.shared.coreplugin.CorePluginsInjector;
@@ -50,11 +51,14 @@ public class CorePluginsInjectingPropertyPlaceholderConfigurer extends
                         CustomImport.PropertyNames.CUSTOM_IMPORTS.getName());
         PluginType queryDatabases = new PluginType("query-databases", "query-databases");
         PluginType miscellaneous = new PluginType("miscellaneous", null);
-        PluginType webapps = new PluginType("webapps", "webapps");
+        PluginType webapps = new PluginType("webapps", BasicConstant.WEB_APPS_PROPERTY);
 
         new CorePluginsInjector(ScannerType.AS, new IPluginType[]
             { maintenanceTasks, customImports, queryDatabases, miscellaneous, dssDataSources,
                     webapps }).injectCorePlugins(properties);
+
+        // Inject the web apps into jetty
+        new JettyWebAppPluginInjector(properties).injectWebApps();
     }
 
     private PluginType createPluginTypeDssDataSources()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/coreplugin/JettyWebAppPluginInjector.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/coreplugin/JettyWebAppPluginInjector.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3f19202d6c178c77ee32433e7833094f00908d4
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/coreplugin/JettyWebAppPluginInjector.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.coreplugin;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.log4j.Logger;
+
+import ch.systemsx.cisd.common.filesystem.FileUtilities;
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.common.utilities.PropertyParametersUtil;
+import ch.systemsx.cisd.common.utilities.PropertyUtils;
+import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
+
+/**
+ * A class that injects web apps into jetty.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class JettyWebAppPluginInjector
+{
+    /**
+     * A utility class that generates a configuration file for a Jetty context for a webapp.
+     * 
+     * @author Chandrasekhar Ramakrishnan
+     */
+    public static class ContextConfiguration
+    {
+        private final String webapp;
+
+        private final Properties properties;
+
+        public ContextConfiguration(String webapp, Properties properties)
+        {
+            this.webapp = webapp;
+            this.properties = properties;
+        }
+
+        public String getConfigurationOrNull()
+        {
+
+            String resourceBase =
+                    properties.getProperty(JettyWebAppPluginInjector.WEB_APP_FOLDER_PROPERTY);
+            if (null == resourceBase)
+            {
+                JettyWebAppPluginInjector.operationLog.error("No configuration property for "
+                        + JettyWebAppPluginInjector.WEB_APP_FOLDER_PROPERTY
+                        + " was found in webapp properties :\n" + properties.toString());
+                return null;
+            }
+            String configuration =
+                    "<Configure class=\"org.eclipse.jetty.server.handler.ContextHandler\">\n"
+                            + "  <Call class=\"org.eclipse.jetty.util.log.Log\" name=\"debug\"><Arg>Configure ["
+                            + webapp
+                            + "] webapp</Arg></Call>\n"
+                            + "  <Set name=\"contextPath\">/"
+                            + webapp
+                            + "</Set>\n"
+                            + "  <Set name=\"resourceBase\">"
+                            + resourceBase
+                            + "</Set>\n"
+                            + "  <Set name=\"handler\">\n"
+                            + "    <New class=\"org.eclipse.jetty.server.handler.ResourceHandler\">\n"
+                            + "      <Set name=\"welcomeFiles\">\n"
+                            + "        <Array type=\"String\">\n"
+                            + "          <Item>index.html</Item>\n" + "        </Array>\n"
+                            + "      </Set>\n"
+                            + "      <Set name=\"cacheControl\">max-age=3600,public</Set>\n"
+                            + "    </New>\n" + "  </Set>\n" + "</Configure>";
+
+            return configuration;
+        }
+    }
+
+    // This is the folder referenced in jetty.xml. It must have the same name as in the
+    // jetty.xml configuration file.
+    private static final String CONTEXT_FOLDER = "contexts";
+
+    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
+            JettyWebAppPluginInjector.class);
+
+    private final List<String> webapps;
+
+    private final Map<String, Properties> webappProperties;
+
+    // This is initialized in ensureContextFolderExists and is invalid before that
+    // method runs
+    private File contextsFolder = null;
+
+    public static final String WEB_APP_FOLDER_PROPERTY = "webapp-folder";
+
+    private static Map<String, Properties> extractWebappProperties(Properties props,
+            List<String> webapps)
+    {
+        HashMap<String, Properties> map = new HashMap<String, Properties>();
+
+        for (String webapp : webapps)
+        {
+            Properties webappProperties =
+                    PropertyParametersUtil.extractSingleSectionProperties(props, webapp, false)
+                            .getProperties();
+            map.put(webapp, webappProperties);
+        }
+        return map;
+    }
+
+    public JettyWebAppPluginInjector(Properties props)
+    {
+        List<String> appList =
+                PropertyUtils.tryGetListInOriginalCase(props, BasicConstant.WEB_APPS_PROPERTY);
+        webapps = (null == appList) ? Collections.<String> emptyList() : appList;
+        webappProperties = extractWebappProperties(props, webapps);
+    }
+
+    public void injectWebApps()
+    {
+        logWebappsToInject();
+
+        // Leave if there is nothing to do
+        if (webapps.size() < 1)
+        {
+            return;
+        }
+        if (false == isRunningUnderJetty())
+        {
+            // We are not running in Jetty. Log and then get out.
+            operationLog.error("Not running under jetty. Cannot inject webapps.");
+            return;
+        }
+        if (false == ensureContextFolderExists())
+        {
+            operationLog.error("Could not create folder " + contextsFolder.getAbsolutePath()
+                    + ". Cannot inject webapps.");
+            return;
+        }
+        for (String webapp : webapps)
+        {
+            injectWebapp(webapp, webappProperties.get(webapp));
+        }
+    }
+
+    private void logWebappsToInject()
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Found " + webapps.size());
+        if (1 == webapps.size())
+        {
+            sb.append(" webapp");
+        } else
+        {
+            sb.append(" webapps");
+        }
+        sb.append(" to inject.");
+
+        operationLog.info(sb.toString());
+    }
+
+    private boolean ensureContextFolderExists()
+    {
+        // This must be non-null because isRunningUnderJetty is true
+        String jettyHomePath = System.getProperty("jetty.home");
+        contextsFolder = new File(jettyHomePath, CONTEXT_FOLDER);
+        if (false == contextsFolder.exists())
+        {
+            return contextsFolder.mkdir();
+        }
+        return true;
+    }
+
+    private boolean isRunningUnderJetty()
+    {
+        return null != System.getProperty("jetty.home");
+    }
+
+    private void injectWebapp(String webapp, Properties props)
+    {
+        String webappDisplayName = webapp;
+        operationLog.info("Injecting webapp [" + webappDisplayName + "]");
+        ContextConfiguration config = new ContextConfiguration(webappDisplayName, props);
+        File contextConfig = new File(contextsFolder, webappDisplayName + ".xml");
+        String configContent = config.getConfigurationOrNull();
+        if (null != configContent)
+        {
+            FileUtilities.writeToFile(contextConfig, configContent);
+        }
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java
index 99a2e7ab106683e6fa26993492076493da35836c..831d53ff2f867e4b174aaf374358c9cd300bb3ff 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java
@@ -114,6 +114,8 @@ public class BasicConstant
 
     public static final String DATA_SET_UPLOAD_CLIENT_PATH = "data-set-uploader-launch.jnlp";
 
+    public static final String WEB_APPS_PROPERTY = "webapps";
+
     private BasicConstant()
     {
     }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/coreplugin/CorePluginsInjectorTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/coreplugin/CorePluginsInjectorTest.java
index a28c150a85dca4bdf0e7a86740a3f04c2570283e..71f5555afd51d4cb07a0f14047cfd5ad7e4bf252 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/coreplugin/CorePluginsInjectorTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/coreplugin/CorePluginsInjectorTest.java
@@ -44,6 +44,10 @@ import ch.systemsx.cisd.common.logging.ISimpleLogger;
 import ch.systemsx.cisd.common.logging.LogLevel;
 import ch.systemsx.cisd.common.test.RecordingMatcher;
 import ch.systemsx.cisd.common.utilities.ExtendedProperties;
+import ch.systemsx.cisd.common.utilities.PropertyParametersUtil;
+import ch.systemsx.cisd.common.utilities.PropertyUtils;
+import ch.systemsx.cisd.openbis.generic.server.coreplugin.JettyWebAppPluginInjector;
+import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
 import ch.systemsx.cisd.openbis.generic.shared.coreplugin.CorePluginScanner.ScannerType;
 
 /**
@@ -354,10 +358,36 @@ public class CorePluginsInjectorTest extends AbstractFileSystemTestCase
 
         injector.injectCorePlugins(properties);
 
-        assertEquals("example-webapp", properties.getProperty("webapps"));
-        String webappFolder = properties.getProperty("example-webapp.webapp-folder");
+        List<String> appList =
+                PropertyUtils.tryGetListInOriginalCase(properties, BasicConstant.WEB_APPS_PROPERTY);
+        assertEquals(1, appList.size());
+        assertEquals("example-webapp", appList.get(0));
+        Properties exampleWebappProperties =
+                PropertyParametersUtil.extractSingleSectionProperties(properties, appList.get(0),
+                        false).getProperties();
+        String webappFolder =
+                exampleWebappProperties
+                        .getProperty(JettyWebAppPluginInjector.WEB_APP_FOLDER_PROPERTY);
         assertEquals(webapps.toString() + "/example-webapp/html", webappFolder);
 
+        JettyWebAppPluginInjector.ContextConfiguration configuration =
+                new JettyWebAppPluginInjector.ContextConfiguration("example-webapp",
+                        exampleWebappProperties);
+        String expectedConfiguration =
+                "<Configure class=\"org.eclipse.jetty.server.handler.ContextHandler\">\n"
+                        + "  <Call class=\"org.eclipse.jetty.util.log.Log\" name=\"debug\"><Arg>Configure [example-webapp] webapp</Arg></Call>\n"
+                        + "  <Set name=\"contextPath\">/example-webapp</Set>\n"
+                        + "  <Set name=\"resourceBase\">targets/unit-test-wd/ch.systemsx.cisd.openbis.generic.shared.coreplugin.CorePluginsInjectorTest/core-plugins/screening/1/dss/webapps/example-webapp/html</Set>\n"
+                        + "  <Set name=\"handler\">\n"
+                        + "    <New class=\"org.eclipse.jetty.server.handler.ResourceHandler\">\n"
+                        + "      <Set name=\"welcomeFiles\">\n"
+                        + "        <Array type=\"String\">\n"
+                        + "          <Item>index.html</Item>\n" + "        </Array>\n"
+                        + "      </Set>\n"
+                        + "      <Set name=\"cacheControl\">max-age=3600,public</Set>\n"
+                        + "    </New>\n" + "  </Set>\n" + "</Configure>";
+        assertEquals(expectedConfiguration, configuration.getConfigurationOrNull());
+
         context.assertIsSatisfied();
     }