Merge "Add JettyStaticResourceServer to policy-endpoints"
diff --git a/policy-endpoints/pom.xml b/policy-endpoints/pom.xml
index d70399c..a79bd59 100644
--- a/policy-endpoints/pom.xml
+++ b/policy-endpoints/pom.xml
@@ -2,7 +2,7 @@
   ============LICENSE_START=======================================================
    Copyright (C) 2018 Ericsson. All rights reserved.
    Modifications Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved.
-   Modifications Copyright (C) 2019 Nordix Foundation.
+   Modifications Copyright (C) 2019-2020 Nordix Foundation.
   ================================================================================
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -40,6 +40,8 @@
         <cambria.version>1.2.1-oss</cambria.version>
         <http.client.version>4.5.5</http.client.version>
         <http.core.version>4.4.4</http.core.version>
+        <!--This is required since oparent does not include jetty-servlets. TBD get oparent updated -->
+        <jetty.version>9.4.24.v20191120</jetty.version>
     </properties>
 
     <dependencies>
@@ -109,6 +111,12 @@
         </dependency>
 
         <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-servlets</artifactId>
+            <version>${jetty.version}</version>
+        </dependency>
+
+        <dependency>
             <groupId>org.glassfish.jersey.core</groupId>
             <artifactId>jersey-server</artifactId>
         </dependency>
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServer.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServer.java
index 030bf93..49dfea0 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServer.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServer.java
@@ -102,7 +102,7 @@
     void addServletPackage(String servletPath, String restPackage);
 
     /**
-     * Add org.eclipse.jetty.servlet.DefaultServlet into context
+     * Add a static resource path to manage static resources.
      *
      * @param servletPath servlet path
      * @param resourceBase static resources folder
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServerFactory.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServerFactory.java
index 0c30e3e..90c0db2 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServerFactory.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServerFactory.java
@@ -3,13 +3,14 @@
  * policy-endpoints
  * ================================================================================
  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2020 Nordix Foundation.
  * ================================================================================
  * 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.
@@ -29,8 +30,8 @@
 public interface HttpServletServerFactory {
 
     /**
-     * Builds an http or https server with support for servlets.
-     * 
+     * Builds an http or https rest server with support for servlets.
+     *
      * @param name name
      * @param https use secured http over tls connection
      * @param host binding host
@@ -45,7 +46,7 @@
         boolean managed);
 
     /**
-     * Builds an http server with support for servlets.
+     * Builds an http rest server with support for servlets.
      *
      * @param name name
      * @param host binding host
@@ -59,8 +60,8 @@
     HttpServletServer build(String name, String host, int port, String contextPath, boolean swagger, boolean managed);
 
     /**
-     * Build a list of http servers per properties.
-     * 
+     * Build a list of http rest servers per properties.
+     *
      * @param properties properties based configuration
      * @return list of http servers
      * @throws IllegalArgumentException when invalid parameters are provided
@@ -68,8 +69,23 @@
     List<HttpServletServer> build(Properties properties);
 
     /**
+     * Builds an http or https server to manage static resources.
+     *
+     * @param name name
+     * @param https use secured http over tls connection
+     * @param host binding host
+     * @param port port
+     * @param contextPath server base path
+     * @param managed is it managed by infrastructure
+     * @return http server
+     * @throws IllegalArgumentException when invalid parameters are provided
+     */
+    HttpServletServer buildStaticResourceServer(String name, boolean https, String host, int port, String contextPath,
+            boolean managed);
+
+    /**
      * Gets a server based on the port.
-     * 
+     *
      * @param port port
      * @return http server
      */
@@ -77,14 +93,14 @@
 
     /**
      * Provides an inventory of servers.
-     * 
+     *
      * @return inventory of servers
      */
     List<HttpServletServer> inventory();
 
     /**
      * Destroys server bound to a port.
-     * 
+     *
      * @param port the port the server is bound to
      */
     void destroy(int port);
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/IndexedHttpServletServerFactory.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/IndexedHttpServletServerFactory.java
index 517ad20..445a351 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/IndexedHttpServletServerFactory.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/IndexedHttpServletServerFactory.java
@@ -3,6 +3,7 @@
  * ONAP Policy Engine - Common Modules
  * ================================================================================
  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2020 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,6 +27,7 @@
 import java.util.Properties;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.common.endpoints.http.server.internal.JettyJerseyServer;
