Copy PapRestServer to policy/common

Copied and renamed the class to RestServer.  Also modified it to
derive from ServiceManagerContainer.
Added getName() method to HttpServletServer, which facilitated
the refactoring.
Renamed "controllers" to "providers".

Change-Id: I905166e41063e3fe84e356fd6c4a91ca9d4cb8a6
Issue-ID: POLICY-1652
Signed-off-by: Jim Hahn <jrh3@att.com>
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 73b1e54..0adf782 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
@@ -26,6 +26,12 @@
  * Http Servlet Server interface.
  */
 public interface HttpServletServer extends Startable {
+    /**
+     * Gets the server name.
+     *
+     * @return the server name
+     */
+    String getName();
 
     /**
      * Get the port.
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/RestServer.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/RestServer.java
new file mode 100644
index 0000000..1f7a921
--- /dev/null
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/RestServer.java
@@ -0,0 +1,140 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ *  Modifications Copyright (C) 2019 AT&T Intellectual Property.
+ * ================================================================================
+ * 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;
+
+import java.util.List;
+import java.util.Properties;
+import org.onap.policy.common.endpoints.http.server.aaf.AafAuthFilter;
+import org.onap.policy.common.endpoints.parameters.RestServerParameters;
+import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.common.gson.GsonMessageBodyHandler;
+import org.onap.policy.common.utils.services.ServiceManagerContainer;
+
+/**
+ * Class to manage life cycle of a rest server.
+ *
+ * @author Ram Krishna Verma (ram.krishna.verma@est.tech)
+ */
+public class RestServer extends ServiceManagerContainer {
+
+    /**
+     * Factory used to access objects. May be overridden by junit tests.
+     */
+    private static Factory factory = new Factory();
+
+    private final List<HttpServletServer> servers;
+
+    /**
+     * Constructs the object.
+     *
+     * @param restServerParameters the rest server parameters
+     * @param aafFilter class of object to use to filter AAF requests, or {@code null}
+     * @param jaxrsProviders classes providing the services
+     */
+    public RestServer(final RestServerParameters restServerParameters, Class<? extends AafAuthFilter> aafFilter,
+                    Class<?>... jaxrsProviders) {
+
+        if (jaxrsProviders.length == 0) {
+            throw new IllegalArgumentException("no providers specified");
+        }
+
+        this.servers = factory.getServerFactory()
+                        .build(getServerProperties(restServerParameters, getProviderClassNames(jaxrsProviders)));
+
+        for (HttpServletServer server : this.servers) {
+            if (aafFilter != null && server.isAaf()) {
+                server.addFilterClass(null, aafFilter.getName());
+            }
+
+            addAction("REST " + server.getName(), server::start, server::stop);
+        }
+    }
+
+    /**
+     * Creates the server properties object using restServerParameters.
+     *
+     * @param restServerParameters the rest server parameters
+     * @param names comma-separated list of classes providing the services
+     *
+     * @return the properties object
+     */
+    private Properties getServerProperties(RestServerParameters restServerParameters, String names) {
+        final Properties props = new Properties();
+        props.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES, restServerParameters.getName());
+
+        final String svcpfx =
+                        PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + restServerParameters.getName();
+
+        props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, restServerParameters.getHost());
+        props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX,
+                        Integer.toString(restServerParameters.getPort()));
+        props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, names);
+        props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "false");
+        props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, "true");
+        props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX,
+                        restServerParameters.getUserName());
+        props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX,
+                        restServerParameters.getPassword());
+        props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX,
+                        String.valueOf(restServerParameters.isHttps()));
+        props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_AAF_SUFFIX,
+                        String.valueOf(restServerParameters.isAaf()));
+        props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER,
+                        GsonMessageBodyHandler.class.getName());
+        return props;
+    }
+
+    /**
+     * Gets the provider class names, as a comma-separated string.
+     *
+     * @param jaxrsProviders classes providing the services
+     * @return the provider class names
+     */
+    private String getProviderClassNames(Class<?>[] jaxrsProviders) {
+        StringBuilder names = new StringBuilder();
+
+        for (Class<?> prov : jaxrsProviders) {
+            if (names.length() > 0) {
+                names.append(',');
+            }
+
+            names.append(prov.getName());
+        }
+
+        return names.toString();
+    }
+
+    @Override
+    public String toString() {
+        return "RestServer [servers=" + servers + "]";
+    }
+
+    /**
+     * Factory used to access objects.
+     */
+    public static class Factory {
+
+        public HttpServletServerFactory getServerFactory() {
+            return HttpServletServerFactoryInstance.getServerFactory();
+        }
+    }
+}
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestServerTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestServerTest.java
new file mode 100644
index 0000000..3f67173
--- /dev/null
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestServerTest.java
@@ -0,0 +1,223 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.endpoints.http.server.test;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Properties;
+import javax.servlet.http.HttpServletRequest;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.common.endpoints.http.server.HttpServletServerFactory;
+import org.onap.policy.common.endpoints.http.server.RestServer;
+import org.onap.policy.common.endpoints.http.server.RestServer.Factory;
+import org.onap.policy.common.endpoints.http.server.aaf.AafAuthFilter;
+import org.onap.policy.common.endpoints.parameters.RestServerParameters;
+import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.common.gson.GsonMessageBodyHandler;
+import org.powermock.reflect.Whitebox;
+
+public class RestServerTest {
+    private static final String SERVER1 = "my-server-A";
+    private static final String SERVER2 = "my-server-B";
+    private static final String FACTORY_FIELD = "factory";
+    private static final String HOST = "my-host";
+    private static final String PARAM_NAME = "my-param";
+    private static final String PASS = "my-pass";
+    private static final Integer PORT = 9876;
+    private static final String USER = "my-user";
+    private static Factory saveFactory;
+
+    private RestServer rest;
+    private HttpServletServer server1;
+    private HttpServletServer server2;
+    private Factory factory;
+    private HttpServletServerFactory serverFactory;
+    private RestServerParameters params;
+
+    @BeforeClass
+    public static void setUpBeforeClass() {
+        saveFactory = Whitebox.getInternalState(RestServer.class, FACTORY_FIELD);
+    }
+
+    @AfterClass
+    public static void tearDownAfterClass() {
+        Whitebox.setInternalState(RestServer.class, FACTORY_FIELD, saveFactory);
+    }
+
+    /**
+     * Initializes mocks.
+     */
+    @Before
+    public void setUp() {
+        server1 = mock(HttpServletServer.class);
+        server2 = mock(HttpServletServer.class);
+        factory = mock(Factory.class);
+        serverFactory = mock(HttpServletServerFactory.class);
+        params = mock(RestServerParameters.class);
+
+        when(factory.getServerFactory()).thenReturn(serverFactory);
+        when(serverFactory.build(any())).thenReturn(Arrays.asList(server1, server2));
+
+        when(server1.getName()).thenReturn(SERVER1);
+        when(server2.getName()).thenReturn(SERVER2);
+
+        when(params.getHost()).thenReturn(HOST);
+        when(params.getName()).thenReturn(PARAM_NAME);
+        when(params.getPassword()).thenReturn(PASS);
+        when(params.getPort()).thenReturn(PORT);
+        when(params.getUserName()).thenReturn(USER);
+        when(params.isAaf()).thenReturn(true);
+        when(params.isHttps()).thenReturn(true);
+
+        Whitebox.setInternalState(RestServer.class, FACTORY_FIELD, factory);
+    }
+
+    @Test
+    public void testRestServer() {
+        rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
+
+        rest.start();
+        verify(server1).start();
+        verify(server2).start();
+
+        rest.stop();
+        verify(server1).stop();
+        verify(server2).stop();
+    }
+
+    @Test
+    public void testRestServer_NoAaf() {
+        rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
+        verify(server1, never()).addFilterClass(any(), any());
+        verify(server2, never()).addFilterClass(any(), any());
+    }
+
+    @Test
+    public void testRestServer_OnlyOneAaf() {
+        when(server2.isAaf()).thenReturn(true);
+
+        rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
+
+        verify(server1, never()).addFilterClass(any(), any());
+        verify(server2).addFilterClass(null, Filter.class.getName());
+    }
+
+    @Test
+    public void testRestServer_BothAaf() {
+        when(server1.isAaf()).thenReturn(true);
+        when(server2.isAaf()).thenReturn(true);
+
+        rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
+
+        verify(server1).addFilterClass(null, Filter.class.getName());
+        verify(server2).addFilterClass(null, Filter.class.getName());
+    }
+
+    @Test
+    public void testRestServer_BothAaf_NoFilter() {
+        when(server1.isAaf()).thenReturn(true);
+        when(server2.isAaf()).thenReturn(true);
+
+        rest = new RestServer(params, null, Provider1.class, Provider2.class);
+
+        verify(server1, never()).addFilterClass(any(), any());
+        verify(server2, never()).addFilterClass(any(), any());
+    }
+
+    @Test
+    public void testRestServer_MissingProviders() {
+        assertThatIllegalArgumentException().isThrownBy(() -> new RestServer(params, Filter.class));
+    }
+
+    @Test
+    public void testGetServerProperties_testGetProviderNames() {
+        rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
+
+        ArgumentCaptor<Properties> cap = ArgumentCaptor.forClass(Properties.class);
+        verify(serverFactory).build(cap.capture());
+
+        Properties props = cap.getValue();
+        String svcpfx = PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + PARAM_NAME;
+
+        assertEquals(HOST, props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX));
+        assertEquals(String.valueOf(PORT),
+                        props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX));
+        assertEquals(Provider1.class.getName() + "," + Provider2.class.getName(),
+                        props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX));
+        assertEquals("false", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX));
+        assertEquals("true", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX));
+        assertEquals(USER, props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX));
+        assertEquals(PASS, props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX));
+        assertEquals("true", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX));
+        assertEquals("true", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_AAF_SUFFIX));
+        assertEquals(GsonMessageBodyHandler.class.getName(),
+                        props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER));
+    }
+
+    @Test
+    public void testToString() {
+        rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
+        assertNotNull(rest.toString());
+    }
+
+    @Test
+    public void testFactory() {
+        assertNotNull(saveFactory);
+        assertNotNull(saveFactory.getServerFactory());
+    }
+
+    private static class Filter extends AafAuthFilter {
+        @Override
+        protected String getPermissionType(HttpServletRequest request) {
+            return "";
+        }
+
+        @Override
+        protected String getPermissionInstance(HttpServletRequest request) {
+            return "";
+        }
+    }
+
+    private static class Provider1 {
+        private Provider1() {
+            // do nothing
+        }
+    }
+
+    private static class Provider2 {
+        private Provider2() {
+            // do nothing
+        }
+    }
+}