diff options
Diffstat (limited to 'policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java')
-rw-r--r-- | policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java | 209 |
1 files changed, 117 insertions, 92 deletions
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); } } |