86f5fb04e141f82431f9e314a95da1c65cd58c91
[policy/common.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP Policy Engine - Common Modules
4  * ================================================================================
5  * Copyright (C) 2017-2019, 2021 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2020 Nordix Foundation.
7  * Modifications Copyright (C) 2021 Bell Canada. All rights reserved.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.common.endpoints.http.server;
24
25 import com.google.re2j.Pattern;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Properties;
30 import org.apache.commons.lang3.StringUtils;
31 import org.onap.policy.common.endpoints.http.server.internal.JettyJerseyServer;
32 import org.onap.policy.common.endpoints.http.server.internal.JettyStaticResourceServer;
33 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
34 import org.onap.policy.common.endpoints.utils.PropertyUtils;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * Indexed factory implementation.
40  */
41 class IndexedHttpServletServerFactory implements HttpServletServerFactory {
42     private static final Pattern COMMA_SPACE_PAT = Pattern.compile("\\s*,\\s*");
43
44     /**
45      * logger.
46      */
47     protected static Logger logger = LoggerFactory.getLogger(IndexedHttpServletServerFactory.class);
48
49     /**
50      * servers index.
51      */
52     protected HashMap<Integer, HttpServletServer> servers = new HashMap<>();
53
54     @Override
55     public synchronized HttpServletServer build(String name, boolean https, String host, int port, String contextPath,
56         boolean swagger, boolean managed) {
57
58         if (servers.containsKey(port)) {
59             return servers.get(port);
60         }
61
62         var server = new JettyJerseyServer(name, https, host, port, contextPath, swagger);
63         if (managed) {
64             servers.put(port, server);
65         }
66
67         return server;
68     }
69
70     @Override
71     public synchronized HttpServletServer build(String name, String host, int port, String contextPath, boolean swagger,
72         boolean managed) {
73         return build(name, false, host, port, contextPath, swagger, managed);
74     }
75
76     @Override
77     public synchronized List<HttpServletServer> build(Properties properties) {
78
79         ArrayList<HttpServletServer> serviceList = new ArrayList<>();
80
81         String serviceNames = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES);
82         if (StringUtils.isBlank(serviceNames)) {
83             logger.warn("No topic for HTTP Service: {}", properties);
84             return serviceList;
85         }
86
87         for (String serviceName : COMMA_SPACE_PAT.split(serviceNames)) {
88             addService(serviceList, serviceName, properties);
89         }
90
91         return serviceList;
92     }
93
94
95
96     @Override
97     public HttpServletServer buildStaticResourceServer(String name, boolean https, String host, int port,
98             String contextPath, boolean managed) {
99         if (servers.containsKey(port)) {
100             return servers.get(port);
101         }
102
103         var server = new JettyStaticResourceServer(name, https, host, port, contextPath);
104         if (managed) {
105             servers.put(port, server);
106         }
107
108         return server;
109     }
110
111     private void addService(ArrayList<HttpServletServer> serviceList, String serviceName, Properties properties) {
112
113         String servicePrefix = PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + serviceName;
114
115         var props = new PropertyUtils(properties, servicePrefix,
116             (name, value, ex) -> logger
117                         .warn("{}: {} {} is in invalid format for http service {} ", this, name, value, serviceName));
118
119         var servicePort = props.getInteger(PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, -1);
120         if (servicePort < 0) {
121             logger.warn("No HTTP port for service in {}", serviceName);
122             return;
123         }
124
125         final var hostName = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, null);
126         final var contextUriPath = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_CONTEXT_URIPATH_SUFFIX, null);
127         var managed = props.getBoolean(PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, true);
128         var swagger = props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, false);
129         var https = props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX, false);
130
131         // create the service
132         HttpServletServer service = build(serviceName, https, hostName, servicePort, contextUriPath, swagger, managed);
133
134         // configure the service
135         setSerializationProvider(props, service);
136         setAuthentication(props, service, contextUriPath);
137
138         final var restUriPath = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_REST_URIPATH_SUFFIX, null);
139
140         addFilterClasses(props, service, restUriPath);
141         addRestServletClasses(props, service, restUriPath);
142         addServletPackages(props, service, restUriPath);
143
144         addServletClass(props, service);
145         setPrometheus(props, service);
146
147         serviceList.add(service);
148     }
149
150     private void setSerializationProvider(PropertyUtils props, HttpServletServer service) {
151
152         final var classProv = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER, null);
153
154         if (!StringUtils.isBlank(classProv)) {
155             service.setSerializationProvider(classProv);
156         }
157     }
158
159     private void setAuthentication(PropertyUtils props, HttpServletServer service, final String contextUriPath) {
160         /* authentication method either AAF or HTTP Basic Auth */
161
162         final var aaf = props.getBoolean(PolicyEndPointProperties.PROPERTY_AAF_SUFFIX, false);
163         final var userName = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, null);
164         final var password = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, null);
165         final var authUriPath = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_AUTH_URIPATH_SUFFIX, null);
166
167         if (aaf) {
168             service.setAafAuthentication(contextUriPath);
169         } else if (!StringUtils.isBlank(userName) && !StringUtils.isBlank(password)) {
170             service.setBasicAuthentication(userName, password, authUriPath);
171         }
172     }
173
174     private void setPrometheus(PropertyUtils props, HttpServletServer service) {
175         if (props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_PROMETHEUS_SUFFIX, false)) {
176             service.setPrometheus("/metrics");
177         }
178     }
179
180     private void addFilterClasses(PropertyUtils props, HttpServletServer service, final String restUriPath) {
181
182         final var filterClasses =
183                         props.getString(PolicyEndPointProperties.PROPERTY_HTTP_FILTER_CLASSES_SUFFIX, null);
184
185         if (!StringUtils.isBlank(filterClasses)) {
186             for (String filterClass : COMMA_SPACE_PAT.split(filterClasses)) {
187                 service.addFilterClass(restUriPath, filterClass);
188             }
189         }
190     }
191
192     private void addRestServletClasses(PropertyUtils props, HttpServletServer service, final String restUriPath) {
193         final var restClasses = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, null);
194
195         if (!StringUtils.isBlank(restClasses)) {
196             for (String restClass : COMMA_SPACE_PAT.split(restClasses)) {
197                 service.addServletClass(restUriPath, restClass);
198             }
199         }
200     }
201
202     private void addServletClass(PropertyUtils props, HttpServletServer service) {
203         var servletClass = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_SERVLET_CLASS_SUFFIX, null);
204         var servletUriPath = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_SERVLET_URIPATH_SUFFIX, null);
205
206         if (!StringUtils.isBlank(servletClass) && !StringUtils.isBlank(servletUriPath)) {
207             service.addStdServletClass(servletUriPath, servletClass);
208         }
209     }
210
211     private void addServletPackages(PropertyUtils props, HttpServletServer service, final String restUriPath) {
212
213         final var restPackages = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_REST_PACKAGES_SUFFIX, null);
214
215         if (!StringUtils.isBlank(restPackages)) {
216             for (String restPackage : COMMA_SPACE_PAT.split(restPackages)) {
217                 service.addServletPackage(restUriPath, restPackage);
218             }
219         }
220     }
221
222     @Override
223     public synchronized HttpServletServer get(int port) {
224
225         if (servers.containsKey(port)) {
226             return servers.get(port);
227         }
228
229         throw new IllegalArgumentException("Http Server for " + port + " not found");
230     }
231
232     @Override
233     public synchronized List<HttpServletServer> inventory() {
234         return new ArrayList<>(this.servers.values());
235     }
236
237     @Override
238     public synchronized void destroy(int port) {
239
240         if (!servers.containsKey(port)) {
241             return;
242         }
243
244         HttpServletServer server = servers.remove(port);
245         server.shutdown();
246     }
247
248     @Override
249     public synchronized void destroy() {
250         List<HttpServletServer> httpServletServers = this.inventory();
251         for (HttpServletServer server : httpServletServers) {
252             server.shutdown();
253         }
254
255         synchronized (this) {
256             this.servers.clear();
257         }
258     }
259
260 }