+import org.onap.policy.common.endpoints.http.server.internal.JettyStaticResourceServer;
 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
 import org.onap.policy.common.endpoints.utils.PropertyUtils;
 import org.slf4j.Logger;
@@ -88,6 +90,23 @@
         return serviceList;
     }
 
+
+
+    @Override
+    public HttpServletServer buildStaticResourceServer(String name, boolean https, String host, int port,
+            String contextPath, boolean managed) {
+        if (servers.containsKey(port)) {
+            return servers.get(port);
+        }
+
+        JettyStaticResourceServer server = new JettyStaticResourceServer(name, https, host, port, contextPath);
+        if (managed) {
+            servers.put(port, server);
+        }
+
+        return server;
+    }
+
     private void addService(ArrayList<HttpServletServer> serviceList, String serviceName, Properties properties) {
 
         String servicePrefix = PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + serviceName;
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyJerseyServer.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyJerseyServer.java
index 462f079..fb43ce4 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyJerseyServer.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyJerseyServer.java
@@ -23,8 +23,8 @@
 
 import io.swagger.jersey.config.JerseyJaxrsConfig;
 import java.util.HashMap;
+import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
-import org.eclipse.jetty.servlet.DefaultServlet;
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.glassfish.jersey.server.ServerProperties;
 import org.onap.policy.common.utils.network.NetworkUtil;
@@ -74,34 +74,14 @@
             "io.swagger.jaxrs.listing.ApiListingResource," + "io.swagger.jaxrs.listing.SwaggerSerializers";
 
     /**
-     * Servlet Holder Resource Base Path.
-     */
-    protected static final String SERVLET_HOLDER_RESOURCE_BASE = "resourceBase";
-
-    /**
-     * Servlet Holder Directory Allowed.
-     */
-    protected static final String SERVLET_HOLDER_DIR_ALLOWED = "dirAllowed";
-
-    /**
-     * Servlet Holder Path Information Only.
-     */
-    protected static final String SERVLET_HOLDER_PATH_INFO_ONLY = "pathInfoOnly";
-
-    /**
      * Logger.
      */
     protected static Logger logger = LoggerFactory.getLogger(JettyJerseyServer.class);
 
     /**
-     * Container for jersey servlets.
+     * Container for servlets.
      */
-    protected HashMap<String, ServletHolder> jerseyServlets = new HashMap<>();
-
-    /**
-     * Container for default servlets.
-     */
-    protected HashMap<String, ServletHolder> defaultServlets = new HashMap<>();
+    protected final Map<String, ServletHolder> servlets = new HashMap<>();
 
     /**
      * Swagger ID.
@@ -166,9 +146,9 @@
      *
      * @throws IllegalArgumentException if invalid arguments are provided
      */
-    protected synchronized ServletHolder getJerseyServlet(String servletPath) {
+    protected synchronized ServletHolder getServlet(String servletPath) {
 
-        return jerseyServlets.computeIfAbsent(servletPath, key -> {
+        return servlets.computeIfAbsent(servletPath, key -> {
 
             ServletHolder jerseyServlet =
                     context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, servletPath);
@@ -178,19 +158,6 @@
         });
     }
 
-    /**
-     * Retrieves cached default servlet based on servlet path.
-     *
-     * @param servletPath servlet path
-     * @return the jetty servlet holder
-     *
-     * @throws IllegalArgumentException if invalid arguments are provided
-     */
-    protected synchronized ServletHolder getDefaultServlet(String servPath) {
-
-        return defaultServlets.computeIfAbsent(servPath, key -> context.addServlet(DefaultServlet.class, servPath));
-    }
-
     @Override
     public synchronized void addServletPackage(String servletPath, String restPackage) {
         String servPath = servletPath;
@@ -202,7 +169,7 @@
             servPath = "/*";
         }
 
-        ServletHolder jerseyServlet = this.getJerseyServlet(servPath);
+        ServletHolder jerseyServlet = this.getServlet(servPath);
 
         initStandardParams(jerseyServlet);
 
@@ -232,7 +199,7 @@
             servletPath = "/*";
         }
 
-        ServletHolder jerseyServlet = this.getJerseyServlet(servletPath);
+        ServletHolder jerseyServlet = this.getServlet(servletPath);
 
         initStandardParams(jerseyServlet);
 
@@ -251,28 +218,6 @@
         }
     }
 
