diff options
author | Jorge Hernandez <jh1730@att.com> | 2017-05-25 16:44:15 -0500 |
---|---|---|
committer | Jorge Hernandez <jh1730@att.com> | 2017-05-25 16:44:15 -0500 |
commit | 881c32ec109f0fff6f5661940ad035c3dfc0c7d9 (patch) | |
tree | 79070ad7386cc9b62cf504ebf62ec8702792be4d | |
parent | f354096969e91aa2b3dcdc52adcc2bde1b3b0b74 (diff) |
[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 <jh1730@att.com>
20 files changed, 1849 insertions, 802 deletions
diff --git a/policy-core/src/main/java/org/openecomp/policy/drools/properties/PolicyProperties.java b/policy-core/src/main/java/org/openecomp/policy/drools/properties/PolicyProperties.java index 1274e08c..5e7a351c 100644 --- a/policy-core/src/main/java/org/openecomp/policy/drools/properties/PolicyProperties.java +++ b/policy-core/src/main/java/org/openecomp/policy/drools/properties/PolicyProperties.java @@ -90,6 +90,7 @@ public interface PolicyProperties { public static final String PROPERTY_HTTP_REST_URIPATH_SUFFIX = ".restUriPath"; public static final String PROPERTY_HTTP_HTTPS_SUFFIX = ".https"; + public static final String PROPERTY_HTTP_SWAGGER_SUFFIX = ".swagger"; /* HTTP Client Properties */ diff --git a/policy-endpoints/pom.xml b/policy-endpoints/pom.xml index cd79f6a7..dba7349f 100644 --- a/policy-endpoints/pom.xml +++ b/policy-endpoints/pom.xml @@ -89,7 +89,6 @@ <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> - <version>${jersey.version}</version> </dependency> <dependency> @@ -127,6 +126,17 @@ <artifactId>jackson-datatype-jsr310</artifactId> <version>${jackson.version}</version> </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> 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<HttpServletServer> 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<HttpServletServer> 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<Integer, JettyJerseyServer> servers = new HashMap<Integer, JettyJerseyServer>(); + /** + * servers index + */ + protected HashMap<Integer, HttpServletServer> servers = new HashMap<Integer, HttpServletServer>(); @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<String> packages = new ArrayList<String>(); - protected HashMap<String, ServletHolder> servlets = - new HashMap<String, ServletHolder>(); + /** + * Container for servlets + */ + protected HashMap<String, ServletHolder> servlets = new HashMap<String, ServletHolder>(); + + /** + * 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(); } } diff --git a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpClientTest.java b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpClientTest.java index 47774b1f..cd149f7a 100644 --- a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpClientTest.java +++ b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpClientTest.java @@ -38,7 +38,7 @@ public class HttpClientTest { public void testHttpNoAuthClient() throws Exception { System.out.println("-- testHttpNoAuthClient() --"); - HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 6666, "/", true); + HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 6666, "/", false, true); server.addServletPackage("/*", this.getClass().getPackage().getName()); server.waitedStart(5000); @@ -59,7 +59,7 @@ public class HttpClientTest { public void testHttpAuthClient() throws Exception { System.out.println("-- testHttpAuthClient() --"); - HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 6666, "/", true); + HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 6666, "/", false, true); server.setBasicAuthentication("x", "y", null); server.addServletPackage("/*", this.getClass().getPackage().getName()); server.waitedStart(5000); @@ -81,7 +81,7 @@ public class HttpClientTest { public void testHttpAuthClient401() throws Exception { System.out.println("-- testHttpAuthClient401() --"); - HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 6666, "/", true); + HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 6666, "/", false, true); server.setBasicAuthentication("x", "y", null); server.addServletPackage("/*", this.getClass().getPackage().getName()); server.waitedStart(5000); diff --git a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpServerTest.java b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpServerTest.java index 94f29804..6a369814 100644 --- a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpServerTest.java +++ b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpServerTest.java @@ -31,7 +31,7 @@ import org.junit.Test; import org.openecomp.policy.drools.http.server.HttpServletServer; /** - * + * HttpServletServer JUNIT tests */ public class HttpServerTest { @@ -39,7 +39,7 @@ public class HttpServerTest { public void testSingleServer() throws Exception { System.out.println("-- testSingleServer() --"); - HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 5678, "/", true); + HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 5678, "/", false, true); server.addServletPackage("/*", this.getClass().getPackage().getName()); server.waitedStart(5000); @@ -50,6 +50,16 @@ public class HttpServerTest { String response = response(url); System.out.println("Received .. " + response); assertTrue(response.equals(echo)); + + String responseSwagger = null; + try { + URL urlSwagger = new URL("http://localhost:5678/swagger.json" + echo); + responseSwagger = response(urlSwagger); + } catch(IOException ioe) { + // Expected + } + + assertTrue(responseSwagger == null); HttpServletServer.factory.destroy(); assertTrue(HttpServletServer.factory.inventory().size() == 0); @@ -59,11 +69,11 @@ public class HttpServerTest { public void testMultipleServers() throws Exception { System.out.println("-- testMultipleServers() --"); - HttpServletServer server1 = HttpServletServer.factory.build("echo-1", "localhost", 5678, "/", true); + HttpServletServer server1 = HttpServletServer.factory.build("echo-1", "localhost", 5678, "/", true, true); server1.addServletPackage("/*", this.getClass().getPackage().getName()); server1.waitedStart(5000); - HttpServletServer server2 = HttpServletServer.factory.build("echo-2", "localhost", 5679, "/", true); + HttpServletServer server2 = HttpServletServer.factory.build("echo-2", "localhost", 5679, "/", false, true); server2.addServletPackage("/*", this.getClass().getPackage().getName()); server2.waitedStart(5000); @@ -77,11 +87,28 @@ public class HttpServerTest { System.out.println("Received .. " + response1); assertTrue(response1.equals(echo)); + URL urlSwagger = new URL("http://localhost:5678/swagger.json"); + String responseSwagger = response(urlSwagger); + + System.out.println("Received .. " + responseSwagger); + assertTrue(responseSwagger != null); + URL url2 = new URL("http://localhost:5679/junit/echo/" + echo); String response2 = response(url2); System.out.println("Received .. " + response2); assertTrue(response2.equals(echo)); + String responseSwagger2 = null; + try { + URL urlSwagger2 = new URL("http://localhost:5679/swagger.json"); + responseSwagger2 = response(urlSwagger2); + } catch(IOException ioe) { + // Expected + } + + System.out.println("Received .. " + responseSwagger2); + assertTrue(responseSwagger2 == null); + HttpServletServer.factory.destroy(); assertTrue(HttpServletServer.factory.inventory().size() == 0); } @@ -92,7 +119,7 @@ public class HttpServerTest { String randomName = UUID.randomUUID().toString(); - HttpServletServer server = HttpServletServer.factory.build(randomName, "localhost", 5678, "/", true); + HttpServletServer server = HttpServletServer.factory.build(randomName, "localhost", 5678, "/", false, true); server.addServletPackage("/*", this.getClass().getPackage().getName()); server.waitedStart(5000); @@ -118,7 +145,7 @@ public class HttpServerTest { System.out.println("-- testServiceClass() --"); String randomName = UUID.randomUUID().toString(); - HttpServletServer server = HttpServletServer.factory.build(randomName, "localhost", 5678, "/", true); + HttpServletServer server = HttpServletServer.factory.build(randomName, "localhost", 5678, "/", false, true); server.addServletClass("/*", RestEchoService.class.getCanonicalName()); server.waitedStart(5000); @@ -140,7 +167,7 @@ public class HttpServerTest { String randomName = UUID.randomUUID().toString(); - HttpServletServer server = HttpServletServer.factory.build(randomName, "localhost", 5678, "/", true); + HttpServletServer server = HttpServletServer.factory.build(randomName, "localhost", 5678, "/", false, true); server.addServletClass("/*", RestEchoService.class.getCanonicalName()); server.addServletClass("/*", RestEndpoints.class.getCanonicalName()); server.waitedStart(5000); @@ -173,6 +200,9 @@ public class HttpServerTest { while ((line = ioReader.readLine()) != null) { response += line; } + + System.out.println("R is " + response); + ioReader.close(); return response; } diff --git a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestEchoService.java b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestEchoService.java index a0320a09..b714925f 100644 --- a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestEchoService.java +++ b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestEchoService.java @@ -6,12 +6,19 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +@Api(value="echo") @Path("/junit/echo") public class RestEchoService { @GET @Path("{word}") @Produces(MediaType.TEXT_PLAIN) + @ApiOperation( + value="echoes back whatever received" + ) public String echo(@PathParam("word") String word) { return word; } diff --git a/policy-healthcheck/pom.xml b/policy-healthcheck/pom.xml index 5a409d4a..913a944c 100644 --- a/policy-healthcheck/pom.xml +++ b/policy-healthcheck/pom.xml @@ -32,7 +32,7 @@ <artifactId>policy-healthcheck</artifactId> <name>policy-healthcheck</name> - <description>Separately loadable module with healthcheck code</description> + <description>Separately loadable module to perform healthchecks of the system</description> <properties> <maven.compiler.source>1.8</maven.compiler.source> @@ -92,6 +92,11 @@ </build> <dependencies> + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + <scope>provided</scope> + </dependency> <dependency> <groupId>org.openecomp.policy.drools-pdp</groupId> <artifactId>policy-core</artifactId> diff --git a/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/RestHealthCheck.java b/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/RestHealthCheck.java index e37e758a..06854042 100644 --- a/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/RestHealthCheck.java +++ b/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/RestHealthCheck.java @@ -4,23 +4,54 @@ import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import org.openecomp.policy.drools.healthcheck.HealthCheck.Reports; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.Info; +import io.swagger.annotations.SwaggerDefinition; +import io.swagger.annotations.Tag; + @Path("/") +@Api +@Produces(MediaType.APPLICATION_JSON) +@SwaggerDefinition( + info = @Info( + description = "PDP-D Healthcheck Service", + version = "v1.0", + title = "PDP-D Healthcheck" + ), + consumes = {MediaType.APPLICATION_JSON}, + produces = {MediaType.APPLICATION_JSON}, + schemes = {SwaggerDefinition.Scheme.HTTP}, + tags = { + @Tag(name = "pdp-d-healthcheck", description = "Drools PDP Healthcheck Operations") + } +) public class RestHealthCheck { @GET - @Path("{a:healthcheck|test}") + @Path("healthcheck") @Produces(MediaType.APPLICATION_JSON) - public Reports healthcheck() { - Reports reports = HealthCheck.monitor.healthCheck(); - return reports; + @ApiOperation( + value="Perform a system healthcheck", + notes="Provides healthy status of the PDP-D plus the components defined in its configuration by using a REST interface", + response=Reports.class + ) + public Response healthcheck() { + return Response.status(Response.Status.OK).entity(HealthCheck.monitor.healthCheck()).build(); } @GET @Path("healthcheck/configuration") @Produces(MediaType.APPLICATION_JSON) + @ApiOperation( + value="Configuration", + notes="Provides the Healthcheck server configuration and monitored REST clients", + response=HealthCheck.class + ) public HealthCheck configuration() { return HealthCheck.monitor; } diff --git a/policy-management/config/policy-engine.properties b/policy-management/config/policy-engine.properties index 41456c27..27bd7651 100644 --- a/policy-management/config/policy-engine.properties +++ b/policy-management/config/policy-engine.properties @@ -18,9 +18,13 @@ ueb.sink.topics.PDPD_CONFIGURATION.partitionKey= ueb.sink.topics.PDPD_CONFIGURATION.managed=false http.server.services=CONFIG -http.server.services.CONFIG.host=localhost +http.server.services.CONFIG.host=0.0.0.0 http.server.services.CONFIG.port=9696 http.server.services.CONFIG.userName=x http.server.services.CONFIG.password=y http.server.services.CONFIG.restPackages=org.openecomp.policy.drools.server.restful +#http.server.services.CONFIG.restPackages=org.openecomp.policy.drools.server.restful,org.openecomp.policy.drools.healthcheck +#http.server.services.CONFIG.restClasses=org.openecomp.policy.drools.server.restful.RestManager,org.openecomp.policy.drools.healthcheck.RestHealthCheck +#http.server.services.CONFIG.restClasses=org.openecomp.policy.drools.server.restful.RestManager http.server.services.CONFIG.managed=false +http.server.services.CONFIG.swagger=true diff --git a/policy-management/pom.xml b/policy-management/pom.xml index 8b791e47..7feef7a8 100644 --- a/policy-management/pom.xml +++ b/policy-management/pom.xml @@ -174,7 +174,6 @@ <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> - <version>${jersey.version}</version> </dependency> <dependency> @@ -196,6 +195,11 @@ </dependency> <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + </dependency> + + <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> @@ -211,7 +215,7 @@ <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>${jackson.version}</version> - </dependency> + </dependency> <dependency> <groupId>com.google.code.gson</groupId> diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java b/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java index 4396a0ce..e404a092 100644 --- a/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java +++ b/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java @@ -49,6 +49,7 @@ import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration import org.openecomp.policy.drools.utils.ReflectionUtil; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; /** * Maven-based Drools Controller that interacts with the @@ -667,6 +668,7 @@ public class MavenDroolsController implements DroolsController { /** * {@inheritDoc} */ + @JsonProperty("sessions") @Override public List<String> getSessionNames() { return getSessionNames(true); @@ -675,6 +677,7 @@ public class MavenDroolsController implements DroolsController { /** * {@inheritDoc} */ + @JsonProperty("sessionCoordinates") @Override public List<String> getCanonicalSessionNames() { return getSessionNames(false); diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java b/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java index a4aaa856..de666165 100644 --- a/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java +++ b/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java @@ -20,8 +20,10 @@ package org.openecomp.policy.drools.server.restful; -import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.UUID; import java.util.regex.Pattern; @@ -64,69 +66,112 @@ import org.openecomp.policy.drools.protocol.configuration.PdpdConfiguration; import org.openecomp.policy.drools.system.PolicyController; import org.openecomp.policy.drools.system.PolicyEngine; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Info; +import io.swagger.annotations.SwaggerDefinition; +import io.swagger.annotations.Tag; + /** - * REST Endpoint for management of the Drools PDP + * Telemetry JAX-RS Interface to the PDP-D */ + @Path("/policy/pdp") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +@Api +@SwaggerDefinition( + info = @Info( + description = "PDP-D Telemetry Services", + version = "v1.0", + title = "PDP-D Telemetry" + ), + consumes = {MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN}, + produces = {MediaType.APPLICATION_JSON}, + schemes = {SwaggerDefinition.Scheme.HTTP}, + tags = { + @Tag(name = "pdp-d-telemetry", description = "Drools PDP Telemetry Operations") + } +) public class RestManager { /** * Logger */ private static Logger logger = FlexLogger.getLogger(RestManager.class); - /** - * gets the Policy Engine - * - * @return the Policy Engine - */ @GET @Path("engine") - @Produces(MediaType.APPLICATION_JSON) - public PolicyEngine engine() { - return PolicyEngine.manager; + @ApiOperation( + value="Retrieves the Engine Operational Status", + notes="Top-level abstraction. Provides a global view of resources", + response=PolicyEngine.class + ) + public Response engine() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); } - - /** - * Updates the Policy Engine - * - * @param configuration configuration - * @return Policy Engine - */ - @PUT + @DELETE @Path("engine") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response updateEngine(PdpdConfiguration configuration) { - PolicyController controller = null; - boolean success = true; - try { - success = PolicyEngine.manager.configure(configuration); - } catch (Exception e) { - success = false; + @ApiOperation( + value="Shuts down the Engine", + notes="Deleting the engine, the top-level abstraction, equivalenty shuts it down", + response=PolicyEngine.class + ) + public Response engineShutdown() { + try { + PolicyEngine.manager.shutdown(); + } catch (IllegalStateException e) { logger.warn(MessageCodes.EXCEPTION_ERROR, e, - "PolicyEngine", this.toString()); + "shutdown: " + PolicyEngine.manager); + return Response.status(Response.Status.BAD_REQUEST). + entity(PolicyEngine.manager). + build(); } - if (!success) - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation")).build(); - else - return Response.status(Response.Status.OK).entity(controller).build(); + return Response.status(Response.Status.OK). + entity(PolicyEngine.manager). + build(); } - + @GET @Path("engine/features") - @Produces(MediaType.APPLICATION_JSON) - public List<PolicyEngineFeatureAPI> engineFeatures() { - return PolicyEngine.manager.getFeatureProviders(); + @ApiOperation( + value="Engine Features", + notes="Provides the list of loaded features using the PolicyEngineFeatureAPI", + responseContainer="List" + ) + public Response engineFeatures() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatures()).build(); } @GET + @Path("engine/features/inventory") + @ApiOperation( + value="Engine Detailed Feature Inventory", + notes="Provides detailed list of loaded features using the PolicyEngineFeatureAPI", + responseContainer="List", + response=PolicyEngineFeatureAPI.class + ) + public Response engineFeaturesInventory() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatureProviders()).build(); + } + + @GET @Path("engine/features/{featureName}") - @Produces(MediaType.APPLICATION_JSON) - public Response engineFeature(@PathParam("featureName") String featureName) { + @ApiOperation( + value="Engine Feature", + notes="Provides Details for a given feature Engine Provider", + response=PolicyEngineFeatureAPI.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message = "The feature cannot be found") + }) + public Response engineFeature(@ApiParam(value="Feature Name", required=true) + @PathParam("featureName") String featureName) { try { return Response.status(Response.Status.OK). entity(PolicyEngine.manager.getFeatureProvider(featureName)).build(); @@ -137,25 +182,33 @@ public class RestManager { } @GET - @Path("engine/properties") - @Produces(MediaType.APPLICATION_JSON) - public Properties engineProperties() { - return PolicyEngine.manager.getProperties(); + @Path("engine/inputs") + @ApiOperation( + value="Engine Input Ports", + notes="List of input ports", + responseContainer="List" + ) + public Response engineInputs() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Inputs.values())). + build(); } - /** - * Activates the Policy Engine - * - * @param configuration configuration - * @return Policy Engine - */ - @PUT - @Path("engine/activation") - @Produces(MediaType.APPLICATION_JSON) - public Response activateEngine() { + @POST + @Path("engine/inputs/configuration") + @ApiOperation( + value="Engine Input Configuration Requests", + notes="Feeds a configuration request input into the Engine" + ) + @ApiResponses(value={ + @ApiResponse(code=406, message = "The configuration request cannot be honored") + }) + public Response engineUpdate( + @ApiParam(value="Configuration to apply", required=true) PdpdConfiguration configuration) { + PolicyController controller = null; boolean success = true; try { - PolicyEngine.manager.activate(); + success = PolicyEngine.manager.configure(configuration); } catch (Exception e) { success = false; logger.warn(MessageCodes.EXCEPTION_ERROR, e, @@ -166,22 +219,45 @@ public class RestManager { return Response.status(Response.Status.NOT_ACCEPTABLE). entity(new Error("cannot perform operation")).build(); else - return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); + return Response.status(Response.Status.OK).entity(controller).build(); + } + + @GET + @Path("engine/properties") + @ApiOperation( + value="Engine Configuration Properties", + notes="Used for booststrapping the engine", + response=Properties.class + ) + public Response engineProperties() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getProperties()).build(); + } + + @GET + @Path("engine/switches") + @ApiOperation( + value="Engine Control Switches", + notes="List of the Engine Control Switches", + responseContainer="List" + ) + public Response engineSwitches() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Switches.values())). + build(); } - /** - * Activates the Policy Engine - * - * @param configuration configuration - * @return Policy Engine - */ @PUT - @Path("engine/deactivation") - @Produces(MediaType.APPLICATION_JSON) - public Response deactivateEngine() { + @Path("engine/switches/activation") + @ApiOperation( + value="Switches on the Engine Activation Switch", + notes="Turns on Activation Switch on the Engine. This order entails that the engine " + + "and controllers are unlocked and started", + response=PolicyEngine.class + ) + public Response engineActivation() { boolean success = true; try { - PolicyEngine.manager.deactivate(); + PolicyEngine.manager.activate(); } catch (Exception e) { success = false; logger.warn(MessageCodes.EXCEPTION_ERROR, e, @@ -196,68 +272,117 @@ public class RestManager { } @DELETE - @Path("engine") - @Produces(MediaType.APPLICATION_JSON) - public Response engineShutdown() { - try { - PolicyEngine.manager.shutdown(); - } catch (IllegalStateException e) { + @Path("engine/switches/activation") + @ApiOperation( + value="Switches off Engine Activation Switch", + notes="Turns off the Activation Switch on the Engine. This order entails that the engine " + + "and controllers are locked (with the exception of those resources defined as unmanaged)", + response=PolicyEngine.class + ) + public Response engineDeactivation() { + boolean success = true; + try { + PolicyEngine.manager.deactivate(); + } catch (Exception e) { + success = false; logger.warn(MessageCodes.EXCEPTION_ERROR, e, - "shutdown: " + PolicyEngine.manager); - return Response.status(Response.Status.BAD_REQUEST). - entity(PolicyEngine.manager). - build(); + "PolicyEngine", this.toString()); } - return Response.status(Response.Status.OK). - entity(PolicyEngine.manager). - build(); - } + if (!success) + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")).build(); + else + return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); + } @PUT - @Path("engine/lock") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response lockEngine() { + @Path("engine/switches/lock") + @ApiOperation( + value="Switches on the Engine Lock Control", + notes="This switch locks all the engine resources as a whole, except those that are defined unmanaged", + response=PolicyEngine.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response engineLock() { boolean success = PolicyEngine.manager.lock(); if (success) return Response.status(Status.OK). - entity("Policy Engine is locked"). + entity(PolicyEngine.manager). build(); else - return Response.status(Status.SERVICE_UNAVAILABLE). - entity("Policy Engine cannot be locked"). + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")). build(); } @DELETE - @Path("engine/unlock") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response unlockEngine() { + @Path("engine/switches/lock") + @ApiOperation( + value="Switches off the Lock control", + notes="This switch locks all the engine resources as a whole, except those that are defined unmanaged", + response=PolicyEngine.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response engineUnlock() { boolean success = PolicyEngine.manager.unlock(); if (success) return Response.status(Status.OK). - entity("Policy Engine is unlocked"). + entity(PolicyEngine.manager). build(); else - return Response.status(Status.SERVICE_UNAVAILABLE). - entity("Policy Engine cannot be unlocked"). + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")). build(); } @GET @Path("engine/controllers") - @Produces(MediaType.APPLICATION_JSON) - public List<PolicyController> controllers() { - return PolicyEngine.manager.getPolicyControllers(); + @ApiOperation( + value="Lists the Policy Controllers Names", + notes="Unique Policy Controller Identifiers", + responseContainer="List" + ) + public Response controllers() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getPolicyControllerIds()).build(); + } + + @GET + @Path("engine/controllers/inventory") + @ApiOperation( + value="Lists the Policy Controllers", + notes="Detailed list of Policy Controllers", + responseContainer="List", + response=PolicyController.class + ) + public Response controllerInventory() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getPolicyControllers()).build(); } @POST @Path("engine/controllers") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response addController(Properties config) { + @ApiOperation( + value="Creates and starts a new Policy Controller", + notes="Controller creation based on properties", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=400, message = "Invalid configuration information has been provided"), + @ApiResponse(code=304, message = "The controller already exists"), + @ApiResponse(code=406, message = "The administrative state of the system prevents it " + + "from processing this request"), + @ApiResponse(code=206, message = "The controller has been created " + + "but cannot be started"), + @ApiResponse(code=201, message = "The controller has been succesfully created and started") + }) + public Response controllerAdd(@ApiParam(value="Configuration Properties to apply", required = true) + Properties config) { if (config == null) return Response.status(Response.Status.BAD_REQUEST). entity(new Error("A configuration must be provided")). @@ -315,20 +440,45 @@ public class RestManager { return Response.status(Response.Status.CREATED). entity(controller). build(); - } + } @GET @Path("engine/controllers/features") - @Produces(MediaType.APPLICATION_JSON) - public List<PolicyControllerFeatureAPI> controllerFeatures() { - return PolicyController.factory.getFeatureProviders(); + @ApiOperation( + value="Lists of Feature Providers Identifiers", + notes="Unique Policy Controller Identifiers", + responseContainer="List" + ) + public Response controllerFeatures() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatures()).build(); + } + + @GET + @Path("engine/controllers/features/inventory") + @ApiOperation( + value="Detailed Controllers Feature Inventory", + notes="Provides detailed list of loaded features using the PolicyControllerFeatureAPI", + responseContainer="List", + response=PolicyControllerFeatureAPI.class + ) + public Response controllerFeaturesInventory() { + return Response.status(Response.Status.OK). + entity(PolicyController.factory.getFeatureProviders()). + build(); } @GET @Path("engine/controllers/features/{featureName}") - @Produces(MediaType.APPLICATION_JSON) - public Response controllerFeature(@PathParam("controllerName") String controllerName, - @PathParam("featureName") String featureName) { + @ApiOperation( + value="Controller Feature", + notes="Provides Details for a given Policy Controller feature provider", + response=PolicyControllerFeatureAPI.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message = "The feature cannot be found") + }) + public Response controllerFeature(@ApiParam(value="Feature Name", required=true) + @PathParam("featureName") String featureName) { try { return Response.status(Response.Status.OK). entity(PolicyController.factory.getFeatureProvider(featureName)). @@ -340,9 +490,21 @@ public class RestManager { } @GET - @Path("engine/controllers/{controllerName}") - @Produces(MediaType.APPLICATION_JSON) - public Response controller(@PathParam("controllerName") String controllerName) { + @Path("engine/controllers/{controller}") + @ApiOperation( + value="Retrieves a Policy Controller", + notes="A Policy Controller is a concrete drools application abstraction. " + + "It aggregates networking, drools, and other resources," + + "as provides operational controls over drools applications", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response controller(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { try { return Response.status(Response.Status.OK). entity(PolicyController.factory.get(controllerName)). @@ -355,46 +517,26 @@ public class RestManager { return Response.status(Response.Status.NOT_ACCEPTABLE). entity(new Error(controllerName + " not acceptable")). build(); - } catch (Exception e) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR). - entity(new Error(controllerName + " not acceptable")). - build(); - } - } - @GET - @Path("engine/controllers/{controllerName}/properties") - @Produces(MediaType.APPLICATION_JSON) - public Response controllerProperties(@PathParam("controllerName") String controllerName) { - try { - PolicyController controller = PolicyController.factory.get(controllerName); - return Response.status(Response.Status.OK). - entity(controller.getProperties()). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " not acceptable")). - build(); - } catch (Exception e) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR). - entity(new Error(controllerName + " not acceptable")). - build(); } } @DELETE - @Path("engine/controllers/{controllerName}") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response deleteController(@PathParam("controllerName") String controllerName) { - - if (controllerName == null || controllerName.isEmpty()) - return Response.status(Response.Status.BAD_REQUEST). - entity("A controller name must be provided"). - build(); + @Path("engine/controllers/{controller}") + @ApiOperation( + value="Deletes a Policy Controller", + notes="A Policy Controller is a concrete drools application abstraction. " + + "It aggregates networking, drools, and other resources," + + "as provides operational controls over drools applications", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A problem has occurred while deleting the Policy Controller") + }) + public Response controllerDelete(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { PolicyController controller; try { @@ -432,17 +574,62 @@ public class RestManager { build(); } - /** - * Updates the Policy Engine - * - * @param configuration configuration - * @return Policy Engine - */ - @PUT - @Path("engine/controllers/{controllerName}") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response updateController(@PathParam("controllerName") String controllerName, + @GET + @Path("engine/controllers/{controller}/properties") + @ApiOperation( + value="Retrieves the configuration properties of a Policy Controller", + notes="Configuration resources used by the controller if Properties format", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response controllerProperties(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + try { + PolicyController controller = PolicyController.factory.get(controllerName); + return Response.status(Response.Status.OK). + entity(controller.getProperties()). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/inputs") + @ApiOperation( + value="Policy Controller Input Ports", + notes="List of input ports", + responseContainer="List" + ) + public Response controllerInputs() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Inputs.values())). + build(); + } + + @POST + @Path("engine/controllers/{controller}/inputs/configuration") + @ApiOperation( + value="Policy Controller Input Configuration Requests", + notes="Feeds a configuration request input into the given Policy Controller" + ) + @ApiResponses(value={ + @ApiResponse(code=400, message = "The configuration request is invalid"), + @ApiResponse(code=406, message = "The configuration request cannot be honored") + }) + public Response controllerUpdate(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Configuration to apply", required=true) ControllerConfiguration controllerConfiguration) { if (controllerName == null || controllerName.isEmpty() || @@ -478,85 +665,240 @@ public class RestManager { } @GET - @Path("engine/controllers/{controllerName}/drools") - @Produces(MediaType.APPLICATION_JSON) - public Response drools(@PathParam("controllerName") String controllerName) { + @Path("engine/controllers/{controller}/switches") + @ApiOperation( + value="Policy Controller Switches", + notes="List of the Policy Controller Switches", + responseContainer="List" + ) + public Response controllerSwitches() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Switches.values())). + build(); + } + + @PUT + @Path("engine/controllers/{controller}/switches/lock") + @ApiOperation( + value="Switches on the Policy Controller Lock Control", + notes="This action on the switch locks the Policy Controller", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response controllerLock(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + PolicyController policyController = PolicyController.factory.get(controllerName); + boolean success = policyController.lock(); + if (success) + return Response.status(Status.OK). + entity(policyController). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("Controller " + controllerName + " cannot be locked")). + build(); + } + + @DELETE + @Path("engine/controllers/{controller}/switches/lock") + @ApiOperation( + value="Switches off the Policy Controller Lock Control", + notes="This action on the switch unlocks the Policy Controller", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response controllerUnlock(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + PolicyController policyController = PolicyController.factory.get(controllerName); + boolean success = policyController.unlock(); + if (success) + return Response.status(Status.OK). + entity(policyController). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("Controller " + controllerName + " cannot be unlocked")). + build(); + } + + @GET + @Path("engine/controllers/{controller}/drools") + @ApiOperation( + value="Retrieves the Drools Controller subcomponent of the Policy Controller", + notes="The Drools Controller provides an abstraction over the Drools subsystem", + response=DroolsController.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response drools(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { try { DroolsController drools = getDroolsController(controllerName); return Response.status(Response.Status.OK). entity(drools). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); } } @GET - @Path("engine/controllers/{controllerName}/drools/facts/{sessionName}") - @Produces(MediaType.APPLICATION_JSON) - public Response droolsFacts(@DefaultValue("false") @QueryParam("count") boolean count, - @PathParam("controllerName") String controllerName, - @PathParam("sessionName") String sessionName) { + @Path("engine/controllers/{controller}/drools/facts") + @ApiOperation( + value="Retrieves Facts Summary information for a given controller", + notes="Provides the session names, and a count of fact object in the drools working memory", + responseContainer="Map" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response droolsFacts(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { try { + Map<String,Long> sessionCounts = new HashMap<>(); DroolsController drools = getDroolsController(controllerName); - if (!count) - return Response.status(Response.Status.OK). - entity(drools.factClassNames(sessionName)). - build(); - else - return Response.status(Response.Status.OK). - entity(new Long(drools.factCount(sessionName))). - build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + for (String session : drools.getSessionNames()) { + sessionCounts.put(session, drools.factCount(session)); + } + return Response.status(Response.Status.OK). + entity(sessionCounts). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); } } @GET - @Path("engine/controllers/{controllerName}/drools/facts/{sessionName}/{className}") - @Produces(MediaType.APPLICATION_JSON) - public Response droolsFacts(@DefaultValue("false") @QueryParam("count") boolean count, - @PathParam("controllerName") String controllerName, - @PathParam("sessionName") String sessionName, - @PathParam("className") String className) { + @Path("engine/controllers/{controller}/drools/facts/{session}") + @ApiOperation( + value="Retrieves Fact Types (classnames) for a given controller and its count", + notes="The fact types are the classnames of the objects inserted in the drools working memory", + responseContainer="Map" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller or session cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response droolsFacts(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName) { try { DroolsController drools = getDroolsController(controllerName); - List<Object> facts = drools.facts(sessionName, className, false); + return Response.status(Response.Status.OK). + entity(drools.factClassNames(sessionName)). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error("entity not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/drools/facts/{session}/{factType}") + @ApiOperation( + value="Retrieves fact objects of a given type in the drools working memory" + + "for a given controller and session", + notes="The fact types are the classnames of the objects inserted in the drools working memory", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, session, or fact type cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response droolsFacts(@ApiParam(value="Fact count", required=false) + @DefaultValue("false") @QueryParam("count") boolean count, + @ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName, + @ApiParam(value="Drools Fact Type", required=true) + @PathParam("factType") String factType) { + try { + DroolsController drools = getDroolsController(controllerName); + List<Object> facts = drools.facts(sessionName, factType, false); if (!count) return Response.status(Response.Status.OK).entity(facts).build(); else return Response.status(Response.Status.OK).entity(facts.size()).build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + sessionName + ":" + factType + + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + ":" + factType + + " not acceptable")). + build(); } } @DELETE - @Path("engine/controllers/{controllerName}/drools/facts/{sessionName}/{className}") - @Produces(MediaType.APPLICATION_JSON) - public Response deleteDroolsFacts(@PathParam("controllerName") String controllerName, - @PathParam("sessionName") String sessionName, - @PathParam("className") String className) { + @Path("engine/controllers/{controller}/drools/facts/{session}/{factType}") + @ApiOperation( + value="Deletes all the fact objects of a given type from the drools working memory" + + "for a given controller and session. The objects retracted from the working " + + "memory are provided in the response.", + notes="The fact types are the classnames of the objects inserted in the drools working memory", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, session, or fact type, cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response droolsFactsDelete(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName, + @ApiParam(value="Drools Fact Type", required=true) + @PathParam("factType") String factType) { try { DroolsController drools = getDroolsController(controllerName); - List<Object> facts = drools.facts(sessionName, className, true); + List<Object> facts = drools.facts(sessionName, factType, true); return Response.status(Response.Status.OK).entity(facts).build(); - } catch (IllegalArgumentException | IllegalStateException e) { - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + sessionName + ":" + factType + + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + ":" + factType + + " not acceptable")). + build(); } catch (Exception e) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR). entity(new Error(e.getMessage())). @@ -565,12 +907,28 @@ public class RestManager { } @GET - @Path("engine/controllers/{controllerName}/drools/facts/{sessionName}/{queryName}/{queriedEntity}") - @Produces(MediaType.APPLICATION_JSON) - public Response droolsFacts(@DefaultValue("false") @QueryParam("count") boolean count, - @PathParam("controllerName") String controllerName, - @PathParam("sessionName") String sessionName, - @PathParam("queryName") String queryName, + @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}") + @ApiOperation( + value="Gets all the fact objects returned by a DRL query with no parameters from the drools working memory" + + "for a given controller and session", + notes="The DRL query must be defined in the DRL file", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, session, or query information, cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response droolsFacts(@ApiParam(value="Fact count", required=false) + @DefaultValue("false") @QueryParam("count") boolean count, + @ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName, + @ApiParam(value="Query Name Present in DRL", required=true) + @PathParam("query") String queryName, + @ApiParam(value="Query Identifier Present in the DRL Query", required=true) @PathParam("queriedEntity") String queriedEntity) { try { DroolsController drools = getDroolsController(controllerName); @@ -579,10 +937,16 @@ public class RestManager { return Response.status(Response.Status.OK).entity(facts).build(); else return Response.status(Response.Status.OK).entity(facts.size()).build(); - } catch (IllegalArgumentException | IllegalStateException e) { - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not acceptable")). + build(); } catch (Exception e) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR). entity(new Error(e.getMessage())). @@ -590,14 +954,30 @@ public class RestManager { } } - @PUT - @Path("engine/controllers/{controllerName}/drools/facts/{sessionName}/{queryName}/{queriedEntity}") - @Produces(MediaType.APPLICATION_JSON) - public Response droolsFacts(@PathParam("controllerName") String controllerName, - @PathParam("sessionName") String sessionName, - @PathParam("queryName") String queryName, + @POST + @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}") + @ApiOperation( + value="Gets all the fact objects returned by a DRL query with parameters from the drools working memory" + + "for a given controller and session", + notes="The DRL query with parameters must be defined in the DRL file", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, session, or query information, cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response droolsFacts(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName, + @ApiParam(value="Query Name Present in DRL", required=true) + @PathParam("query") String queryName, + @ApiParam(value="Query Identifier Present in the DRL Query", required=true) @PathParam("queriedEntity") String queriedEntity, - List<Object> queryParameters) { + @ApiParam(value="Query Parameter Values to pass in the DRL Query", required=false) + List<Object> queryParameters) { try { DroolsController drools = getDroolsController(controllerName); List<Object> facts; @@ -606,10 +986,16 @@ public class RestManager { else facts = drools.factQuery(sessionName, queryName, queriedEntity, false, queryParameters.toArray()); return Response.status(Response.Status.OK).entity(facts).build(); - } catch (IllegalArgumentException | IllegalStateException e) { - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not acceptable")). + build(); } catch (Exception e) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR). entity(new Error(e.getMessage())). @@ -618,13 +1004,29 @@ public class RestManager { } @DELETE - @Path("engine/controllers/{controllerName}/drools/facts/{sessionName}/{queryName}/{queriedEntity}") - @Produces(MediaType.APPLICATION_JSON) - public Response deleteDroolsFacts(@PathParam("controllerName") String controllerName, - @PathParam("sessionName") String sessionName, - @PathParam("queryName") String queryName, - @PathParam("queriedEntity") String queriedEntity, - List<Object> queryParameters) { + @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}") + @ApiOperation( + value="Deletes all the fact objects returned by a DRL query with parameters from the drools working memory" + + "for a given controller and session", + notes="The DRL query with parameters must be defined in the DRL file", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, session, or query information, cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response droolsFactsDelete(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName, + @ApiParam(value="Query Name Present in DRL", required=true) + @PathParam("query") String queryName, + @ApiParam(value="Query Identifier Present in the DRL Query", required=true) + @PathParam("queriedEntity") String queriedEntity, + @ApiParam(value="Query Parameter Values to pass in the DRL Query", required=false) + List<Object> queryParameters) { try { DroolsController drools = getDroolsController(controllerName); List<Object> facts; @@ -633,10 +1035,16 @@ public class RestManager { else facts = drools.factQuery(sessionName, queryName, queriedEntity, true, queryParameters.toArray()); return Response.status(Response.Status.OK).entity(facts).build(); - } catch (IllegalArgumentException | IllegalStateException e) { - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not acceptable")). + build(); } catch (Exception e) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR). entity(new Error(e.getMessage())). @@ -644,10 +1052,45 @@ public class RestManager { } } + @POST + @Path("engine/controllers/tools/coders/decoders/filters/rules/{ruleName}") + @ApiOperation( + value="Produces a Decoder Rule Filter in a format that the Policy Controller can understand", + notes="The result can be used with other APIs to attach a filter to a decoder" + ) + public Response rules(@ApiParam(value="Negate regex?", required=true) + @DefaultValue("false") @QueryParam("negate") boolean negate, + @ApiParam(value="Rule Name", required=true) + @PathParam("ruleName") String name, + @ApiParam(value="Regex expression", required=true) + String regex) { + String literalRegex = Pattern.quote(regex); + if (negate) + literalRegex = "^(?!" + literalRegex + "$).*"; + + return Response.status(Status.OK). + entity(new JsonProtocolFilter.FilterRule(name,literalRegex)). + build(); + } + @GET - @Path("engine/controllers/{controllerName}/decoders") - @Produces(MediaType.APPLICATION_JSON) - public Response decoders(@PathParam("controllerName") String controllerName) { + @Path("engine/controllers/{controller}/decoders") + @ApiOperation( + value="Gets all the decoders used by a controller", + notes="A Policy Controller uses decoders to deserialize incoming network messages from " + + "subscribed network topics into specific (fact) objects. " + + "The deserialized (fact) object will typically be inserted in the drools working " + + " memory of the controlled drools application.", + responseContainer="List", + response=ProtocolCoderToolset.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoders(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { try { DroolsController drools = getDroolsController(controllerName); List<ProtocolCoderToolset> decoders = EventProtocolCoder.manager.getDecoders @@ -655,117 +1098,210 @@ public class RestManager { return Response.status(Response.Status.OK). entity(decoders). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); } } @GET - @Path("engine/controllers/{controllerName}/decoders/filters") - @Produces(MediaType.APPLICATION_JSON) - public Response decoderFilters(@PathParam("controllerName") String controllerName) { + @Path("engine/controllers/{controller}/decoders/filters") + @ApiOperation( + value="Gets all the filters used by a controller", + notes="A Policy Controller uses decoders to deserialize incoming network messages from " + + "subscribed network topics into specific (fact) objects. " + + "The deserialized (fact) object will typically be inserted in the drools working " + + " memory of the controlled drools application." + + "Acceptance filters are used to filter out undesired network messages for the given controller", + responseContainer="List", + response=CoderFilters.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilters(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { try { DroolsController drools = getDroolsController(controllerName); List<CoderFilters> filters = EventProtocolCoder.manager.getDecoderFilters - (drools.getGroupId(), drools.getArtifactId()); + (drools.getGroupId(), drools.getArtifactId()); return Response.status(Response.Status.OK). entity(filters). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); } } @GET - @Path("engine/controllers/{controllerName}/decoders/{topicName}") - @Produces(MediaType.APPLICATION_JSON) - public Response decoder(@PathParam("controllerName") String controllerName, - @PathParam("topicName") String topicName) { + @Path("engine/controllers/{controller}/decoders/{topic}") + @ApiOperation( + value="Gets all the decoders in use by a controller for a networked topic", + notes="A Policy Controller uses decoders to deserialize incoming network messages from " + + "subscribed network topics into specific (fact) objects. " + + "The deserialized (fact) object will typically be inserted in the drools working " + + " memory of the controlled drools application.", + responseContainer="List", + response=ProtocolCoderToolset.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller or topic cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoder(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Networked Topic Name", required=true) + @PathParam("topic") String topic) { try { DroolsController drools = getDroolsController(controllerName); ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topicName); + (drools.getGroupId(), drools.getArtifactId(), topic); return Response.status(Response.Status.OK). entity(decoder). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + " not acceptable")). + build(); } } @GET - @Path("engine/controllers/{controllerName}/decoders/{topicName}/filters") - @Produces(MediaType.APPLICATION_JSON) - public Response decoderFilter(@PathParam("controllerName") String controllerName, - @PathParam("topicName") String topicName) { + @Path("engine/controllers/{controller}/decoders/{topic}/filters") + @ApiOperation( + value="Gets all filters attached to decoders for a given networked topic in use by a controller", + notes="A Policy Controller uses decoders to deserialize incoming network messages from " + + "subscribed network topics into specific (fact) objects. " + + "The deserialized (fact) object will typically be inserted in the drools working " + + " memory of the controlled drools application." + + "Acceptance filters are used to filter out undesired network messages for the given controller", + responseContainer="List", + response=CoderFilters.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller or topic cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilter(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Networked Topic Name", required=true) + @PathParam("topic") String topic) { try { DroolsController drools = getDroolsController(controllerName); ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topicName); + (drools.getGroupId(), drools.getArtifactId(), topic); if (decoder == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(topicName + " does not exist")). + entity(new Error(topic + " does not exist")). build(); else return Response.status(Response.Status.OK). entity(decoder.getCoders()). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + " not acceptable")). + build(); } } @GET - @Path("engine/controllers/{controllerName}/decoders/{topicName}/filters/{factClassName}") - @Produces(MediaType.APPLICATION_JSON) - public Response decoderFilter(@PathParam("controllerName") String controllerName, - @PathParam("topicName") String topicName, - @PathParam("factClassName") String factClass) { + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}") + @ApiOperation( + value="Gets all filters attached to decoders for a given subscribed networked topic " + + "and fact type", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type (classname).", + responseContainer="List", + response=CoderFilters.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, or fact type cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilter(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Networked Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass) { try { DroolsController drools = getDroolsController(controllerName); ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topicName); + (drools.getGroupId(), drools.getArtifactId(), topic); CoderFilters filters = decoder.getCoder(factClass); if (filters == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(topicName + ":" + factClass + " does not exist")). + entity(new Error(topic + ":" + factClass + " does not exist")). build(); else return Response.status(Response.Status.OK). entity(filters). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not acceptable")). + build(); } } - @POST - @Path("engine/controllers/{controllerName}/decoders/{topicName}/filters/{factClassName}") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response decoderFilter(@PathParam("controllerName") String controllerName, - @PathParam("topicName") String topicName, - @PathParam("factClassName") String factClass, + @PUT + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}") + @ApiOperation( + value="Attaches filters to the decoder for a given networked topic " + + "and fact type", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type (classname).", + responseContainer="List", + response=CoderFilters.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, fact type, cannot be found, " + + "or a filter has not been provided"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilter(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass, + @ApiParam(value="Configuration Filter", required=true) JsonProtocolFilter configFilters) { if (configFilters == null) { @@ -777,121 +1313,183 @@ public class RestManager { try { DroolsController drools = getDroolsController(controllerName); ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topicName); + (drools.getGroupId(), drools.getArtifactId(), topic); CoderFilters filters = decoder.getCoder(factClass); if (filters == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(topicName + ":" + factClass + " does not exist")). + entity(new Error(topic + ":" + factClass + " does not exist")). build(); filters.setFilter(configFilters); return Response.status(Response.Status.OK). entity(filters). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not acceptable")). + build(); } } @GET - @Path("engine/controllers/{controllerName}/decoders/{topicName}/filters/{factClassName}/rules") - @Produces(MediaType.APPLICATION_JSON) - public Response decoderFilterRules(@PathParam("controllerName") String controllerName, - @PathParam("topicName") String topicName, - @PathParam("factClassName") String factClass) { + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules") + @ApiOperation( + value="Gets the filter rules attached to a topic decoder of a controller", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type and are composed of field matching rules. ", + responseContainer="List", + response=FilterRule.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, or fact type cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilterRules(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass) { try { DroolsController drools = getDroolsController(controllerName); ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topicName); + (drools.getGroupId(), drools.getArtifactId(), topic); CoderFilters filters = decoder.getCoder(factClass); if (filters == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topicName + ":" + factClass + " does not exist")). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). build(); JsonProtocolFilter filter = filters.getFilter(); if (filter == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topicName + ":" + factClass + " no filters")). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). build(); return Response.status(Response.Status.OK). entity(filter.getRules()). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not acceptable")). + build(); } } @GET - @Path("engine/controllers/{controllerName}/decoders/{topicName}/filters/{factClassName}/rules/{ruleName}") - @Produces(MediaType.APPLICATION_JSON) - public Response decoderFilterRules(@PathParam("controllerName") String controllerName, - @PathParam("topicName") String topicName, - @PathParam("factClassName") String factClass, - @PathParam("ruleName") String ruleName) { + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}") + @ApiOperation( + value="Gets a filter rule by name attached to a topic decoder of a controller", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type and are composed of field matching rules. ", + responseContainer="List", + response=FilterRule.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, fact type, or rule name cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilterRules(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass, + @ApiParam(value="Rule Name", required=true) + @PathParam("ruleName") String ruleName) { try { DroolsController drools = getDroolsController(controllerName); ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topicName); + (drools.getGroupId(), drools.getArtifactId(), topic); CoderFilters filters = decoder.getCoder(factClass); if (filters == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topicName + ":" + factClass + " does not exist")). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). build(); JsonProtocolFilter filter = filters.getFilter(); if (filter == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topicName + ":" + factClass + " no filters")). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). build(); return Response.status(Response.Status.OK). entity(filter.getRules(ruleName)). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + ": " + ruleName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + ":" + ruleName + " not acceptable")). + build(); } } @DELETE - @Path("engine/controllers/{controllerName}/decoders/{topicName}/filters/{factClassName}/rules/{ruleName}") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response deleteDecoderFilterRule(@PathParam("controllerName") String controllerName, - @PathParam("topicName") String topicName, - @PathParam("factClassName") String factClass, - @PathParam("ruleName") String ruleName, - FilterRule rule) { + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}") + @ApiOperation( + value="Deletes a filter rule by name attached to a topic decoder of a controller", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type and are composed of field matching rules. ", + responseContainer="List", + response=FilterRule.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, fact type, or rule name cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilterRuleDelete(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass, + @ApiParam(value="Rule Name", required=true) + @PathParam("ruleName") String ruleName, + @ApiParam(value="Filter Rule", required=true) + FilterRule rule) { try { DroolsController drools = getDroolsController(controllerName); ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topicName); + (drools.getGroupId(), drools.getArtifactId(), topic); CoderFilters filters = decoder.getCoder(factClass); if (filters == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topicName + ":" + factClass + " does not exist")). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). build(); JsonProtocolFilter filter = filters.getFilter(); if (filter == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topicName + ":" + factClass + " no filters")). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). build(); if (rule == null) { @@ -903,7 +1501,7 @@ public class RestManager { if (rule.getName() == null || !rule.getName().equals(ruleName)) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topicName + ":" + factClass + ":" + ruleName + + entity(new Error(controllerName + ":" + topic + ":" + factClass + ":" + ruleName + " rule name request inconsistencies (" + rule.getName() + ")")). build(); @@ -911,43 +1509,66 @@ public class RestManager { return Response.status(Response.Status.OK). entity(filter.getRules()). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + ": " + ruleName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + ":" + ruleName + " not acceptable")). + build(); } } @PUT - @Path("engine/controllers/{controllerName}/decoders/{topicName}/filters/{factClassName}/rules") - @Produces(MediaType.APPLICATION_JSON) - public Response decoderFilterRule(@PathParam("controllerName") String controllerName, - @PathParam("topicName") String topicName, - @PathParam("factClassName") String factClass, - JsonProtocolFilter.FilterRule rule) { + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules") + @ApiOperation( + value="Places a new filter rule in a topic decoder", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type and are composed of field matching rules. ", + responseContainer="List", + response=FilterRule.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, or fact type cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilterRule(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass, + @ApiParam(value="Rule Name", required=true) + @PathParam("ruleName") String ruleName, + @ApiParam(value="Filter Rule", required=true) + FilterRule rule) { try { DroolsController drools = getDroolsController(controllerName); ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topicName); + (drools.getGroupId(), drools.getArtifactId(), topic); CoderFilters filters = decoder.getCoder(factClass); if (filters == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topicName + ":" + factClass + " does not exist")). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). build(); JsonProtocolFilter filter = filters.getFilter(); if (filter == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topicName + ":" + factClass + " no filters")). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). build(); if (rule.getName() == null) return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topicName + ":" + factClass + + entity(new Error(controllerName + ":" + topic + ":" + factClass + " rule name request inconsistencies (" + rule.getName() + ")")). build(); @@ -955,59 +1576,54 @@ public class RestManager { return Response.status(Response.Status.OK). entity(filter.getRules()). build(); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); - } - } - - @GET - @Path("engine/controllers/{controllerName}/encoders") - @Produces(MediaType.APPLICATION_JSON) - public Response encoderFilters(@PathParam("controllerName") String controllerName) { - List<CoderFilters> encoders; - try { - PolicyController controller = PolicyController.factory.get(controllerName); - if (controller == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + " does not exist")). - build(); - DroolsController drools = controller.getDrools(); - if (drools == null) - return Response.status(Response.Status.INTERNAL_SERVER_ERROR). - entity(new Error(controllerName + " has not drools component")). - build(); - encoders = EventProtocolCoder.manager.getEncoderFilters - (drools.getGroupId(), drools.getArtifactId()); } catch (IllegalArgumentException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + " not found: " + e.getMessage())). - build(); + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not found")). + build(); } catch (IllegalStateException e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - controllerName, this.toString()); return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " is not accepting the request")).build(); + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not acceptable")). + build(); } - - return Response.status(Response.Status.OK). - entity(encoders). - build(); } @POST - @Path("engine/controllers/{controllerName}/decoders/{topic}") - @Produces(MediaType.APPLICATION_JSON) - public Response decode(@PathParam("controllerName") String controllerName, - @PathParam("topic") String topic, - String json) { + @Path("engine/controllers/{controller}/decoders/{topic}") + @Consumes(MediaType.TEXT_PLAIN) + @ApiOperation( + value="Decodes a string into a fact object, and encodes it back into a string", + notes="Tests the decode/encode functions of a controller", + response=CodingResult.class + ) + @ApiResponses(value = { + @ApiResponse(code=400, message="Bad input has been provided"), + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decode(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="JSON String to decode", required=true) + String json) { - PolicyController policyController = PolicyController.factory.get(controllerName); + PolicyController policyController; + try { + policyController = PolicyController.factory.get(controllerName); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + " not acceptable")). + build(); + } CodingResult result = new CodingResult(); result.decoding = false; @@ -1032,9 +1648,7 @@ public class RestManager { result.jsonEncoding = EventProtocolCoder.manager.encode(topic, event); result.encoding = true; } catch (Exception e) { - return Response.status(Response.Status.OK). - entity(result). - build(); + // continue so to propagate decoding results .. } return Response.status(Response.Status.OK). @@ -1042,318 +1656,526 @@ public class RestManager { build(); } + @GET + @Path("engine/controllers/{controller}/encoders") + @ApiOperation( + value="Retrieves the encoder filters of a controller", + notes="The encoders serializes a fact object, typically for network transmission", + responseContainer="List", + response=CoderFilters.class + ) + @ApiResponses(value = { + @ApiResponse(code=400, message="Bad input has been provided"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response encoderFilters(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + List<CoderFilters> encoders; + try { + PolicyController controller = PolicyController.factory.get(controllerName); + DroolsController drools = controller.getDrools(); + encoders = EventProtocolCoder.manager.getEncoderFilters + (drools.getGroupId(), drools.getArtifactId()); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " not found: " + e.getMessage())). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " is not accepting the request")).build(); + } + + return Response.status(Response.Status.OK). + entity(encoders). + build(); + } + @GET @Path("engine/topics") - @Produces(MediaType.APPLICATION_JSON) - public TopicEndpoint topics() { - return TopicEndpoint.manager; + @ApiOperation( + value="Retrieves the managed topics", + notes="Network Topics Aggregation", + response=TopicEndpoint.class + ) + public Response topics() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager). + build(); } + + @GET + @Path("engine/topics/switches") + @ApiOperation( + value="Topics Control Switches", + notes="List of the Topic Control Switches", + responseContainer="List" + ) + public Response topicSwitches() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Switches.values())). + build(); + } + + @PUT + @Path("engine/topics/switches/lock") + @ApiOperation( + value="Locks all the managed topics", + notes="The operation affects all managed sources and sinks", + response=TopicEndpoint.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response topicsLock() { + boolean success = TopicEndpoint.manager.lock(); + if (success) + return Response.status(Status.OK). + entity(TopicEndpoint.manager). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")). + build(); + } + + @DELETE + @Path("engine/topics/switches/lock") + @ApiOperation( + value="Unlocks all the managed topics", + notes="The operation affects all managed sources and sinks", + response=TopicEndpoint.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response topicsUnlock() { + boolean success = TopicEndpoint.manager.unlock(); + if (success) + return Response.status(Status.OK). + entity(TopicEndpoint.manager). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")). + build(); + } - @SuppressWarnings("unchecked") @GET @Path("engine/topics/sources") - @Produces(MediaType.APPLICATION_JSON) - public List<TopicSource> sources() { - return (List<TopicSource>) TopicEndpoint.manager.getTopicSources(); + @ApiOperation( + value="Retrieves the managed topic sources", + notes="Network Topic Sources Agregation", + responseContainer="List", + response=TopicSource.class + ) + public Response sources() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getTopicSources()). + build(); } - @SuppressWarnings("unchecked") @GET @Path("engine/topics/sinks") - @Produces(MediaType.APPLICATION_JSON) - public List<TopicSink> sinks() { - return (List<TopicSink>) TopicEndpoint.manager.getTopicSinks(); + @ApiOperation( + value="Retrieves the managed topic sinks", + notes="Network Topic Sinks Agregation", + responseContainer="List", + response=TopicSink.class + ) + public Response sinks() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getTopicSinks()). + build(); } @GET @Path("engine/topics/sources/ueb") - @Produces(MediaType.APPLICATION_JSON) - public List<UebTopicSource> uebSources() { - return TopicEndpoint.manager.getUebTopicSources(); + @ApiOperation( + value="Retrieves the UEB managed topic sources", + notes="UEB Topic Sources Agregation", + responseContainer="List", + response=UebTopicSource.class + ) + public Response uebSources() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getUebTopicSources()). + build(); } @GET @Path("engine/topics/sinks/ueb") - @Produces(MediaType.APPLICATION_JSON) - public List<UebTopicSink> uebSinks() { - return (List<UebTopicSink>) TopicEndpoint.manager.getUebTopicSinks(); + @ApiOperation( + value="Retrieves the UEB managed topic sinks", + notes="UEB Topic Sinks Agregation", + responseContainer="List", + response=UebTopicSource.class + ) + public Response uebSinks() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getUebTopicSinks()). + build(); } @GET @Path("engine/topics/sources/dmaap") - @Produces(MediaType.APPLICATION_JSON) - public List<DmaapTopicSource> dmaapSources() { - return TopicEndpoint.manager.getDmaapTopicSources(); + @ApiOperation( + value="Retrieves the DMaaP managed topic sources", + notes="DMaaP Topic Sources Agregation", + responseContainer="List", + response=DmaapTopicSource.class + ) + public Response dmaapSources() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getDmaapTopicSources()). + build(); } @GET @Path("engine/topics/sinks/dmaap") - @Produces(MediaType.APPLICATION_JSON) - public List<DmaapTopicSink> dmaapSinks() { - return (List<DmaapTopicSink>) TopicEndpoint.manager.getDmaapTopicSinks(); - } - - @SuppressWarnings("unchecked") - @GET - @Path("engine/topics/{topic}/sources") - @Produces(MediaType.APPLICATION_JSON) - public List<TopicSource> sourceTopic(@PathParam("topic") String topic) { - List<String> topics = new ArrayList<String>(); - topics.add(topic); - - return (List<TopicSource>) TopicEndpoint.manager.getTopicSources(topics); + @ApiOperation( + value="Retrieves the DMaaP managed topic sinks", + notes="DMaaP Topic Sinks Agregation", + responseContainer="List", + response=DmaapTopicSink.class + ) + public Response dmaapSinks() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getDmaapTopicSinks()). + build(); } - @SuppressWarnings("unchecked") - @GET - @Path("engine/topics/{topic}/sinks") - @Produces(MediaType.APPLICATION_JSON) - public List<TopicSink> sinkTopic(@PathParam("topic") String topic) { - List<String> topics = new ArrayList<String>(); - topics.add(topic); - - return (List<TopicSink>) TopicEndpoint.manager.getTopicSinks(topics); - } - - @GET - @Path("engine/topics/{topic}/ueb/source") - @Produces(MediaType.APPLICATION_JSON) - public UebTopicSource uebSourceTopic(@PathParam("topic") String topic) { - return TopicEndpoint.manager.getUebTopicSource(topic); + @Path("engine/topics/sources/ueb/{topic}") + @ApiOperation( + value="Retrieves an UEB managed topic source", + notes="This is an UEB Network Communicaton Endpoint source of messages for the Engine", + response=UebTopicSource.class + ) + public Response uebSourceTopic(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getUebTopicSource(topic)). + build(); } @GET - @Path("engine/topics/{topic}/ueb/sink") - @Produces(MediaType.APPLICATION_JSON) - public UebTopicSink uebSinkTopic(@PathParam("topic") String topic) { - return TopicEndpoint.manager.getUebTopicSink(topic); + @Path("engine/topics/sinks/ueb/{topic}") + @ApiOperation( + value="Retrieves an UEB managed topic sink", + notes="This is an UEB Network Communicaton Endpoint destination of messages from the Engine", + response=UebTopicSink.class + ) + public Response uebSinkTopic(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getUebTopicSink(topic)). + build(); } @GET - @Path("engine/topics/{topic}/dmaap/source") - @Produces(MediaType.APPLICATION_JSON) - public DmaapTopicSource dmaapSourceTopic(@PathParam("topic") String topic) { - return TopicEndpoint.manager.getDmaapTopicSource(topic); + @Path("engine/topics/sources/dmaap/{topic}") + @ApiOperation( + value="Retrieves a DMaaP managed topic source", + notes="This is a DMaaP Network Communicaton Endpoint source of messages for the Engine", + response=DmaapTopicSource.class + ) + public Response dmaapSourceTopic(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getDmaapTopicSource(topic)). + build(); } @GET - @Path("engine/topics/{topic}/dmaap/sink") - @Produces(MediaType.APPLICATION_JSON) - public DmaapTopicSink dmaapSinkTopic(@PathParam("topic") String topic) { - return TopicEndpoint.manager.getDmaapTopicSink(topic); + @Path("engine/topics/sinks/dmaap/{topic}") + @ApiOperation( + value="Retrieves a DMaaP managed topic sink", + notes="This is a DMaaP Network Communicaton Endpoint destination of messages from the Engine", + response=DmaapTopicSink.class + ) + public Response dmaapSinkTopic(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getDmaapTopicSink(topic)). + build(); } @GET - @Path("engine/topics/{topic}/ueb/source/events") - @Produces(MediaType.APPLICATION_JSON) - public Response uebSourceEvent(@PathParam("topic") String topicName) { - - UebTopicSource uebReader = TopicEndpoint.manager.getUebTopicSource(topicName); - String[] events = uebReader.getRecentEvents(); + @Path("engine/topics/sources/ueb/{topic}/events") + @ApiOperation( + value="Retrieves the latest events received by an UEB topic", + notes="This is a UEB Network Communicaton Endpoint source of messages for the Engine", + responseContainer="List" + ) + public Response uebSourceEvents(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { return Response.status(Status.OK). - entity(events). - build(); + entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSource(topic).getRecentEvents())). + build(); } @GET - @Path("engine/topics/{topic}/ueb/sink/events") - @Produces(MediaType.APPLICATION_JSON) - public Response uebSinkEvent(@PathParam("topic") String topicName) { - - UebTopicSink uebSink = TopicEndpoint.manager.getUebTopicSink(topicName); - String[] events = uebSink.getRecentEvents(); + @Path("engine/topics/sinks/ueb/{topic}/events") + @ApiOperation( + value="Retrieves the latest events sent from a topic", + notes="This is a UEB Network Communicaton Endpoint sink of messages from the Engine", + responseContainer="List" + ) + public Response uebSinkEvents(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { return Response.status(Status.OK). - entity(events). - build(); + entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSink(topic).getRecentEvents())). + build(); } @GET - @Path("engine/topics/{topic}/dmaap/source/events") - @Produces(MediaType.APPLICATION_JSON) - public Response dmaapSourcevent(@PathParam("topic") String topicName) { - - DmaapTopicSource uebReader = TopicEndpoint.manager.getDmaapTopicSource(topicName); - String[] events = uebReader.getRecentEvents(); + @Path("engine/topics/sources/dmaap/{topic}/events") + @ApiOperation( + value="Retrieves the latest events received by a DMaaP topic", + notes="This is a DMaaP Network Communicaton Endpoint source of messages for the Engine", + responseContainer="List" + ) + public Response dmaapSourceEvents(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { return Response.status(Status.OK). - entity(events). - build(); + entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSource(topic).getRecentEvents())). + build(); } - @DELETE - @Path("engine/topics/lock") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response unlockTopics() { - boolean success = TopicEndpoint.manager.unlock(); - if (success) - return Response.status(Status.OK). - entity("Endpoints are unlocked"). - build(); - else - return Response.status(Status.SERVICE_UNAVAILABLE). - entity("Endpoints cannot be unlocked"). - build(); - } - - - @GET - @Path("engine/topics/{topic}/dmaap/sink/events") - @Produces(MediaType.APPLICATION_JSON) - public Response dmaapSinkEvent(@PathParam("topic") String topicName) { - - DmaapTopicSink uebSink = TopicEndpoint.manager.getDmaapTopicSink(topicName); - String[] events = uebSink.getRecentEvents(); + @GET + @Path("engine/topics/sinks/dmaap/{topic}/events") + @ApiOperation( + value="Retrieves the latest events send through a DMaaP topic", + notes="This is a DMaaP Network Communicaton Endpoint destination of messages from the Engine", + responseContainer="List" + ) + public Response dmaapSinkEvents( + @PathParam("topic") String topic) { return Response.status(Status.OK). - entity(events). - build(); - } - - @PUT - @Path("engine/topics/{topic}/ueb/sources/events") - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.APPLICATION_JSON) - public Response uebOffer(@PathParam("topic") String topicName, - String json) { - try { - UebTopicSource uebReader = TopicEndpoint.manager.getUebTopicSource(topicName); - boolean success = uebReader.offer(json); - if (success) - return Response.status(Status.OK). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("Failure to inject event over " + topicName)). - build(); - } catch (Exception e) { - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); - } + entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSink(topic).getRecentEvents())). + build(); } - @PUT - @Path("engine/topics/{topic}/dmaap/sources/events") - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.APPLICATION_JSON) - public Response dmaapOffer(@PathParam("topic") String topicName, - String json) { - try { - DmaapTopicSource dmaapReader = TopicEndpoint.manager.getDmaapTopicSource(topicName); - boolean success = dmaapReader.offer(json); - if (success) - return Response.status(Status.OK). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("Failure to inject event over " + topicName)). - build(); - } catch (Exception e) { - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); - } + @GET + @Path("engine/topics/sources/ueb/{topic}/switches") + @ApiOperation( + value="UEB Topic Control Switches", + notes="List of the UEB Topic Control Switches", + responseContainer="List" + ) + public Response uebTopicSwitches() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Switches.values())). + build(); } @PUT - @Path("engine/topics/lock") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response lockTopics() { - boolean success = TopicEndpoint.manager.lock(); + @Path("engine/topics/sources/ueb/{topic}/switches/lock") + @ApiOperation( + value="Locks an UEB Source topic", + response=UebTopicSource.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response uebTopicLock(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + UebTopicSource source = TopicEndpoint.manager.getUebTopicSource(topic); + boolean success = source.lock(); if (success) return Response.status(Status.OK). - entity("Endpoints are locked"). + entity(source). build(); else - return Response.status(Status.SERVICE_UNAVAILABLE). - entity("Endpoints cannot be locked"). + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation on " + topic)). build(); } - @PUT - @Path("engine/topics/{topic}/ueb/sources/lock") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response lockTopic(@PathParam("topic") String topicName) { - UebTopicSource reader = TopicEndpoint.manager.getUebTopicSource(topicName); - boolean success = reader.lock(); + @DELETE + @Path("engine/topics/sources/ueb/{topic}/switches/lock") + @ApiOperation( + value="Unlocks an UEB Source topic", + response=UebTopicSource.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response uebTopicUnlock(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + UebTopicSource source = TopicEndpoint.manager.getUebTopicSource(topic); + boolean success = source.unlock(); if (success) return Response.status(Status.OK). - entity("Endpoints are unlocked"). + entity(source). build(); else - return Response.status(Status.SERVICE_UNAVAILABLE). - entity("Endpoints cannot be unlocked"). + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation on " + topic)). build(); } - @PUT - @Path("engine/topics/{topic}/ueb/sources/unlock") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response unlockTopic(@PathParam("topic") String topicName) { - UebTopicSource reader = TopicEndpoint.manager.getUebTopicSource(topicName); - boolean success = reader.unlock(); - if (success) - return Response.status(Status.OK). - entity("Endpoints are unlocked"). - build(); - else - return Response.status(Status.SERVICE_UNAVAILABLE). - entity("Endpoints cannot be unlocked"). - build(); + @GET + @Path("engine/topics/sources/dmaap/{topic}/switches") + @ApiOperation( + value="DMaaP Topic Control Switches", + notes="List of the DMaaP Topic Control Switches", + responseContainer="List" + ) + public Response dmaapTopicSwitches() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Switches.values())). + build(); } @PUT - @Path("engine/controllers/{controllerName}/lock") - @Produces(MediaType.APPLICATION_JSON) - public Response lockController(@PathParam("controllerName") String controllerName) { - PolicyController policyController = PolicyController.factory.get(controllerName); - boolean success = policyController.lock(); + @Path("engine/topics/sources/dmaap/{topic}/switches/lock") + @ApiOperation( + value="Locks an DMaaP Source topic", + response=DmaapTopicSource.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response dmmapTopicLock(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + DmaapTopicSource source = TopicEndpoint.manager.getDmaapTopicSource(topic); + boolean success = source.lock(); if (success) return Response.status(Status.OK). - entity("Controller " + controllerName + " is now locked"). + entity(source). build(); else - return Response.status(Status.SERVICE_UNAVAILABLE). - entity("Controller " + controllerName + " cannot be locked"). + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation on " + topic)). build(); - } + } @DELETE - @Path("engine/controllers/{controllerName}/lock") - @Produces(MediaType.APPLICATION_JSON) - public Response unlockController(@PathParam("controllerName") String controllerName) { - PolicyController policyController = PolicyController.factory.get(controllerName); - boolean success = policyController.unlock(); + @Path("engine/topics/sources/dmaap/{topic}/switches/lock") + @ApiOperation( + value="Unlocks an DMaaP Source topic", + response=DmaapTopicSource.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response dmaapTopicUnlock(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + DmaapTopicSource source = TopicEndpoint.manager.getDmaapTopicSource(topic); + boolean success = source.unlock(); if (success) return Response.status(Status.OK). - entity("Controller " + controllerName + " is now unlocked"). + entity(source). build(); else return Response.status(Status.SERVICE_UNAVAILABLE). - entity("Controller " + controllerName + " cannot be unlocked"). + entity(new Error("cannot perform operation on " + topic)). build(); } - @POST - @Path("engine/util/coders/filters/rules/{ruleName}") - @Produces(MediaType.APPLICATION_JSON) - public Response rules(@DefaultValue("false") @QueryParam("negate") boolean negate, - @PathParam("ruleName") String name, - String regex) { - String literalRegex = Pattern.quote(regex); - if (negate) - literalRegex = "^(?!" + literalRegex + "$).*"; - - return Response.status(Status.OK). - entity(new JsonProtocolFilter.FilterRule(name,literalRegex)). - build(); + @PUT + @Path("engine/topics/sources/ueb/{topic}/events") + @Consumes(MediaType.TEXT_PLAIN) + @ApiOperation( + value="Offers an event to an UEB topic for internal processing by the engine", + notes="The offered event is treated as it was incoming from the network", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The topic information cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response uebOffer(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Network Message", required=true) + String json) { + try { + UebTopicSource uebReader = TopicEndpoint.manager.getUebTopicSource(topic); + boolean success = uebReader.offer(json); + if (success) + return Response.status(Status.OK). + entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSource(topic).getRecentEvents())). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("Failure to inject event over " + topic)). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(topic + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(topic + " not acceptable due to current state")). + build(); + } catch (Exception e) { + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(e.getMessage())). + build(); + } + } + + @PUT + @Path("engine/topics/sources/dmaap/{topic}/events") + @Consumes(MediaType.TEXT_PLAIN) + @ApiOperation( + value="Offers an event to a DMaaP topic for internal processing by the engine", + notes="The offered event is treated as it was incoming from the network", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The topic information cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response dmaapOffer(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Network Message", required=true) + String json) { + try { + DmaapTopicSource dmaapReader = TopicEndpoint.manager.getDmaapTopicSource(topic); + boolean success = dmaapReader.offer(json); + if (success) + return Response.status(Status.OK). + entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSource(topic).getRecentEvents())). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("Failure to inject event over " + topic)). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(topic + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(topic + " not acceptable due to current state")). + build(); + } catch (Exception e) { + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(e.getMessage())). + build(); + } } @GET - @Path("engine/util/uuid") + @Path("engine/tools/uuid") + @ApiOperation( + value="Produces an UUID", + notes="UUID generation utility" + ) + @Produces(MediaType.TEXT_PLAIN) public Response uuid() { return Response.status(Status.OK). entity(UUID.randomUUID().toString()). @@ -1381,54 +2203,52 @@ public class RestManager { /* * Helper classes for aggregation of results */ - - - /** - * Endpoints aggregation Helper class - */ - public static class Endpoints { - public List<TopicSource> sources; - public List<TopicSink> sinks; - - public Endpoints(List<TopicSource> sources, - List<TopicSink> sinks) { - this.sources = sources; - this.sinks = sinks; - } - } - - /** - * Endpoint Helper Class - */ - public static class Endpoint { - public TopicSource source; - public TopicSink sink; - - public Endpoint(TopicSource source, - TopicSink sink) { - this.source = source; - this.sink = sink; - } - } /** - * Coding (Encoding) Helper class + * Coding/Encoding Results Aggregation Helper class */ public static class CodingResult { + /** + * serialized output + */ + public String jsonEncoding; + /** + * encoding result + */ + public Boolean encoding; + + /** + * decoding result + */ public Boolean decoding; } + /** + * Generic Error Reporting class + */ public static class Error { public String error; - /** - * @param error - */ public Error(String error) { this.error = error; } } + + /** + * Feed Ports into Resources + */ + public enum Inputs { + configuration, + } + + /** + * Resource Toggles + */ + public enum Switches { + activation, + lock, + } } diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java index d2133374..f18aa78e 100644 --- a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java +++ b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java @@ -47,6 +47,7 @@ import org.openecomp.policy.drools.protocol.configuration.ControllerConfiguratio import org.openecomp.policy.drools.protocol.configuration.PdpdConfiguration; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -162,6 +163,14 @@ public interface PolicyEngine extends Startable, Lockable, TopicListener { */ public List<PolicyController> getPolicyControllers(); + + /** + * get policy controller names + * + * @return list of controller names + */ + public List<String> getPolicyControllerIds(); + /** * get unmanaged sources * @@ -296,13 +305,6 @@ public interface PolicyEngine extends Startable, Lockable, TopicListener { * Invoked when the host goes into the standby state. */ public void deactivate(); - - /** - * get policy controller names - * - * @return list of controller names - */ - public List<String> getControllers(); /** * Policy Engine Manager @@ -1037,8 +1039,9 @@ class PolicyEngineManager implements PolicyEngine { /** * {@inheritDoc} */ + @JsonProperty("controllers") @Override - public List<String> getControllers() { + public List<String> getPolicyControllerIds() { List<String> controllerNames = new ArrayList<String>(); for (PolicyController controller: PolicyController.factory.inventory()) { controllerNames.add(controller.getName()); diff --git a/policy-management/src/main/server/config/IntegrityMonitor.properties b/policy-management/src/main/server/config/IntegrityMonitor.properties index 529abcda..293f3582 100644 --- a/policy-management/src/main/server/config/IntegrityMonitor.properties +++ b/policy-management/src/main/server/config/IntegrityMonitor.properties @@ -25,6 +25,7 @@ http.server.services.TEST.host=0.0.0.0 http.server.services.TEST.port=9981 http.server.services.TEST.restClasses=org.openecomp.policy.drools.core.IntegrityMonitorRestManager http.server.services.TEST.managed=false +http.server.services.TEST.swagger=true # The following were added as part of US673632 # diff --git a/policy-management/src/main/server/config/policy-engine.properties b/policy-management/src/main/server/config/policy-engine.properties index 647f7367..dbaf72af 100644 --- a/policy-management/src/main/server/config/policy-engine.properties +++ b/policy-management/src/main/server/config/policy-engine.properties @@ -44,3 +44,4 @@ http.server.services.CONFIG.userName=${{ENGINE_MANAGEMENT_USER}} http.server.services.CONFIG.password=${{ENGINE_MANAGEMENT_PASSWORD}} http.server.services.CONFIG.restPackages=org.openecomp.policy.drools.server.restful http.server.services.CONFIG.managed=false +http.server.services.CONFIG.swagger=true diff --git a/policy-management/src/main/server/config/policy-healthcheck.properties b/policy-management/src/main/server/config/policy-healthcheck.properties index 51da7ece..8a44fb9b 100644 --- a/policy-management/src/main/server/config/policy-healthcheck.properties +++ b/policy-management/src/main/server/config/policy-healthcheck.properties @@ -3,6 +3,7 @@ http.server.services.HEALTHCHECK.host=0.0.0.0 http.server.services.HEALTHCHECK.port=6969 http.server.services.HEALTHCHECK.restClasses=org.openecomp.policy.drools.healthcheck.RestHealthCheck http.server.services.HEALTHCHECK.managed=false +http.server.services.HEALTHCHECK.swagger=true http.client.services=PAP,PDP diff --git a/policy-persistence/pom.xml b/policy-persistence/pom.xml index b8677619..d6c90d5e 100644 --- a/policy-persistence/pom.xml +++ b/policy-persistence/pom.xml @@ -96,7 +96,7 @@ <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-jersey2-jaxrs</artifactId> - <version>${swagger.version}</version> + <scope>provided</scope> </dependency> <dependency> <groupId>org.openecomp.policy.drools-pdp</groupId> @@ -33,9 +33,6 @@ <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> - - <swagger-maven-plugin-version>3.1.4</swagger-maven-plugin-version> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.source.version>1.8</project.source.version> <project.target.version>1.8</project.target.version> @@ -43,6 +40,7 @@ <dmaap.version>0.2.12</dmaap.version> <cambria.version>0.0.1</cambria.version> <jersey.version>2.22.2</jersey.version> + <jersey.swagger.version>1.5.13</jersey.swagger.version> <jackson.version>2.8.4</jackson.version> <sonar.language>java</sonar.language> @@ -158,6 +156,11 @@ <artifactId>jersey-container-servlet-core</artifactId> <version>${jersey.version}</version> </dependency> + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + <version>${jersey.swagger.version}</version> + </dependency> </dependencies> </dependencyManagement> @@ -175,53 +178,6 @@ </configuration> </plugin> <plugin> - <groupId>com.github.kongchen</groupId> - <artifactId>swagger-maven-plugin</artifactId> - <version>${swagger-maven-plugin-version}</version> - <configuration> - <apiSources> - <apiSource> - <springmvc>false</springmvc> - <locations> - <location> - org.openecomp.policy.drools.core.DroolsPDPIntegrityMonitor - </location> - </locations> - <info> - <title>Drools PDP</title> - <version>1.0.0</version> - </info> - <swaggerDirectory>${project.build.directory}/swagger/integrityMonitor</swaggerDirectory> - <swaggerFileName>swagger</swaggerFileName> - <attachSwaggerArtifact>true</attachSwaggerArtifact> - </apiSource> - </apiSources> - </configuration> - <dependencies> - <!-- Adding dependency to swagger-hibernate-validations to enable the BeanValidator as a custom - model converter --> - <dependency> - <groupId>io.swagger</groupId> - <artifactId>swagger-hibernate-validations</artifactId> - <version>1.5.6</version> - </dependency> - <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --> - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-lang3</artifactId> - <version>3.4</version> - </dependency> - </dependencies> - <executions> - <execution> - <phase>compile</phase> - <goals> - <goal>generate</goal> - </goals> - </execution> - </executions> - </plugin> - <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> <version>2.8</version> <!-- This version supports the "deployAtEnd" parameter --> |