aboutsummaryrefslogtreecommitdiffstats
path: root/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http
diff options
context:
space:
mode:
Diffstat (limited to 'policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http')
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClient.java82
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClientConfigException.java4
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClientFactoryInstance.java10
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/IndexedHttpClientFactory.java20
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java181
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/AuthorizationFilter.java24
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServer.java50
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServerFactory.java42
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServerFactoryInstance.java11
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/IndexedHttpServletServerFactory.java114
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/JsonExceptionMapper.java21
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/RestServer.java87
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlExceptionMapper.java19
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlJacksonHandler.java9
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlMessageBodyHandler.java21
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/aaf/AafAuthFilter.java45
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/aaf/AafGranularAuthFilter.java48
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyJerseyServer.java74
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java209
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyStaticResourceServer.java107
20 files changed, 673 insertions, 505 deletions
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClient.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClient.java
index 2fe46fb3..01deaa2d 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClient.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClient.java
@@ -2,7 +2,8 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 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,15 +21,17 @@
package org.onap.policy.common.endpoints.http.client;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.InvocationCallback;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Response;
import java.util.Map;
-
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Response;
-
+import java.util.concurrent.Future;
import org.onap.policy.common.capabilities.Startable;
/**
- * Http Client interface.
+ * Http Client interface. Supports both synchronous and asynchronous operations.
+ *
*/
public interface HttpClient extends Startable {
@@ -48,6 +51,26 @@ public interface HttpClient extends Startable {
Response get();
/**
+ * Asynchronous GET request.
+ *
+ * @param callback callback to be invoked, asynchronously, when the request completes
+ * @param path context uri path
+ * @param headers request headers
+ *
+ * @return future that can be used to cancel the request or await the response
+ */
+ Future<Response> get(InvocationCallback<Response> callback, String path, Map<String, Object> headers);
+
+ /**
+ * Asynchronous GET request.
+ *
+ * @param callback callback to be invoked, asynchronously, when the request completes
+ * @param headers request headers
+ * @return future that can be used to cancel the request or await the response
+ */
+ Future<Response> get(InvocationCallback<Response> callback, Map<String, Object> headers);
+
+ /**
* PUT request.
*
* @param path context uri path
@@ -59,6 +82,19 @@ public interface HttpClient extends Startable {
Response put(String path, Entity<?> entity, Map<String, Object> headers);
/**
+ * Asynchronous PUT request.
+ *
+ * @param callback callback to be invoked, asynchronously, when the request completes
+ * @param path context uri path
+ * @param entity body
+ * @param headers headers
+ *
+ * @return future that can be used to cancel the request or await the response
+ */
+ Future<Response> put(InvocationCallback<Response> callback, String path, Entity<?> entity,
+ Map<String, Object> headers);
+
+ /**
* POST request.
*
* @param path context uri path
@@ -70,6 +106,19 @@ public interface HttpClient extends Startable {
Response post(String path, Entity<?> entity, Map<String, Object> headers);
/**
+ * Asynchronous POST request.
+ *
+ * @param callback callback to be invoked, asynchronously, when the request completes
+ * @param path context uri path
+ * @param entity body
+ * @param headers headers
+ *
+ * @return future that can be used to cancel the request or await the response
+ */
+ Future<Response> post(InvocationCallback<Response> callback, String path, Entity<?> entity,
+ Map<String, Object> headers);
+
+ /**
* DELETE request.
*
* @param path context uri path
@@ -80,6 +129,17 @@ public interface HttpClient extends Startable {
Response delete(String path, Map<String, Object> headers);
/**
+ * Asynchronous DELETE request.
+ *
+ * @param callback callback to be invoked, asynchronously, when the request completes
+ * @param path context uri path
+ * @param headers headers
+ *
+ * @return future that can be used to cancel the request or await the response
+ */
+ Future<Response> delete(InvocationCallback<Response> callback, String path, Map<String, Object> headers);
+
+ /**
* Retrieve the body from the HTTP transaction.
*
* @param response response.
@@ -134,9 +194,9 @@ public interface HttpClient extends Startable {
String getBasePath();
/**
- * Get the user name.
+ * Get the username.
*
- * @return the user name
+ * @return the username
*/
String getUserName();
@@ -154,4 +214,10 @@ public interface HttpClient extends Startable {
*/
String getBaseUrl();
+ /**
+ * Gets a web target associated with the base URL.
+ *
+ * @return a webtarget
+ */
+ WebTarget getWebTarget();
}
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClientConfigException.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClientConfigException.java
index 98ec576f..bb871fa0 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClientConfigException.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClientConfigException.java
@@ -3,6 +3,7 @@
* ONAP
* ================================================================================
* Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 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,10 +21,13 @@
package org.onap.policy.common.endpoints.http.client;
+import java.io.Serial;
+
/**
* Exception generated by HttpClient builder.
*/
public class HttpClientConfigException extends Exception {
+ @Serial
private static final long serialVersionUID = 1L;
public HttpClientConfigException() {
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClientFactoryInstance.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClientFactoryInstance.java
index c2921640..f64be30e 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClientFactoryInstance.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClientFactoryInstance.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019, 2021 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.
@@ -20,8 +20,11 @@
package org.onap.policy.common.endpoints.http.client;
+import lombok.AccessLevel;
import lombok.Getter;
+import lombok.NoArgsConstructor;
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class HttpClientFactoryInstance {
/**
@@ -29,9 +32,4 @@ public class HttpClientFactoryInstance {
*/
@Getter
private static final HttpClientFactory clientFactory = new IndexedHttpClientFactory();
-
-
- private HttpClientFactoryInstance() {
- // do nothing
- }
}
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/IndexedHttpClientFactory.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/IndexedHttpClientFactory.java
index edf8ff6f..5f0b1d6e 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/IndexedHttpClientFactory.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/IndexedHttpClientFactory.java
@@ -2,7 +2,8 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 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,6 +21,7 @@
package org.onap.policy.common.endpoints.http.client;
+import com.google.re2j.Pattern;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
@@ -38,11 +40,12 @@ import org.slf4j.LoggerFactory;
* HTTP client factory implementation indexed by name.
*/
class IndexedHttpClientFactory implements HttpClientFactory {
+ private static final Pattern COMMA_SPACE_PAT = Pattern.compile("\\s*,\\s*");
/**
* Logger.
*/
- private static Logger logger = LoggerFactory.getLogger(IndexedHttpClientFactory.class);
+ private static final Logger logger = LoggerFactory.getLogger(IndexedHttpClientFactory.class);
protected HashMap<String, HttpClient> clients = new HashMap<>();
@@ -75,7 +78,7 @@ class IndexedHttpClientFactory implements HttpClientFactory {
return clientList;
}
- for (String clientName : clientNames.split("\\s*,\\s*")) {
+ for (String clientName : COMMA_SPACE_PAT.split(clientNames)) {
addClient(clientList, clientName, properties);
}
@@ -85,23 +88,22 @@ class IndexedHttpClientFactory implements HttpClientFactory {
private void addClient(ArrayList<HttpClient> clientList, String clientName, Properties properties) {
String clientPrefix = PolicyEndPointProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + clientName;
- PropertyUtils props = new PropertyUtils(properties, clientPrefix,
+ var props = new PropertyUtils(properties, clientPrefix,
(name, value, ex) ->
logger.warn("{}: {} {} is in invalid format for http client {} ", this, name, value, clientName));
- int port = props.getInteger(PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, -1);
+ var port = props.getInteger(PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, -1);
if (port < 0) {
logger.warn("No HTTP port for client in {}", clientName);
return;
}
- boolean https = props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX, false);
-
try {
HttpClient client = this.build(BusTopicParams.builder()
.clientName(clientName)
- .useHttps(https)
- .allowSelfSignedCerts(https)
+ .useHttps(props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX, false))
+ .allowSelfSignedCerts(
+ props.getBoolean(PolicyEndPointProperties.PROPERTY_ALLOW_SELF_SIGNED_CERTIFICATES_SUFFIX, false))
.hostname(props.getString(PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, null))
.port(port)
.basePath(props.getString(PolicyEndPointProperties.PROPERTY_HTTP_URL_SUFFIX, null))
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
index 8a717712..130b6c15 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
@@ -2,9 +2,9 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved.
* Modifications Copyright (C) 2018 Samsung Electronics Co., Ltd.
- * Modifications Copyright (C) 2019 Nordix Foundation.
+ * Modifications Copyright (C) 2019, 2023 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,24 +22,29 @@
package org.onap.policy.common.endpoints.http.client.internal;
-import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.re2j.Pattern;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.Invocation.Builder;
+import jakarta.ws.rs.client.InvocationCallback;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Response;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
+import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.concurrent.Future;
import javax.net.ssl.SSLContext;
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.Invocation.Builder;
-import javax.ws.rs.core.Response;
+import lombok.Getter;
+import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
import org.onap.policy.common.endpoints.http.client.HttpClient;
-import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
import org.onap.policy.common.utils.network.NetworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,15 +52,18 @@ import org.slf4j.LoggerFactory;
/**
* Http Client implementation using a Jersey Client.
*/
+@Getter
+@ToString
public class JerseyClient implements HttpClient {
+ private static final Pattern COMMA_PAT = Pattern.compile(",");
/**
* Logger.
*/
- private static Logger logger = LoggerFactory.getLogger(JerseyClient.class);
+ private static final Logger logger = LoggerFactory.getLogger(JerseyClient.class);
protected static final String JERSEY_DEFAULT_SERIALIZATION_PROVIDER =
- "org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJsonProvider";
+ "org.onap.policy.common.gson.GsonMessageBodyHandler";
protected final String name;
protected final boolean https;
@@ -74,9 +82,14 @@ public class JerseyClient implements HttpClient {
/**
* Constructor.
*
- * <p>name the name https is it https or not selfSignedCerts are there self signed certs
- * hostname the hostname port port being used basePath base context userName user
- * password password
+ * <p>name - the name
+ * https - is it https or not
+ * selfSignedCerts - are there self-signed certs
+ * hostname - the hostname
+ * port - port being used
+ * basePath - base context
+ * userName - user credentials
+ * password - password credentials
*
* @param busTopicParams Input parameters object
* @throws KeyManagementException key exception
@@ -109,7 +122,7 @@ public class JerseyClient implements HttpClient {
this.client = detmClient();
if (!StringUtils.isBlank(this.userName) && !StringUtils.isBlank(this.password)) {
- HttpAuthenticationFeature authFeature = HttpAuthenticationFeature.basic(userName, password);
+ var authFeature = HttpAuthenticationFeature.basic(userName, password);
this.client.register(authFeature);
}
@@ -124,11 +137,17 @@ public class JerseyClient implements HttpClient {
private Client detmClient() throws NoSuchAlgorithmException, KeyManagementException {
if (this.https) {
ClientBuilder clientBuilder;
- SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
+ var sslContext = SSLContext.getInstance("TLSv1.2");
if (this.selfSignedCerts) {
sslContext.init(null, NetworkUtil.getAlwaysTrustingManager(), new SecureRandom());
+
+ // This falls under self-signed certs which is used for non-production testing environments where
+ // the hostname in the cert is unlikely to be crafted properly. We always return true for the
+ // hostname verifier. This causes a sonar vuln, but we ignore it as it could cause problems in some
+ // testing environments.
clientBuilder =
- ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier((host, session) -> true);
+ ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier(
+ (host, session) -> true); //NOSONAR
} else {
sslContext.init(null, null, null);
clientBuilder = ClientBuilder.newBuilder().sslContext(sslContext);
@@ -149,23 +168,48 @@ public class JerseyClient implements HttpClient {
private void registerSerProviders(String serializationProvider) throws ClassNotFoundException {
String providers = (StringUtils.isBlank(serializationProvider)
? JERSEY_DEFAULT_SERIALIZATION_PROVIDER : serializationProvider);
- for (String prov : providers.split(",")) {
+ for (String prov : COMMA_PAT.split(providers)) {
this.client.register(Class.forName(prov));
}
}
@Override
+ public WebTarget getWebTarget() {
+ return this.client.target(this.baseUrl);
+ }
+
+ @Override
public Response get(String path) {
if (!StringUtils.isBlank(path)) {
- return this.client.target(this.baseUrl).path(path).request().get();
+ return getWebTarget().path(path).request().get();
} else {
- return this.client.target(this.baseUrl).request().get();
+ return getWebTarget().request().get();
}
}
@Override
public Response get() {
- return this.client.target(this.baseUrl).request().get();
+ return getWebTarget().request().get();
+ }
+
+ @Override
+ public Future<Response> get(InvocationCallback<Response> callback, String path, Map<String, Object> headers) {
+ Map<String, Object> headers2 = (headers != null ? headers : Collections.emptyMap());
+
+ if (!StringUtils.isBlank(path)) {
+ return getBuilder(path, headers2).async().get(callback);
+ } else {
+ return get(callback, headers2);
+ }
+ }
+
+ @Override
+ public Future<Response> get(InvocationCallback<Response> callback, Map<String, Object> headers) {
+ var builder = getWebTarget().request();
+ if (headers != null) {
+ headers.forEach(builder::header);
+ }
+ return builder.async().get(callback);
}
@Override
@@ -174,16 +218,33 @@ public class JerseyClient implements HttpClient {
}
@Override
+ public Future<Response> put(InvocationCallback<Response> callback, String path, Entity<?> entity,
+ Map<String, Object> headers) {
+ return getBuilder(path, headers).async().put(entity, callback);
+ }
+
+ @Override
public Response post(String path, Entity<?> entity, Map<String, Object> headers) {
return getBuilder(path, headers).post(entity);
}
@Override
+ public Future<Response> post(InvocationCallback<Response> callback, String path, Entity<?> entity,
+ Map<String, Object> headers) {
+ return getBuilder(path, headers).async().post(entity, callback);
+ }
+
+ @Override
public Response delete(String path, Map<String, Object> headers) {
return getBuilder(path, headers).delete();
}
@Override
+ public Future<Response> delete(InvocationCallback<Response> callback, String path, Map<String, Object> headers) {
+ return getBuilder(path, headers).async().delete(callback);
+ }
+
+ @Override
public boolean start() {
return alive;
}
@@ -211,84 +272,8 @@ public class JerseyClient implements HttpClient {
return this.alive;
}
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public boolean isHttps() {
- return https;
- }
-
- @Override
- public boolean isSelfSignedCerts() {
- return selfSignedCerts;
- }
-
- @Override
- public String getHostname() {
- return hostname;
- }
-
- @Override
- public int getPort() {
- return port;
- }
-
- @Override
- public String getBasePath() {
- return basePath;
- }
-
- @Override
- public String getUserName() {
- return userName;
- }
-
- @JsonIgnore
- @GsonJsonIgnore
- @Override
- public String getPassword() {
- return password;
- }
-
- @Override
- public String getBaseUrl() {
- return baseUrl;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("JerseyClient [name=");
- builder.append(name);
- builder.append(", https=");
- builder.append(https);
- builder.append(", selfSignedCerts=");
- builder.append(selfSignedCerts);
- builder.append(", hostname=");
- builder.append(hostname);
- builder.append(", port=");
- builder.append(port);
- builder.append(", basePath=");
- builder.append(basePath);
- builder.append(", userName=");
- builder.append(userName);
- builder.append(", password=");
- builder.append(password);
- builder.append(", client=");
- builder.append(client);
- builder.append(", baseUrl=");
- builder.append(baseUrl);
- builder.append(", alive=");
- builder.append(alive);
- builder.append("]");
- return builder.toString();
- }
-
private Builder getBuilder(String path, Map<String, Object> headers) {
- Builder builder = this.client.target(this.baseUrl).path(path).request();
+ var builder = getWebTarget().path(path).request();
for (Entry<String, Object> header : headers.entrySet()) {
builder.header(header.getKey(), header.getValue());
}
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/AuthorizationFilter.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/AuthorizationFilter.java
index d884b869..44204cfd 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/AuthorizationFilter.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/AuthorizationFilter.java
@@ -3,6 +3,7 @@
* ONAP
* ================================================================================
* Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023-2024 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,36 +21,33 @@
package org.onap.policy.common.endpoints.http.server;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AuthorizationFilter implements Filter {
- private static Logger logger = LoggerFactory.getLogger(AuthorizationFilter.class);
+ private static final Logger logger = LoggerFactory.getLogger(AuthorizationFilter.class);
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
- if (!(servletRequest instanceof HttpServletRequest)) {
+ if (!(servletRequest instanceof HttpServletRequest request)) {
throw new ServletException("Not an HttpServletRequest instance");
}
- if (!(servletResponse instanceof HttpServletResponse)) {
+ if (!(servletResponse instanceof HttpServletResponse response)) {
throw new ServletException("Not an HttpServletResponse instance");
}
- HttpServletRequest request = (HttpServletRequest) servletRequest;
- HttpServletResponse response = (HttpServletResponse) servletResponse;
-
String role = getRole(request);
boolean authorized = request.isUserInRole(role);
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 0adf782c..a20c125d 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
@@ -3,6 +3,8 @@
* ONAP
* ================================================================================
* Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2020, 2024 Nordix Foundation.
+ * Modifications Copyright (C) 2021 Bell Canada. 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.
@@ -50,18 +52,6 @@ public interface HttpServletServer extends Startable {
void setBasicAuthentication(String user, String password, String relativeUriPath);
/**
- * Enables AAF based authentication.
- *
- * @param filterPath filter path
- */
- void setAafAuthentication(String filterPath);
-
- /**
- * Checks if AAF authentication has been enabled.
- */
- boolean isAaf();
-
- /**
* Sets the serialization provider to be used when classes are added to the service.
*
* @param provider the provider to use for message serialization and de-serialization
@@ -83,22 +73,44 @@ public interface HttpServletServer extends Startable {
* @param restClass JAX-RS API Class
*
* @throws IllegalArgumentException unable to process because of invalid input
- * @throws IllegalStateException unable to process because of invalid state
+ * @throws IllegalStateException unable to process because of invalid state, for example
+ * different types of servlets map to the same servletPath
*/
void addServletClass(String servletPath, String restClass);
/**
+ * Adds a Java Servlet.
+ *
+ * @param servletPath servlet path
+ * @param plainServletClass servlet class
+ */
+ void addStdServletClass(String servletPath, String plainServletClass);
+
+ /**
* Adds a package containing JAX-RS classes to serve REST requests.
*
* @param servletPath servlet path
* @param restPackage JAX-RS package to scan
*
* @throws IllegalArgumentException unable to process because of invalid input
- * @throws IllegalStateException unable to process because of invalid state
+ * @throws IllegalStateException unable to process because of invalid state, for example
+ * different types of servlets map to the same servletPath
*/
void addServletPackage(String servletPath, String restPackage);
/**
+ * Add a static resource path to manage static resources.
+ *
+ * @param servletPath servlet path
+ * @param resourceBase static resources folder
+ *
+ * @throws IllegalArgumentException unable to process because of invalid input
+ * @throws IllegalStateException unable to process because of invalid state, for example
+ * different types of servlets map to the same servletPath
+ */
+ void addServletResource(String servletPath, String resourceBase);
+
+ /**
* Blocking start of the http server.
*
* @param maxWaitTime max time to wait for the start to take place
@@ -108,4 +120,14 @@ public interface HttpServletServer extends Startable {
* @throws InterruptedException if the blocking operation is interrupted
*/
boolean waitedStart(long maxWaitTime) throws InterruptedException;
+
+ /**
+ * Are prometheus metrics enabled?.
+ */
+ public boolean isPrometheus();
+
+ /**
+ * Enable prometheus metrics.
+ */
+ public void setPrometheus(String metricsPath);
}
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 0c30e3e5..7ce0becd 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,2023 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,23 +30,24 @@ import java.util.Properties;
public interface HttpServletServerFactory {
/**
- * Builds an http or https server with support for servlets.
- *
+ * Builds a http or https rest server with support for servlets.
+ *
* @param name name
* @param https use secured http over tls connection
* @param host binding host
* @param port port
+ * @param sniHostCheck SNI Host checking flag
* @param contextPath server base path
* @param swagger enable swagger documentation
* @param managed is it managed by infrastructure
* @return http server
* @throws IllegalArgumentException when invalid parameters are provided
*/
- HttpServletServer build(String name, boolean https, String host, int port, String contextPath, boolean swagger,
- boolean managed);
+ HttpServletServer build(String name, boolean https, String host, int port, boolean sniHostCheck, String contextPath,
+ boolean swagger, boolean managed);
/**
- * Builds an http server with support for servlets.
+ * Builds a http rest server with support for servlets.
*
* @param name name
* @param host binding host
@@ -59,8 +61,8 @@ public interface HttpServletServerFactory {
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 +70,24 @@ public interface HttpServletServerFactory {
List<HttpServletServer> build(Properties properties);
/**
+ * Builds a 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 sniHostCheck SNI Host checking flag
+ * @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, boolean sniHostCheck,
+ String contextPath, boolean managed);
+
+ /**
* Gets a server based on the port.
- *
+ *
* @param port port
* @return http server
*/
@@ -77,14 +95,14 @@ public interface HttpServletServerFactory {
/**
* 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/HttpServletServerFactoryInstance.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServerFactoryInstance.java
index a56be701..58e27cbf 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServerFactoryInstance.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServerFactoryInstance.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019, 2021 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.
@@ -20,8 +20,11 @@
package org.onap.policy.common.endpoints.http.server;
+import lombok.AccessLevel;
import lombok.Getter;
+import lombok.NoArgsConstructor;
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class HttpServletServerFactoryInstance {
/**
@@ -29,10 +32,4 @@ public class HttpServletServerFactoryInstance {
*/
@Getter
private static final HttpServletServerFactory serverFactory = new IndexedHttpServletServerFactory();
-
-
- private HttpServletServerFactoryInstance() {
- // do nothing
- }
-
}
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 517ad208..7c9aca4c 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
@@ -2,7 +2,9 @@
* ============LICENSE_START=======================================================
* ONAP Policy Engine - Common Modules
* ================================================================================
- * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2020,2023-2024 Nordix Foundation.
+ * Modifications Copyright (C) 2021 Bell Canada. 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.
@@ -20,12 +22,14 @@
package org.onap.policy.common.endpoints.http.server;
+import com.google.re2j.Pattern;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
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;
@@ -35,8 +39,7 @@ import org.slf4j.LoggerFactory;
* Indexed factory implementation.
*/
class IndexedHttpServletServerFactory implements HttpServletServerFactory {
-
- private static final String SPACES_COMMA_SPACES = "\\s*,\\s*";
+ private static final Pattern COMMA_SPACE_PAT = Pattern.compile("\\s*,\\s*");
/**
* logger.
@@ -49,14 +52,14 @@ class IndexedHttpServletServerFactory implements HttpServletServerFactory {
protected HashMap<Integer, HttpServletServer> servers = new HashMap<>();
@Override
- public synchronized HttpServletServer build(String name, boolean https, String host, int port, String contextPath,
- boolean swagger, boolean managed) {
+ public synchronized HttpServletServer build(String name, boolean https, String host, int port, boolean sniHostCheck,
+ String contextPath, boolean swagger, boolean managed) {
if (servers.containsKey(port)) {
return servers.get(port);
}
- JettyJerseyServer server = new JettyJerseyServer(name, https, host, port, contextPath, swagger);
+ var server = new JettyJerseyServer(name, https, host, port, sniHostCheck, contextPath, swagger);
if (managed) {
servers.put(port, server);
}
@@ -67,7 +70,7 @@ class IndexedHttpServletServerFactory implements HttpServletServerFactory {
@Override
public synchronized HttpServletServer build(String name, String host, int port, String contextPath, boolean swagger,
boolean managed) {
- return build(name, false, host, port, contextPath, swagger, managed);
+ return build(name, false, host, port, false, contextPath, swagger, managed);
}
@Override
@@ -81,103 +84,132 @@ class IndexedHttpServletServerFactory implements HttpServletServerFactory {
return serviceList;
}
- for (String serviceName : serviceNames.split(SPACES_COMMA_SPACES)) {
+ for (String serviceName : COMMA_SPACE_PAT.split(serviceNames)) {
addService(serviceList, serviceName, properties);
}
return serviceList;
}
+ @Override
+ public HttpServletServer buildStaticResourceServer(String name, boolean https, String host, int port,
+ boolean sniHostCheck, String contextPath, boolean managed) {
+ if (servers.containsKey(port)) {
+ return servers.get(port);
+ }
+
+ var server = new JettyStaticResourceServer(name, https, host, port, sniHostCheck, 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;
- PropertyUtils props = new PropertyUtils(properties, servicePrefix,
+ var props = new PropertyUtils(properties, servicePrefix,
(name, value, ex) -> logger
- .warn("{}: {} {} is in invalid format for http service {} ", this, name, value, serviceName));
+ .warn("{}: {} {} is in invalid format for http service {} ", this, name, value, serviceName));
- int servicePort = props.getInteger(PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, -1);
+ var servicePort = props.getInteger(PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, -1);
if (servicePort < 0) {
logger.warn("No HTTP port for service in {}", serviceName);
return;
}
- final String hostName = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, null);
- final String contextUriPath =
- props.getString(PolicyEndPointProperties.PROPERTY_HTTP_CONTEXT_URIPATH_SUFFIX, null);
- boolean managed = props.getBoolean(PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, true);
- boolean swagger = props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, false);
- boolean https = props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX, false);
+ final var hostName = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, null);
+ final var contextUriPath = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_CONTEXT_URIPATH_SUFFIX, null);
+ var managed = props.getBoolean(PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, true);
+ var swagger = props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, false);
+ var https = props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX, false);
+ var sniHostCheck = props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_SNI_HOST_CHECK_SUFFIX, false);
// create the service
- HttpServletServer service = build(serviceName, https, hostName, servicePort, contextUriPath, swagger, managed);
+ HttpServletServer service =
+ build(serviceName, https, hostName, servicePort, sniHostCheck, contextUriPath, swagger, managed);
// configure the service
setSerializationProvider(props, service);
- setAuthentication(props, service, contextUriPath);
+ setAuthentication(props, service);
- final String restUriPath = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_REST_URIPATH_SUFFIX, null);
+ final var restUriPath = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_REST_URIPATH_SUFFIX, null);
addFilterClasses(props, service, restUriPath);
- addServletClasses(props, service, restUriPath);
+ addRestServletClasses(props, service, restUriPath);
addServletPackages(props, service, restUriPath);
+ addServletClass(props, service);
+ setPrometheus(props, service);
+
serviceList.add(service);
}
private void setSerializationProvider(PropertyUtils props, HttpServletServer service) {
- final String classProv = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER, null);
+ final var classProv = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER, null);
if (!StringUtils.isBlank(classProv)) {
service.setSerializationProvider(classProv);
}
}
- private void setAuthentication(PropertyUtils props, HttpServletServer service, final String contextUriPath) {
- /* authentication method either AAF or HTTP Basic Auth */
-
- boolean aaf = props.getBoolean(PolicyEndPointProperties.PROPERTY_AAF_SUFFIX, false);
- final String userName = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, null);
- final String password = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, null);
- final String authUriPath = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_AUTH_URIPATH_SUFFIX, null);
+ private void setAuthentication(PropertyUtils props, HttpServletServer service) {
+ /* authentication method HTTP Basic Auth */
+ final var userName = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, null);
+ final var password = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, null);
+ final var authUriPath = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_AUTH_URIPATH_SUFFIX, null);
- if (aaf) {
- service.setAafAuthentication(contextUriPath);
- } else if (!StringUtils.isBlank(userName) && !StringUtils.isBlank(password)) {
+ if (!StringUtils.isBlank(userName) && !StringUtils.isBlank(password)) {
service.setBasicAuthentication(userName, password, authUriPath);
}
}
+ private void setPrometheus(PropertyUtils props, HttpServletServer service) {
+ if (props.getBoolean(PolicyEndPointProperties.PROPERTY_HTTP_PROMETHEUS_SUFFIX, false)) {
+ service.setPrometheus("/metrics");
+ }
+ }
+
private void addFilterClasses(PropertyUtils props, HttpServletServer service, final String restUriPath) {
- final String filterClasses =
- props.getString(PolicyEndPointProperties.PROPERTY_HTTP_FILTER_CLASSES_SUFFIX, null);
+ final var filterClasses =
+ props.getString(PolicyEndPointProperties.PROPERTY_HTTP_FILTER_CLASSES_SUFFIX, null);
if (!StringUtils.isBlank(filterClasses)) {
- for (String filterClass : filterClasses.split(SPACES_COMMA_SPACES)) {
+ for (String filterClass : COMMA_SPACE_PAT.split(filterClasses)) {
service.addFilterClass(restUriPath, filterClass);
}
}
}
- private void addServletClasses(PropertyUtils props, HttpServletServer service, final String restUriPath) {
-
- final String restClasses = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, null);
+ private void addRestServletClasses(PropertyUtils props, HttpServletServer service, final String restUriPath) {
+ final var restClasses = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, null);
if (!StringUtils.isBlank(restClasses)) {
- for (String restClass : restClasses.split(SPACES_COMMA_SPACES)) {
+ for (String restClass : COMMA_SPACE_PAT.split(restClasses)) {
service.addServletClass(restUriPath, restClass);
}
}
}
+ private void addServletClass(PropertyUtils props, HttpServletServer service) {
+ var servletClass = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_SERVLET_CLASS_SUFFIX, null);
+ var servletUriPath = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_SERVLET_URIPATH_SUFFIX, null);
+
+ if (!StringUtils.isBlank(servletClass) && !StringUtils.isBlank(servletUriPath)) {
+ service.addStdServletClass(servletUriPath, servletClass);
+ }
+ }
+
private void addServletPackages(PropertyUtils props, HttpServletServer service, final String restUriPath) {
- final String restPackages = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_REST_PACKAGES_SUFFIX, null);
+ final var restPackages = props.getString(PolicyEndPointProperties.PROPERTY_HTTP_REST_PACKAGES_SUFFIX, null);
if (!StringUtils.isBlank(restPackages)) {
- for (String restPackage : restPackages.split(SPACES_COMMA_SPACES)) {
+ for (String restPackage : COMMA_SPACE_PAT.split(restPackages)) {
service.addServletPackage(restUriPath, restPackage);
}
}
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/JsonExceptionMapper.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/JsonExceptionMapper.java
index 55b3a0d5..0030c121 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/JsonExceptionMapper.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/JsonExceptionMapper.java
@@ -1,6 +1,7 @@
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,11 +22,12 @@
package org.onap.policy.common.endpoints.http.server;
import com.google.gson.JsonSyntaxException;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
+import lombok.AllArgsConstructor;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +39,7 @@ import org.slf4j.LoggerFactory;
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JsonExceptionMapper implements ExceptionMapper<JsonSyntaxException> {
- private static Logger logger = LoggerFactory.getLogger(JsonExceptionMapper.class);
+ private static final Logger logger = LoggerFactory.getLogger(JsonExceptionMapper.class);
@Override
public Response toResponse(JsonSyntaxException exception) {
@@ -46,11 +48,8 @@ public class JsonExceptionMapper implements ExceptionMapper<JsonSyntaxException>
}
@Getter
+ @AllArgsConstructor
private static class SimpleResponse {
private String errorDetails;
-
- public SimpleResponse(String errorDetails) {
- this.errorDetails = errorDetails;
- }
}
}
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
index 43e39d33..7e6ce866 100644
--- 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
@@ -1,7 +1,8 @@
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2019 Nordix Foundation.
- * Modifications Copyright (C) 2019 AT&T Intellectual Property.
+ * Copyright (C) 2019, 2023-2024 Nordix Foundation.
+ * Modifications Copyright (C) 2019-2021 AT&T Intellectual Property.
+ * Modifications Copyright (C) 2021 Bell Canada. 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.
@@ -21,9 +22,13 @@
package org.onap.policy.common.endpoints.http.server;
+import jakarta.servlet.Filter;
+import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
import java.util.Properties;
-import org.onap.policy.common.endpoints.http.server.aaf.AafAuthFilter;
+import java.util.stream.Collectors;
+import lombok.ToString;
import org.onap.policy.common.endpoints.parameters.RestServerParameters;
import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
import org.onap.policy.common.gson.GsonMessageBodyHandler;
@@ -34,6 +39,7 @@ import org.onap.policy.common.utils.services.ServiceManagerContainer;
*
* @author Ram Krishna Verma (ram.krishna.verma@est.tech)
*/
+@ToString
public class RestServer extends ServiceManagerContainer {
/**
@@ -47,24 +53,34 @@ public class RestServer extends ServiceManagerContainer {
* 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) {
+ public RestServer(final RestServerParameters restServerParameters,
+ Class<?>... jaxrsProviders) {
+ this(restServerParameters, null, Arrays.asList(jaxrsProviders));
+ }
+
+ /**
+ * Constructs the object.
+ *
+ * @param restServerParameters the rest server parameters
+ * @param filters class of object to use to filter requests, or {@code null}
+ * @param jaxrsProviders classes providing the services
+ */
+ public RestServer(final RestServerParameters restServerParameters, List<Class<? extends Filter>> filters,
+ List<Class<?>> jaxrsProviders) {
- if (jaxrsProviders.length == 0) {
+ if (jaxrsProviders == null || jaxrsProviders.isEmpty()) {
throw new IllegalArgumentException("no providers specified");
}
this.servers = factory.getServerFactory()
- .build(getServerProperties(restServerParameters, getProviderClassNames(jaxrsProviders)));
+ .build(getServerProperties(restServerParameters, getProviderClassNames(jaxrsProviders)));
for (HttpServletServer server : this.servers) {
- if (aafFilter != null && server.isAaf()) {
- server.addFilterClass(null, aafFilter.getName());
+ if (filters != null && !filters.isEmpty()) {
+ filters.forEach(filter -> server.addFilterClass(null, filter.getName()));
}
-
addAction("REST " + server.getName(), server::start, server::stop);
}
}
@@ -78,29 +94,36 @@ public class RestServer extends ServiceManagerContainer {
* @return the properties object
*/
protected Properties getServerProperties(RestServerParameters restServerParameters, String names) {
- final Properties props = new Properties();
+ final var props = new Properties();
props.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES, restServerParameters.getName());
final String svcpfx =
- PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + restServerParameters.getName();
+ 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()));
+ 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());
+ getValue(restServerParameters.getUserName()));
props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX,
- restServerParameters.getPassword());
+ getValue(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()));
+ String.valueOf(restServerParameters.isHttps()));
+ props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SNI_HOST_CHECK_SUFFIX,
+ String.valueOf(restServerParameters.isSniHostCHeck()));
props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER,
- String.join(",", GsonMessageBodyHandler.class.getName(), YamlMessageBodyHandler.class.getName(),
- JsonExceptionMapper.class.getName(), YamlExceptionMapper.class.getName()));
+ String.join(",", GsonMessageBodyHandler.class.getName(), YamlMessageBodyHandler.class.getName(),
+ JsonExceptionMapper.class.getName(), YamlExceptionMapper.class.getName()));
+
+ props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERVLET_URIPATH_SUFFIX,
+ Optional.ofNullable(restServerParameters.getServletUriPath()).orElse(""));
+ props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERVLET_CLASS_SUFFIX,
+ Optional.ofNullable(restServerParameters.getServletClass()).orElse(""));
+ props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_PROMETHEUS_SUFFIX,
+ String.valueOf(restServerParameters.isPrometheus()));
return props;
}
@@ -110,23 +133,15 @@ public class RestServer extends ServiceManagerContainer {
* @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();
+ private String getProviderClassNames(List<Class<?>> jaxrsProviders) {
+ return jaxrsProviders.stream().map(Class::getName).collect(Collectors.joining(","));
}
- @Override
- public String toString() {
- return "RestServer [servers=" + servers + "]";
+ private String getValue(final String value) {
+ if (value != null && value.startsWith("${") && value.endsWith("}")) {
+ return System.getenv(value.substring(2, value.length() - 1));
+ }
+ return value;
}
/**
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlExceptionMapper.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlExceptionMapper.java
index 7eac932a..c30c2072 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlExceptionMapper.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlExceptionMapper.java
@@ -1,6 +1,7 @@
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 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,10 +21,11 @@
package org.onap.policy.common.endpoints.http.server;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
+import lombok.AllArgsConstructor;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,7 +38,7 @@ import org.yaml.snakeyaml.error.YAMLException;
@Provider
@Produces(YamlMessageBodyHandler.APPLICATION_YAML)
public class YamlExceptionMapper implements ExceptionMapper<YAMLException> {
- private static Logger logger = LoggerFactory.getLogger(YamlExceptionMapper.class);
+ private static final Logger logger = LoggerFactory.getLogger(YamlExceptionMapper.class);
@Override
public Response toResponse(YAMLException exception) {
@@ -45,11 +47,8 @@ public class YamlExceptionMapper implements ExceptionMapper<YAMLException> {
}
@Getter
+ @AllArgsConstructor
private static class SimpleResponse {
private String errorDetails;
-
- public SimpleResponse(String errorDetails) {
- this.errorDetails = errorDetails;
- }
}
}
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlJacksonHandler.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlJacksonHandler.java
index f71aa90f..4639e6a2 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlJacksonHandler.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlJacksonHandler.java
@@ -3,6 +3,7 @@
* ONAP
* ================================================================================
* Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,10 +22,10 @@
package org.onap.policy.common.endpoints.http.server;
import com.google.gson.GsonBuilder;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.ext.Provider;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.ext.Provider;
import org.onap.policy.common.gson.JacksonHandler;
import org.onap.policy.common.utils.coder.YamlJsonTranslator;
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlMessageBodyHandler.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlMessageBodyHandler.java
index 8506a283..6de6b754 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlMessageBodyHandler.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlMessageBodyHandler.java
@@ -2,7 +2,8 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +23,13 @@ package org.onap.policy.common.endpoints.http.server;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -30,13 +38,6 @@ import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
import org.onap.policy.common.gson.GsonMessageBodyHandler;
import org.onap.policy.common.utils.coder.YamlJsonTranslator;
import org.slf4j.Logger;
@@ -96,7 +97,7 @@ public class YamlMessageBodyHandler implements MessageBodyReader<Object>, Messag
public void writeTo(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException {
- try (OutputStreamWriter writer = new OutputStreamWriter(entityStream, StandardCharsets.UTF_8)) {
+ try (var writer = new OutputStreamWriter(entityStream, StandardCharsets.UTF_8)) {
translator.toYaml(writer, object);
}
}
@@ -121,7 +122,7 @@ public class YamlMessageBodyHandler implements MessageBodyReader<Object>, Messag
public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
- try (InputStreamReader streamReader = new InputStreamReader(entityStream, StandardCharsets.UTF_8)) {
+ try (var streamReader = new InputStreamReader(entityStream, StandardCharsets.UTF_8)) {
Class<?> clazz = (Class<?>) genericType;
return translator.fromYaml(streamReader, clazz);
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/aaf/AafAuthFilter.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/aaf/AafAuthFilter.java
deleted file mode 100644
index df1f6044..00000000
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/aaf/AafAuthFilter.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.aaf;
-
-import javax.servlet.http.HttpServletRequest;
-import org.onap.policy.common.endpoints.http.server.AuthorizationFilter;
-
-/**
- * Generic Authorization AAF Filter Skeleton. This class will return
- * a permission in AAF format. Subclasses are responsible to provide
- * the AAF permission type and instance.
- */
-public abstract class AafAuthFilter extends AuthorizationFilter {
-
- public static final String DEFAULT_NAMESPACE = "org.onap.policy";
-
- @Override
- protected String getRole(HttpServletRequest request) {
- return
- String.format("%s|%s|%s", getPermissionType(request), getPermissionInstance(request),
- request.getMethod().toLowerCase());
- }
-
- protected abstract String getPermissionType(HttpServletRequest request);
-
- protected abstract String getPermissionInstance(HttpServletRequest request);
-}
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/aaf/AafGranularAuthFilter.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/aaf/AafGranularAuthFilter.java
deleted file mode 100644
index 27b15a9c..00000000
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/aaf/AafGranularAuthFilter.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.aaf;
-
-import javax.servlet.http.HttpServletRequest;
-import org.onap.policy.common.utils.network.NetworkUtil;
-
-/**
- * This generic class allows the mapping of REST APIs to AAF permissions
- * to be evaluated in an AAF context. This class can be used for
- * highly granular permissions where each REST resource can be directly
- * mapped transparently to an AAF permission type, the instance being the host
- * server, and the HTTP method corresponding to the action.
- * Subclasses are responsible to provide the root permission prefix, typically
- * the namespace.
- */
-public abstract class AafGranularAuthFilter extends AafAuthFilter {
-
- @Override
- protected String getPermissionType(HttpServletRequest request) {
- return getPermissionTypeRoot() + request.getRequestURI().replace('/', '.');
- }
-
- @Override
- protected String getPermissionInstance(HttpServletRequest request) {
- return NetworkUtil.getHostname();
- }
-
- public abstract String getPermissionTypeRoot();
-}
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 d809479a..d4c392b9 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
@@ -2,8 +2,9 @@
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2019 Nordix Foundation.
+ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019-2020,2023 Nordix Foundation.
+ * Modifications Copyright (C) 2021 Bell Canada. 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.
@@ -21,11 +22,13 @@
package org.onap.policy.common.endpoints.http.server.internal;
-import io.swagger.jersey.config.JerseyJaxrsConfig;
-import java.util.HashMap;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.servlet.ServletContainer;
+import org.onap.policy.common.endpoints.http.server.JsonExceptionMapper;
+import org.onap.policy.common.gson.GsonMessageBodyHandler;
import org.onap.policy.common.utils.network.NetworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +38,7 @@ import org.slf4j.LoggerFactory;
*
* <p>Note: the serialization provider will always be added to the server's class providers, as will the swagger
* providers (assuming swagger has been enabled). This happens whether {@link #addServletClass(String, String)} is used
- * or {@link #addServletPackage(String, String)} is used. Thus it's possible to have both the server's class provider
+ * or {@link #addServletPackage(String, String)} is used. Thus, it's possible to have both the server's class provider
* property and the server's package provider property populated.
*/
public class JettyJerseyServer extends JettyServletServer {
@@ -61,27 +64,17 @@ public class JettyJerseyServer extends JettyServletServer {
protected static final String SWAGGER_PRETTY_PRINT = "swagger.pretty.print";
/**
- * Jersey Jackson Classes Init Param Value.
+ * Jersey GSON Classes Init Param Value.
*/
- protected static final String JERSEY_JACKSON_INIT_CLASSNAMES_PARAM_VALUE =
- "org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJsonProvider";
+ protected static final String JERSEY_GSON_INIT_CLASSNAMES_PARAM_VALUE =
+ String.join(",", GsonMessageBodyHandler.class.getName(), JsonExceptionMapper.class.getName());
/**
- * Jersey Swagger Classes Init Param Value.
- */
- protected static final String SWAGGER_INIT_CLASSNAMES_PARAM_VALUE =
- "io.swagger.jaxrs.listing.ApiListingResource," + "io.swagger.jaxrs.listing.SwaggerSerializers";
- /**
* Logger.
*/
protected static Logger logger = LoggerFactory.getLogger(JettyJerseyServer.class);
/**
- * Container for servlets.
- */
- protected HashMap<String, ServletHolder> servlets = new HashMap<>();
-
- /**
* Swagger ID.
*/
protected String swaggerId = null;
@@ -89,7 +82,7 @@ public class JettyJerseyServer extends JettyServletServer {
/**
* The serialization provider to be used when classes are added to the service.
*/
- private String classProvider = JERSEY_JACKSON_INIT_CLASSNAMES_PARAM_VALUE;
+ private String classProvider = JERSEY_GSON_INIT_CLASSNAMES_PARAM_VALUE;
/**
* Constructor.
@@ -98,14 +91,15 @@ public class JettyJerseyServer extends JettyServletServer {
* @param https enable https?
* @param host host server host
* @param port port server port
+ * @param sniHostCheck SNI Host checking flag
* @param swagger support swagger?
* @param contextPath context path
- *
* @throws IllegalArgumentException in invalid arguments are provided
*/
- public JettyJerseyServer(String name, boolean https, String host, int port, String contextPath, boolean swagger) {
+ public JettyJerseyServer(String name, boolean https, String host, int port, boolean sniHostCheck,
+ String contextPath, boolean swagger) {
- super(name, https, host, port, contextPath);
+ super(name, https, host, port, sniHostCheck, contextPath);
if (swagger) {
this.swaggerId = "swagger-" + this.port;
attachSwaggerServlet(https);
@@ -117,7 +111,10 @@ public class JettyJerseyServer extends JettyServletServer {
*/
protected void attachSwaggerServlet(boolean https) {
- ServletHolder swaggerServlet = context.addServlet(JerseyJaxrsConfig.class, "/");
+ ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
+ handler.setContextPath("/");
+
+ ServletHolder swaggerServlet = handler.addServlet(ServletContainer.class, "/*");
String hostname = this.connector.getHost();
if (StringUtils.isBlank(hostname) || hostname.equals(NetworkUtil.IPV4_WILDCARD_ADDRESS)) {
@@ -125,7 +122,7 @@ public class JettyJerseyServer extends JettyServletServer {
}
swaggerServlet.setInitParameter(SWAGGER_API_BASEPATH,
- ((https) ? "https://" : "http://") + hostname + ":" + this.connector.getPort() + "/");
+ ((https) ? "https://" : "http://") + hostname + ":" + this.connector.getPort() + "/");
swaggerServlet.setInitParameter(SWAGGER_CONTEXT_ID, swaggerId);
swaggerServlet.setInitParameter(SWAGGER_SCANNER_ID, swaggerId);
swaggerServlet.setInitParameter(SWAGGER_PRETTY_PRINT, "true");
@@ -145,21 +142,16 @@ public class JettyJerseyServer extends JettyServletServer {
* @throws IllegalArgumentException if invalid arguments are provided
*/
protected synchronized ServletHolder getServlet(String servletPath) {
-
- return servlets.computeIfAbsent(servletPath, key -> {
-
- ServletHolder jerseyServlet =
- context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, servletPath);
- jerseyServlet.setInitOrder(0);
-
- return jerseyServlet;
- });
+ ServletHolder jerseyServlet =
+ super.getServlet(org.glassfish.jersey.servlet.ServletContainer.class, servletPath);
+ jerseyServlet.setInitOrder(0);
+ return jerseyServlet;
}
@Override
public synchronized void addServletPackage(String servletPath, String restPackage) {
String servPath = servletPath;
- if (restPackage == null || restPackage.isEmpty()) {
+ if (StringUtils.isBlank(restPackage)) {
throw new IllegalArgumentException("No discoverable REST package provided");
}
@@ -189,7 +181,7 @@ public class JettyJerseyServer extends JettyServletServer {
@Override
public synchronized void addServletClass(String servletPath, String restClass) {
- if (restClass == null || restClass.isEmpty()) {
+ if (StringUtils.isBlank(restClass)) {
throw new IllegalArgumentException("No discoverable REST class provided");
}
@@ -232,8 +224,8 @@ public class JettyJerseyServer extends JettyServletServer {
initClasses = classProvider;
if (this.swaggerId != null) {
- initClasses += "," + SWAGGER_INIT_CLASSNAMES_PARAM_VALUE;
-
+ jerseyServlet.setInitParameter("jersey.config.server.provider.packages",
+ "io.swagger.v3.jaxrs2.integration.resources,io.swagger.sample.resource");
jerseyServlet.setInitParameter(SWAGGER_CONTEXT_ID, swaggerId);
jerseyServlet.setInitParameter(SWAGGER_SCANNER_ID, swaggerId);
}
@@ -254,9 +246,9 @@ public class JettyJerseyServer extends JettyServletServer {
@Override
public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("JettyJerseyServer [servlets=").append(servlets).append(", swaggerId=").append(swaggerId)
- .append(", toString()=").append(super.toString()).append("]");
- return builder.toString();
+ return "JettyJerseyServer [Jerseyservlets=" + servlets
+ + ", swaggerId=" + swaggerId
+ + ", toString()=" + super.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 133adade..78858a77 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
@@ -2,7 +2,9 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019-2020, 2023-2024 Nordix Foundation.
+ * Modifications Copyright (C) 2020-2021 Bell Canada. 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.
@@ -20,9 +22,15 @@
package org.onap.policy.common.endpoints.http.server.internal;
-import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.prometheus.client.hotspot.DefaultExports;
+import io.prometheus.client.servlet.jakarta.exporter.MetricsServlet;
+import jakarta.servlet.Servlet;
import java.util.EnumSet;
-import javax.servlet.DispatcherType;
+import java.util.HashMap;
+import java.util.Map;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.ToString;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
@@ -35,58 +43,70 @@ import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.Slf4jRequestLogWriter;
-import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Credential;
import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.onap.aaf.cadi.filter.CadiFilter;
import org.onap.policy.common.endpoints.http.server.HttpServletServer;
-import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Http Server implementation using Embedded Jetty.
*/
+@ToString
public abstract class JettyServletServer implements HttpServletServer, Runnable {
/**
* Keystore/Truststore system property names.
*/
public static final String SYSTEM_KEYSTORE_PROPERTY_NAME = "javax.net.ssl.keyStore";
- public static final String SYSTEM_KEYSTORE_PASSWORD_PROPERTY_NAME = "javax.net.ssl.keyStorePassword"; //NOSONAR
+ public static final String SYSTEM_KEYSTORE_PASSWORD_PROPERTY_NAME = "javax.net.ssl.keyStorePassword"; // NOSONAR
public static final String SYSTEM_TRUSTSTORE_PROPERTY_NAME = "javax.net.ssl.trustStore";
- public static final String SYSTEM_TRUSTSTORE_PASSWORD_PROPERTY_NAME = "javax.net.ssl.trustStorePassword"; //NOSONAR
+ public static final String SYSTEM_TRUSTSTORE_PASSWORD_PROPERTY_NAME = "javax.net.ssl.trustStorePassword"; // NOSONAR
/**
* Logger.
*/
- private static Logger logger = LoggerFactory.getLogger(JettyServletServer.class);
+ private static final Logger logger = LoggerFactory.getLogger(JettyServletServer.class);
+
+ private static final String NOT_SUPPORTED = " is not supported on this type of jetty server";
/**
* Server name.
*/
+ @Getter
protected final String name;
/**
* Server host address.
*/
+ @Getter
protected final String host;
/**
* Server port to bind.
*/
+ @Getter
protected final int port;
/**
- * Server auth user name.
+ * Should SNI host checking be done.
+ */
+ @Getter
+ protected boolean sniHostCheck;
+
+ /**
+ * Server auth username.
*/
+ @Getter
protected String user;
/**
* Server auth password name.
*/
+ @Getter
protected String password;
/**
@@ -112,12 +132,18 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
/**
* Jetty thread.
*/
- protected volatile Thread jettyThread;
+ protected Thread jettyThread;
+
+ /**
+ * Container for default servlets.
+ */
+ protected final Map<String, ServletHolder> servlets = new HashMap<>();
/**
* Start condition.
*/
- protected Object startCondition = new Object();
+ @ToString.Exclude
+ protected final Object startCondition = new Object();
/**
* Constructor.
@@ -125,11 +151,13 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
* @param name server name
* @param host server host
* @param port server port
+ * @param sniHostCheck SNI Host checking flag
* @param contextPath context path
*
* @throws IllegalArgumentException if invalid parameters are passed in
*/
- public JettyServletServer(String name, boolean https, String host, int port, String contextPath) {
+ protected JettyServletServer(String name, boolean https, String host, int port, boolean sniHostCheck,
+ String contextPath) {
String srvName = name;
if (srvName == null || srvName.isEmpty()) {
@@ -154,6 +182,7 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
this.host = srvHost;
this.port = port;
+ this.sniHostCheck = sniHostCheck;
this.contextPath = ctxtPath;
@@ -162,8 +191,7 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
this.jettyServer = new Server();
- CustomRequestLog requestLog =
- new CustomRequestLog(new Slf4jRequestLogWriter(), CustomRequestLog.EXTENDED_NCSA_FORMAT);
+ var requestLog = new CustomRequestLog(new Slf4jRequestLogWriter(), CustomRequestLog.EXTENDED_NCSA_FORMAT);
this.jettyServer.setRequestLog(requestLog);
if (https) {
@@ -181,8 +209,8 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
this.jettyServer.setHandler(context);
}
- public JettyServletServer(String name, String host, int port, String contextPath) {
- this(name, false, host, port, contextPath);
+ protected JettyServletServer(String name, String host, int port, boolean sniHostCheck, String contextPath) {
+ this(name, false, host, port, sniHostCheck, contextPath);
}
@Override
@@ -196,7 +224,20 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
tempFilterPath = "/*";
}
- context.addFilter(filterClass, tempFilterPath, EnumSet.of(DispatcherType.INCLUDE, DispatcherType.REQUEST));
+ context.addFilter(filterClass, tempFilterPath,
+ EnumSet.of(jakarta.servlet.DispatcherType.INCLUDE, jakarta.servlet.DispatcherType.REQUEST));
+ }
+
+ protected ServletHolder getServlet(@NonNull Class<? extends Servlet> servlet, @NonNull String servletPath) {
+ synchronized (servlets) {
+ return servlets.computeIfAbsent(servletPath, key -> context.addServlet(servlet, servletPath));
+ }
+ }
+
+ protected ServletHolder getServlet(String servletClass, String servletPath) {
+ synchronized (servlets) {
+ return servlets.computeIfAbsent(servletPath, key -> context.addServlet(servletClass, servletPath));
+ }
}
/**
@@ -205,32 +246,35 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
* @return the server connector
*/
public ServerConnector httpsConnector() {
- SslContextFactory sslContextFactory = new SslContextFactory.Server();
+ SslContextFactory.Server sslContextFactoryServer = new SslContextFactory.Server();
String keyStore = System.getProperty(SYSTEM_KEYSTORE_PROPERTY_NAME);
if (keyStore != null) {
- sslContextFactory.setKeyStorePath(keyStore);
+ sslContextFactoryServer.setKeyStorePath(keyStore);
String ksPassword = System.getProperty(SYSTEM_KEYSTORE_PASSWORD_PROPERTY_NAME);
if (ksPassword != null) {
- sslContextFactory.setKeyStorePassword(ksPassword);
+ sslContextFactoryServer.setKeyStorePassword(ksPassword);
}
}
String trustStore = System.getProperty(SYSTEM_TRUSTSTORE_PROPERTY_NAME);
if (trustStore != null) {
- sslContextFactory.setTrustStorePath(trustStore);
+ sslContextFactoryServer.setTrustStorePath(trustStore);
String tsPassword = System.getProperty(SYSTEM_TRUSTSTORE_PASSWORD_PROPERTY_NAME);
if (tsPassword != null) {
- sslContextFactory.setTrustStorePassword(tsPassword);
+ sslContextFactoryServer.setTrustStorePassword(tsPassword);
}
}
- HttpConfiguration https = new HttpConfiguration();
- https.addCustomizer(new SecureRequestCustomizer());
- return new ServerConnector(jettyServer, sslContextFactory, new HttpConnectionFactory(https));
+ var httpsConfiguration = new HttpConfiguration();
+ SecureRequestCustomizer src = new SecureRequestCustomizer();
+ src.setSniHostCheck(sniHostCheck);
+ httpsConfiguration.addCustomizer(src);
+
+ return new ServerConnector(jettyServer, sslContextFactoryServer, new HttpConnectionFactory(httpsConfiguration));
}
public ServerConnector httpConnector() {
@@ -238,21 +282,6 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
}
@Override
- public void setAafAuthentication(String filterPath) {
- this.addFilterClass(filterPath, CadiFilter.class.getName());
- }
-
- @Override
- public boolean isAaf() {
- for (FilterHolder filter : context.getServletHandler().getFilters()) {
- if (CadiFilter.class.getName().equals(filter.getClassName())) {
- return true;
- }
- }
- return false;
- }
-
- @Override
public void setBasicAuthentication(String user, String password, String servletPath) {
String srvltPath = servletPath;
@@ -264,22 +293,26 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
srvltPath = "/*";
}
- final HashLoginService hashLoginService = new HashLoginService();
- final UserStore userStore = new UserStore();
- userStore.addUser(user, Credential.getCredential(password), new String[] {"user"});
+ final var hashLoginService = new HashLoginService();
+ final var userStore = new UserStore();
+ userStore.addUser(user, Credential.getCredential(password), new String[] {
+ "user"
+ });
hashLoginService.setUserStore(userStore);
hashLoginService.setName(this.connector.getName() + "-login-service");
- Constraint constraint = new Constraint();
+ var constraint = new Constraint();
constraint.setName(Constraint.__BASIC_AUTH);
- constraint.setRoles(new String[] {"user"});
+ constraint.setRoles(new String[] {
+ "user"
+ });
constraint.setAuthenticate(true);
- ConstraintMapping constraintMapping = new ConstraintMapping();
+ var constraintMapping = new ConstraintMapping();
constraintMapping.setConstraint(constraint);
constraintMapping.setPathSpec(srvltPath);
- ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
+ var securityHandler = new ConstraintSecurityHandler();
securityHandler.setAuthenticator(new BasicAuthenticator());
securityHandler.setRealmName(this.connector.getName() + "-realm");
securityHandler.addConstraintMapping(constraintMapping);
@@ -310,6 +343,11 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
}
this.jettyServer.join();
+
+ } catch (InterruptedException e) {
+ logger.error("{}: error found while bringing up server", this, e);
+ Thread.currentThread().interrupt();
+
} catch (Exception e) {
logger.error("{}: error found while bringing up server", this, e);
}
@@ -415,12 +453,13 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
this.stop();
- if (this.jettyThread == null) {
- return;
+ Thread jettyThreadCopy;
+ synchronized (this) {
+ if ((jettyThreadCopy = this.jettyThread) == null) {
+ return;
+ }
}
- Thread jettyThreadCopy = this.jettyThread;
-
if (jettyThreadCopy.isAlive()) {
try {
jettyThreadCopy.join(2000L);
@@ -451,58 +490,44 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable
}
@Override
- public int getPort() {
- return this.port;
+ public void setSerializationProvider(String provider) {
+ throw new UnsupportedOperationException("setSerializationProvider()" + NOT_SUPPORTED);
}
- /**
- * Get name.
- *
- * @return the name
- */
@Override
- public String getName() {
- return name;
+ public void addServletClass(String servletPath, String servletClass) {
+ throw new UnsupportedOperationException("addServletClass()" + NOT_SUPPORTED);
}
- /**
- * Get host.
- *
- * @return the host
- */
- public String getHost() {
- return host;
+ @Override
+ public void addStdServletClass(@NonNull String servletPath, @NonNull String plainServletClass) {
+ this.getServlet(plainServletClass, servletPath);
}
- /**
- * Get user.
- *
- * @return the user
- */
- public String getUser() {
- return user;
+ @Override
+ public void setPrometheus(String metricsPath) {
+ this.getServlet(MetricsServlet.class, metricsPath);
+ DefaultExports.initialize();
}
- /**
- * Get password.
- *
- * @return the password
- */
- @JsonIgnore
- @GsonJsonIgnore
- public String getPassword() {
- return password;
+ @Override
+ public boolean isPrometheus() {
+ for (ServletHolder servlet : context.getServletHandler().getServlets()) {
+ if (MetricsServlet.class.getName().equals(servlet.getClassName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void addServletPackage(String servletPath, String restPackage) {
+ throw new UnsupportedOperationException("addServletPackage()" + NOT_SUPPORTED);
}
@Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("JettyServer [name=").append(name).append(", host=").append(host).append(", port=").append(port)
- .append(", user=").append(user).append(", password=").append(password != null).append(", contextPath=")
- .append(contextPath).append(", jettyServer=").append(jettyServer).append(", context=")
- .append(this.context).append(", connector=").append(connector).append(", jettyThread=")
- .append(jettyThread).append("]");
- return builder.toString();
+ public void addServletResource(String servletPath, String resourceBase) {
+ throw new UnsupportedOperationException("addServletResource()" + NOT_SUPPORTED);
}
}
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 00000000..ee2b0540
--- /dev/null
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyStaticResourceServer.java
@@ -0,0 +1,107 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020, 2023-2024 Nordix Foundation.
+ * Modifications Copyright (C) 2021 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.endpoints.http.server.internal;
+
+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);
+
+ /**
+ * Constructor.
+ *
+ * @param name name
+ * @param https enable https?
+ * @param host host server host
+ * @param port port server port
+ * @param sniHostCheck SNI Host checking flag
+ * @param contextPath context path
+ * @throws IllegalArgumentException in invalid arguments are provided
+ */
+ public JettyStaticResourceServer(String name, boolean https, String host, int port, boolean sniHostCheck,
+ String contextPath) {
+
+ super(name, https, host, port, sniHostCheck, 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 servletPath) {
+ return super.getServlet(DefaultServlet.class, servletPath);
+ }
+
+ @Override
+ public synchronized void addServletResource(String servletPath, String resourceBase) {
+
+ if (StringUtils.isBlank(resourceBase)) {
+ throw new IllegalArgumentException("No resourceBase provided");
+ }
+
+ if (servletPath == null || servletPath.isEmpty()) {
+ servletPath = "/*";
+ }
+
+ ServletHolder defaultServlet = this.getDefaultServlet(servletPath);
+
+ defaultServlet.setInitParameter(SERVLET_HOLDER_RESOURCE_BASE, resourceBase);
+ 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());
+ }
+ }
+}