-    @Override
-    public synchronized void addServletResource(String servletPath, String resoureBase) {
-
-        if (StringUtils.isBlank(resoureBase)) {
-            throw new IllegalArgumentException("No resourceBase provided");
-        }
-
-        if (servletPath == null || servletPath.isEmpty()) {
-            servletPath = "/*";
-        }
-
-        ServletHolder defaultServlet = this.getDefaultServlet(servletPath);
-
-        defaultServlet.setInitParameter(SERVLET_HOLDER_RESOURCE_BASE, resoureBase);
-        defaultServlet.setInitParameter(SERVLET_HOLDER_DIR_ALLOWED, "false");
-        defaultServlet.setInitParameter(SERVLET_HOLDER_PATH_INFO_ONLY, "true");
-
-        if (logger.isDebugEnabled()) {
-            logger.debug("{}: added REST class: {}", this, defaultServlet.dump());
-        }
-    }
-
     /**
      * Adds "standard" parameters to the initParameter set. Sets swagger parameters, if specified, and sets the class
      * provider property. This can be invoked multiple times, but only the first actually causes any changes to the
@@ -312,9 +257,8 @@
     @Override
     public String toString() {
         StringBuilder builder = new StringBuilder();
-        builder.append("JettyJerseyServer [Jerseyservlets=").append(jerseyServlets).append(", Defaultservlets=")
-                .append(defaultServlets).append(", swaggerId=").append(swaggerId).append(", toString()=")
-                .append(super.toString()).append("]");
+        builder.append("JettyJerseyServer [Jerseyservlets=").append(servlets).append(", swaggerId=").append(swaggerId)
+                .append(", toString()=").append(super.toString()).append("]");
         return builder.toString();
     }
 }
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java
index 133adad..f7f2fc1 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java
@@ -3,6 +3,7 @@
  * ONAP
  * ================================================================================
  * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019-2020 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -64,6 +65,8 @@
      */
     private static Logger logger = LoggerFactory.getLogger(JettyServletServer.class);
 
+    private static final String NOT_SUPPORTED = " is not supported on this type of jetty server";
+
     /**
      * Server name.
      */
@@ -495,6 +498,26 @@
     }
 
     @Override
+    public void setSerializationProvider(String provider) {
+        throw new UnsupportedOperationException("setSerializationProvider()" + NOT_SUPPORTED);
+    }
+
+    @Override
+    public void addServletClass(String servletPath, String restClass) {
+        throw new UnsupportedOperationException("addServletClass()" + NOT_SUPPORTED);
+    }
+
+    @Override
+    public void addServletPackage(String servletPath, String restPackage) {
+        throw new UnsupportedOperationException("addServletPackage()" + NOT_SUPPORTED);
+    }
+
+    @Override
+    public void addServletResource(String servletPath, String resourceBase) {
+        throw new UnsupportedOperationException("addServletResource()" + NOT_SUPPORTED);
+    }
+
+    @Override
     public String toString() {
         StringBuilder builder = new StringBuilder();
         builder.append("JettyServer [name=").append(name).append(", host=").append(host).append(", port=").append(port)
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyStaticResourceServer.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyStaticResourceServer.java
new file mode 100644
index 0000000..15d9990
--- /dev/null
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyStaticResourceServer.java
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.endpoints.http.server.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+import lombok.ToString;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Jetty Server that uses DefaultServlets to support web static resources management.
+ */
+@ToString
+public class JettyStaticResourceServer extends JettyServletServer {
+
+    /**
+     * Servlet Holder Resource Base Path.
+     */
+    protected static final String SERVLET_HOLDER_RESOURCE_BASE = "resourceBase";
+
+    /**
+     * Servlet Holder Directory Allowed.
+     */
+    protected static final String SERVLET_HOLDER_DIR_ALLOWED = "dirAllowed";
+
+    /**
+     * Servlet Holder Path Information Only.
+     */
+    protected static final String SERVLET_HOLDER_PATH_INFO_ONLY = "pathInfoOnly";
+
+    /**
+     * Logger.
+     */
+    protected static Logger logger = LoggerFactory.getLogger(JettyStaticResourceServer.class);
+
+    /**
+     * Container for default servlets.
+     */
+    protected final Map<String, ServletHolder> servlets = new HashMap<>();
+
+    /**
+     * Constructor.
+     *
+     * @param name name
+     * @param https enable https?
+     * @param host host server host
+     * @param port port server port
+     * @param contextPath context path
+     *
+     * @throws IllegalArgumentException in invalid arguments are provided
+     */
+    public JettyStaticResourceServer(String name, boolean https, String host, int port, String contextPath) {
+
+        super(name, https, host, port, contextPath);
+    }
+
+    /**
+     * Retrieves cached default servlet based on servlet path.
+     *
+     * @param servletPath servlet path
+     * @return the jetty servlet holder
+     *
+     * @throws IllegalArgumentException if invalid arguments are provided
+     */
+    protected synchronized ServletHolder getDefaultServlet(String servPath) {
+
+        return servlets.computeIfAbsent(servPath, key -> context.addServlet(DefaultServlet.class, servPath));
+    }
+
+    @Override
+    public synchronized void addServletResource(String servletPath, String resoureBase) {
+
+        if (StringUtils.isBlank(resoureBase)) {
+            throw new IllegalArgumentException("No resourceBase provided");
+        }
+
+        if (servletPath == null || servletPath.isEmpty()) {
+            servletPath = "/*";
+        }
+
+        ServletHolder defaultServlet = this.getDefaultServlet(servletPath);
+
+        defaultServlet.setInitParameter(SERVLET_HOLDER_RESOURCE_BASE, resoureBase);
+        defaultServlet.setInitParameter(SERVLET_HOLDER_DIR_ALLOWED, "false");
+        defaultServlet.setInitParameter(SERVLET_HOLDER_PATH_INFO_ONLY, "true");
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("{}: added Default Servlet: {}", this, defaultServlet.dump());
+        }
+    }
+}
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java
index 0aec411..e202b11 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java
@@ -3,6 +3,7 @@
  * ONAP
  * ================================================================================
  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2020 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,12 +21,15 @@
 
 package org.onap.policy.common.endpoints.http.server.test;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.catchThrowable;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import com.google.gson.Gson;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.HttpURLConnection;
