From 881c32ec109f0fff6f5661940ad035c3dfc0c7d9 Mon Sep 17 00:00:00 2001 From: Jorge Hernandez Date: Thu, 25 May 2017 16:44:15 -0500 Subject: [POLICY-16] generic introduction of swagger On a per-server basis append /swagger.json or /swagger.yaml ie: HTTP GET :6969/swagger.json HTTP GET :9696/swagger.json Resulting specification can be used by swagger clients. Change-Id: I4b1a8b53d50b1528664150934b04e92447e4d4d7 Signed-off-by: Jorge Hernandez --- .../drools/http/server/HttpServletServer.java | 16 +- .../http/server/HttpServletServerFactory.java | 75 +++++++- .../http/server/internal/JettyJerseyServer.java | 195 ++++++++++++++++----- 3 files changed, 228 insertions(+), 58 deletions(-) (limited to 'policy-endpoints/src/main/java') diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServer.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServer.java index 5f5dd787..106602bc 100644 --- a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServer.java +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServer.java @@ -44,10 +44,10 @@ public interface HttpServletServer extends Startable { /** * adds a JAX-RS servlet class to serve REST requests * - * @param servletPath - * @param restClass - * @throws IllegalArgumentException - * @throws IllegalStateException + * @param servletPath servlet path + * @param restClass JAX-RS API Class + * @throws IllegalArgumentException unable to process because of invalid input + * @throws IllegalStateException unable to process because of invalid state */ public void addServletClass(String servletPath, String restClass) throws IllegalArgumentException, IllegalStateException; @@ -55,10 +55,10 @@ public interface HttpServletServer extends Startable { /** * adds a package containing JAX-RS classes to serve REST requests * - * @param servletPath - * @param restPackage - * @throws IllegalArgumentException - * @throws IllegalStateException + * @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 */ public void addServletPackage(String servletPath, String restPackage) throws IllegalArgumentException, IllegalStateException; diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServerFactory.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServerFactory.java index bd5ae242..40f5c9ad 100644 --- a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServerFactory.java +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServerFactory.java @@ -31,36 +31,87 @@ import org.openecomp.policy.drools.http.server.internal.JettyJerseyServer; import org.openecomp.policy.drools.properties.PolicyProperties; /** - * Jetty Server Factory + * Factory of HTTP Servlet-Enabled Servlets */ public interface HttpServletServerFactory { - public HttpServletServer build(String name, String host, int port, String contextPath, boolean managed) - throws IllegalArgumentException; + /** + * builds an http server with support for servlets + * + * @param name name + * @param host binding host + * @param port port + * @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 + */ + public HttpServletServer build(String name, String host, int port, String contextPath, + boolean swagger, boolean managed) + throws IllegalArgumentException; + /** + * list of http servers per properties + * + * @param properties properties based configuration + * @return list of http servers + * @throws IllegalArgumentException when invalid parameters are provided + */ public ArrayList build(Properties properties) throws IllegalArgumentException; + /** + * gets a server based on the port + * + * @param port port + * @return http server + */ public HttpServletServer get(int port); + + /** + * provides an inventory of servers + * + * @return inventory of servers + */ public List inventory(); + + /** + * destroys server bound to a port + * @param port + */ public void destroy(int port); + + /** + * destroys the factory and therefore all servers + */ public void destroy(); } +/** + * Indexed factory implementation + */ class IndexedHttpServletServerFactory implements HttpServletServerFactory { - protected static Logger logger = FlexLogger.getLogger(IndexedHttpServletServerFactory.class); + /** + * logger + */ + protected static Logger logger = FlexLogger.getLogger(IndexedHttpServletServerFactory.class); - protected HashMap servers = new HashMap(); + /** + * servers index + */ + protected HashMap servers = new HashMap(); @Override public synchronized HttpServletServer build(String name, String host, int port, - String contextPath, boolean managed) + String contextPath, boolean swagger, + boolean managed) throws IllegalArgumentException { if (servers.containsKey(port)) return servers.get(port); - JettyJerseyServer server = new JettyJerseyServer(name, host, port, contextPath); + JettyJerseyServer server = new JettyJerseyServer(name, host, port, contextPath, swagger); if (managed) servers.put(port, server); @@ -140,7 +191,15 @@ class IndexedHttpServletServerFactory implements HttpServletServerFactory { managed = Boolean.parseBoolean(managedString); } - HttpServletServer service = build(serviceName, hostName, servicePort, contextUriPath, managed); + String swaggerString = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_HTTP_SWAGGER_SUFFIX); + boolean swagger = false; + if (swaggerString != null && !swaggerString.isEmpty()) { + swagger = Boolean.parseBoolean(swaggerString); + } + + HttpServletServer service = build(serviceName, hostName, servicePort, contextUriPath, swagger, managed); if (userName != null && !userName.isEmpty() && password != null && !password.isEmpty()) { service.setBasicAuthentication(userName, password, authUriPath); } diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/internal/JettyJerseyServer.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/internal/JettyJerseyServer.java index 4914a4cb..5bc320e5 100644 --- a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/internal/JettyJerseyServer.java +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/internal/JettyJerseyServer.java @@ -19,52 +19,132 @@ */ package org.openecomp.policy.drools.http.server.internal; -import java.util.ArrayList; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.HashMap; import org.eclipse.jetty.servlet.ServletHolder; - import org.openecomp.policy.common.logging.flexlogger.FlexLogger; import org.openecomp.policy.common.logging.flexlogger.Logger; +import io.swagger.jersey.config.JerseyJaxrsConfig; + /** - * REST Jetty Server using Jersey + * REST Jetty Server that uses Jersey Servlets to support JAX-RS Web Services */ public class JettyJerseyServer extends JettyServletServer { - protected static final String JERSEY_PACKAGES_PARAM = "jersey.config.server.provider.packages"; - protected static final String JERSEY_CLASSNAMES_PARAM = "jersey.config.server.provider.classnames"; + /** + * Jersey Packages Init Param Name + */ + protected static final String JERSEY_INIT_PACKAGES_PARAM_NAME = "jersey.config.server.provider.packages"; + + /** + * Jersey Packages Init Param Value + */ + protected static final String JERSEY_INIT_PACKAGES_PARAM_VALUE = "com.fasterxml.jackson.jaxrs.json"; + + /** + * Swagger Packages + */ + protected static final String SWAGGER_INIT_PACKAGES_PARAM_VALUE = "io.swagger.jaxrs.listing"; + /** + * Jersey Classes Init Param Name + */ + protected static final String JERSEY_INIT_CLASSNAMES_PARAM_NAME = "jersey.config.server.provider.classnames"; + + /** + * Jersey Jackson Classes Init Param Value + */ + protected static final String JERSEY_JACKSON_INIT_CLASSNAMES_PARAM_VALUE = "com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider"; + + /** + * 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 = FlexLogger.getLogger(JettyJerseyServer.class); - protected ArrayList packages = new ArrayList(); - protected HashMap servlets = - new HashMap(); + /** + * Container for servlets + */ + protected HashMap servlets = new HashMap(); + + /** + * Swagger ID + */ + protected String swaggerId = null; - public JettyJerseyServer(String name, String host, int port, String contextPath) - throws IllegalArgumentException { + /** + * Constructor + * + * @param name name + * @param host host server host + * @param port port server port + * @param swagger support swagger? + * @param contextPath context path + * + * @throws IllegalArgumentException in invalid arguments are provided + */ + public JettyJerseyServer(String name, String host, int port, String contextPath, boolean swagger) + throws IllegalArgumentException { + super(name, host, port, contextPath); + if (swagger) { + this.swaggerId = "swagger-" + this.port; + attachSwaggerServlet(); + } } - protected synchronized ServletHolder getServlet(String servletPath) - throws IllegalArgumentException { + /** + * attaches a swagger initialization servlet + */ + protected void attachSwaggerServlet() { + + ServletHolder swaggerServlet = context.addServlet(JerseyJaxrsConfig.class, "/"); + + String hostname = this.connector.getHost(); + if (hostname == null || hostname.isEmpty() || hostname.equals("0.0.0.0")) { + try { + hostname = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + logger.warn("can't resolve connector's hostname: " + this); + hostname = "localhost"; + } + } + + swaggerServlet.setInitParameter("swagger.api.basepath", + "http://" + hostname + ":" + this.connector.getPort() + "/"); + swaggerServlet.setInitParameter("swagger.context.id", swaggerId); + swaggerServlet.setInitParameter("swagger.scanner.id", swaggerId); + swaggerServlet.setInitParameter("swagger.pretty.print", "true"); + swaggerServlet.setInitOrder(2); - if (servletPath == null || servletPath.isEmpty()) - servletPath = "/*"; + if (logger.isDebugEnabled()) + logger.debug(this + "Swagger Servlet has been attached: " + swaggerServlet.dump()); + } + + /** + * retrieves cached server based on servlet path + * + * @param servletPath servlet path + * @return the jetty servlet holder + * + * @throws IllegalArgumentException if invalid arguments are provided + */ + protected synchronized ServletHolder getServlet(String servletPath) + throws IllegalArgumentException { ServletHolder jerseyServlet = servlets.get(servletPath); if (jerseyServlet == null) { jerseyServlet = context.addServlet (org.glassfish.jersey.servlet.ServletContainer.class, servletPath); jerseyServlet.setInitOrder(0); - String initPackages = - jerseyServlet.getInitParameter(JERSEY_PACKAGES_PARAM); - if (initPackages == null) { - jerseyServlet.setInitParameter( - JERSEY_PACKAGES_PARAM, - "com.jersey.jaxb,com.fasterxml.jackson.jaxrs.json"); - } - this.servlets.put(servletPath, jerseyServlet); + servlets.put(servletPath, jerseyServlet); } return jerseyServlet; @@ -76,19 +156,36 @@ public class JettyJerseyServer extends JettyServletServer { if (restPackage == null || restPackage.isEmpty()) throw new IllegalArgumentException("No discoverable REST package provided"); + + if (servletPath == null || servletPath.isEmpty()) + servletPath = "/*"; ServletHolder jerseyServlet = this.getServlet(servletPath); - if (jerseyServlet == null) - throw new IllegalStateException("Unexpected, no Jersey Servlet class"); + + String initClasses = + jerseyServlet.getInitParameter(JERSEY_INIT_CLASSNAMES_PARAM_NAME); + if (initClasses != null && !initClasses.isEmpty()) + logger.warn("Both packages and classes are used in Jetty+Jersey Configuration: " + restPackage); String initPackages = - jerseyServlet.getInitParameter(JERSEY_PACKAGES_PARAM); - if (initPackages == null) - throw new IllegalStateException("Unexpected, no Init Parameters loaded"); + jerseyServlet.getInitParameter(JERSEY_INIT_PACKAGES_PARAM_NAME); + if (initPackages == null) { + if (this.swaggerId != null) { + initPackages = JERSEY_INIT_PACKAGES_PARAM_VALUE + "," + + SWAGGER_INIT_PACKAGES_PARAM_VALUE + "," + + restPackage; + + jerseyServlet.setInitParameter("swagger.context.id", swaggerId); + jerseyServlet.setInitParameter("swagger.scanner.id", swaggerId); + } else { + initPackages = JERSEY_INIT_PACKAGES_PARAM_VALUE + "," + + restPackage; + } + } else { + initPackages = initPackages + "," + restPackage; + } - jerseyServlet.setInitParameter( - JERSEY_PACKAGES_PARAM, - initPackages + "," + restPackage); + jerseyServlet.setInitParameter(JERSEY_INIT_PACKAGES_PARAM_NAME, initPackages); if (logger.isDebugEnabled()) logger.debug(this + "Added REST Package: " + jerseyServlet.dump()); @@ -100,31 +197,45 @@ public class JettyJerseyServer extends JettyServletServer { if (restClass == null || restClass.isEmpty()) throw new IllegalArgumentException("No discoverable REST class provided"); + + if (servletPath == null || servletPath.isEmpty()) + servletPath = "/*"; ServletHolder jerseyServlet = this.getServlet(servletPath); - if (jerseyServlet == null) - throw new IllegalStateException("Unexpected, no Jersey Servlet class"); + + String initPackages = + jerseyServlet.getInitParameter(JERSEY_INIT_PACKAGES_PARAM_NAME); + if (initPackages != null && !initPackages.isEmpty()) + logger.warn("Both classes and packages are used in Jetty+Jersey Configuration: " + restClass); String initClasses = - jerseyServlet.getInitParameter(JERSEY_CLASSNAMES_PARAM); - if (initClasses == null) - initClasses = restClass; - else + jerseyServlet.getInitParameter(JERSEY_INIT_CLASSNAMES_PARAM_NAME); + if (initClasses == null) { + if (this.swaggerId != null) { + initClasses = JERSEY_JACKSON_INIT_CLASSNAMES_PARAM_VALUE + "," + + SWAGGER_INIT_CLASSNAMES_PARAM_VALUE + "," + + restClass; + + jerseyServlet.setInitParameter("swagger.context.id", swaggerId); + jerseyServlet.setInitParameter("swagger.scanner.id", swaggerId); + } else { + initClasses = JERSEY_JACKSON_INIT_CLASSNAMES_PARAM_VALUE + "," + restClass; + } + } else { initClasses = initClasses + "," + restClass; + } - jerseyServlet.setInitParameter( - JERSEY_CLASSNAMES_PARAM, - initClasses); + jerseyServlet.setInitParameter(JERSEY_INIT_CLASSNAMES_PARAM_NAME, initClasses); if (logger.isDebugEnabled()) logger.debug(this + "Added REST Class: " + jerseyServlet.dump()); } - + @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("JerseyJettyServer [packages=").append(packages).append(", servlets=").append(servlets) - .append(", toString()=").append(super.toString()).append("]"); + builder.append("JettyJerseyServer [servlets=").append(servlets).append(", swaggerId=").append(swaggerId) + .append(", toString()=").append(super.toString()).append("]"); return builder.toString(); } } -- cgit 1.2.3-korg