diff options
3 files changed, 369 insertions, 0 deletions
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 73b1e544..0adf782c 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 @@ import org.onap.policy.common.capabilities.Startable; * 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 00000000..1f7a921a --- /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 00000000..3f671734 --- /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 + } + } +} |