@@ -476,6 +480,103 @@
         assertTrue(HttpServletServerFactoryInstance.getServerFactory().inventory().isEmpty());
     }
 
+    @Test
+    public void testSingleStaticResourceServer() throws Exception {
+        logger.info("-- testSingleStaticResourceServer() --");
+
+        HttpServletServer staticServer = HttpServletServerFactoryInstance.getServerFactory()
+                .buildStaticResourceServer("Static Resources Server", false, LOCALHOST, port, "/", true);
+        Throwable thrown = catchThrowable(() -> staticServer.addServletResource("/*", null));
+        assertThat(thrown).isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("No resourceBase provided");
+
+        staticServer.addServletResource(null,
+                HttpServerTest.class.getClassLoader().getResource("webapps/root").toExternalForm());
+
+        thrown = catchThrowable(() -> staticServer.addServletClass("/*", RestEchoService.class.getName()));
+        assertThat(thrown).isInstanceOf(UnsupportedOperationException.class)
+                .hasMessageContaining("is not supported on this type of jetty server");
+
+        thrown = catchThrowable(() -> staticServer.addServletPackage("/api/*", this.getClass().getPackage().getName()));
+        assertThat(thrown).isInstanceOf(UnsupportedOperationException.class)
+                .hasMessageContaining("is not supported on this type of jetty server");
+
+        thrown = catchThrowable(() -> staticServer.setSerializationProvider(MyGsonProvider.class.getName()));
+        assertThat(thrown).isInstanceOf(UnsupportedOperationException.class)
+                .hasMessageContaining("is not supported on this type of jetty server");
+
+        staticServer.waitedStart(5000);
+
+        assertTrue(HttpServletServerFactoryInstance.getServerFactory().get(port).isAlive());
+        assertEquals(1, HttpServletServerFactoryInstance.getServerFactory().inventory().size());
+
+        String response = http(portUrl);
+        assertThat(response).contains("Test Jetty Static Resources Root");
+
+        HttpServletServerFactoryInstance.getServerFactory().destroy(port);
+        assertEquals(0, HttpServletServerFactoryInstance.getServerFactory().inventory().size());
+    }
+
+    @Test
+    public void testMultiStaticResourceServer() throws Exception {
+        logger.info("-- testMultiStaticResourceServer() --");
+
+        HttpServletServer staticResourceServer = HttpServletServerFactoryInstance.getServerFactory()
+                .buildStaticResourceServer("Static Resources Server", false, LOCALHOST, port, "/", true);
+        staticResourceServer.addServletResource("/root/*",
+                HttpServerTest.class.getClassLoader().getResource("webapps/root").toExternalForm());
+        staticResourceServer.addServletResource("/alt-root/*",
+                HttpServerTest.class.getClassLoader().getResource("webapps/alt-root").toExternalForm());
+        staticResourceServer.waitedStart(5000);
+
+        assertTrue(HttpServletServerFactoryInstance.getServerFactory().get(port).isAlive());
+        assertEquals(1, HttpServletServerFactoryInstance.getServerFactory().inventory().size());
+
+        String response = http(portUrl + "/root/");
+        assertThat(response).contains("Test Jetty Static Resources Root");
+
+        response = http(portUrl + "/alt-root/");
+        assertThat(response).contains("Test Jetty Static Resources Alt-Root");
+
+        HttpServletServerFactoryInstance.getServerFactory().destroy(port);
+        assertEquals(0, HttpServletServerFactoryInstance.getServerFactory().inventory().size());
+    }
+
+    @Test
+    public void testMultiTypesServer() throws Exception {
+        logger.info("-- testMultiTypesServer() --");
+
+        HttpServletServer staticResourceServer = HttpServletServerFactoryInstance.getServerFactory()
+                .buildStaticResourceServer("Static Resources Server", false, LOCALHOST, port, "/", true);
+        staticResourceServer.addServletResource("/root/*",
+                HttpServerTest.class.getClassLoader().getResource("webapps/root").toExternalForm());
+        staticResourceServer.waitedStart(5000);
+
+        int port2 = port + 1;
+        HttpServletServer jerseyServer =
+                HttpServletServerFactoryInstance.getServerFactory().build("echo", LOCALHOST, port2, "/", false, true);
+        jerseyServer.addServletPackage("/api/*", this.getClass().getPackage().getName());
+
+        Throwable thrown = catchThrowable(() -> jerseyServer.addServletResource("/root/*",
+                HttpServerTest.class.getClassLoader().getResource("webapps/root").toExternalForm()));
+        assertThat(thrown).isInstanceOf(UnsupportedOperationException.class)
+                .hasMessageContaining("is not supported on this type of jetty server");
+
+        jerseyServer.waitedStart(5000);
+
+        assertTrue(HttpServletServerFactoryInstance.getServerFactory().get(port).isAlive());
+        assertEquals(2, HttpServletServerFactoryInstance.getServerFactory().inventory().size());
+
+        String response = http(portUrl + "/root/");
+        assertThat(response).contains("Test Jetty Static Resources Root");
+
+        response = http(LOCALHOST_PREFIX + port2 + "/api" + JUNIT_ECHO_HELLO);
+        assertEquals(HELLO, response);
+
+        HttpServletServerFactoryInstance.getServerFactory().destroy();
+        assertEquals(0, HttpServletServerFactoryInstance.getServerFactory().inventory().size());
+    }
+
     /**
      * performs an http request.
      *
diff --git a/policy-endpoints/src/test/resources/webapps/alt-root/index.html b/policy-endpoints/src/test/resources/webapps/alt-root/index.html
new file mode 100644
index 0000000..0948ceb
--- /dev/null
+++ b/policy-endpoints/src/test/resources/webapps/alt-root/index.html
@@ -0,0 +1,28 @@
+<!--
+  ============LICENSE_START=======================================================
+   Copyright (C) 2020 Nordix Foundation.
+  ================================================================================
+  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.
+
+  SPDX-License-Identifier: Apache-2.0
+  ============LICENSE_END=========================================================
+-->
+
+<html>
+    <head>
+        <title>Hello World</title>
+    </head>
+    <body>
+        <h4>Test Jetty Static Resources Alt-Root</h4>
+    </body>
+</html>
\ No newline at end of file
diff --git a/policy-endpoints/src/test/resources/webapps/root/index.html b/policy-endpoints/src/test/resources/webapps/root/index.html
new file mode 100644
index 0000000..a7cc120
--- /dev/null
+++ b/policy-endpoints/src/test/resources/webapps/root/index.html
@@ -0,0 +1,28 @@
+<!--
+  ============LICENSE_START=======================================================
+   Copyright (C) 2020 Nordix Foundation.
+  ================================================================================
+  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.
+
+  SPDX-License-Identifier: Apache-2.0
+  ============LICENSE_END=========================================================
+-->
+
+<html>
+    <head>
+        <title>Hello World</title>
+    </head>
+    <body>
+        <h4>Test Jetty Static Resources Root</h4>
+    </body>
+</html>
\ No newline at end of file