summaryrefslogtreecommitdiffstats
path: root/client/client-monitoring/src/main/java
diff options
context:
space:
mode:
authorramverma <ram.krishna.verma@ericsson.com>2018-07-06 16:29:16 +0100
committerramverma <ram.krishna.verma@ericsson.com>2018-07-09 15:14:03 +0100
commit0ba667816e703344eec33bda147546b30b6bbd5b (patch)
treeda7f8e53a8ae1266717957eea7e95324cf3fe1d7 /client/client-monitoring/src/main/java
parentdcf8f703fdd07161c86231ecc4af0f25872a45f4 (diff)
Adding client monitoring module to apex-pdp
Change-Id: I6b4d00a5e49326f62f3585526ede8e89df99d7e5 Issue-ID: POLICY-864 Signed-off-by: ramverma <ram.krishna.verma@ericsson.com>
Diffstat (limited to 'client/client-monitoring/src/main/java')
-rw-r--r--client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRest.java80
-rw-r--r--client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestMain.java192
-rw-r--r--client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameterException.java49
-rw-r--r--client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameterParser.java116
-rw-r--r--client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameters.java115
-rw-r--r--client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestResource.java346
-rw-r--r--client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ParameterCheck.java211
-rw-r--r--client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/package-info.java27
8 files changed, 1136 insertions, 0 deletions
diff --git a/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRest.java b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRest.java
new file mode 100644
index 000000000..d6f7e64ad
--- /dev/null
+++ b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRest.java
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.client.monitoring.rest;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.onap.policy.apex.model.utilities.Assertions;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This class is used to launch the services. It creates a Grizzly embedded web server and runs the services.
+ */
+public class ApexMonitoringRest {
+ // Logger for this class
+ private static final XLogger logger = XLoggerFactory.getXLogger(ApexMonitoringRest.class);
+
+ // The HTTP server exposing JAX-RS resources defined in this application.
+ private HttpServer server;
+
+ /**
+ * Starts the HTTP server for the Apex services client on the default base URI and with the default REST packages
+ */
+ public ApexMonitoringRest() {
+ this(new ApexMonitoringRestParameters());
+ }
+
+ /**
+ * Starts the HTTP server for the Apex services client
+ *
+ * @param parameters: The Apex parameters to use to start the server
+ */
+ public ApexMonitoringRest(final ApexMonitoringRestParameters parameters) {
+ Assertions.argumentNotNull(parameters, "parameters may not be null");
+
+ logger.debug("Apex services RESTful client starting . . .");
+
+ // Create a resource configuration that scans for JAX-RS resources and providers
+ // in org.onap.policy.apex.services.client.monitoring.rest package
+ final ResourceConfig rc = new ResourceConfig().packages(parameters.getRESTPackages());
+
+ // create and start a new instance of grizzly http server
+ // exposing the Jersey application at BASE_URI
+ server = GrizzlyHttpServerFactory.createHttpServer(parameters.getBaseURI(), rc);
+
+ // Add static content
+ server.getServerConfiguration().addHttpHandler(new org.glassfish.grizzly.http.server.CLStaticHttpHandler(
+ ApexMonitoringRestMain.class.getClassLoader(), "/webapp/"), parameters.getStaticPath());
+
+ logger.debug("Apex services RESTful client started");
+ }
+
+ /**
+ * Shut down the web server
+ */
+ public void shutdown() {
+ logger.debug("Apex services RESTful client shutting down . . .");
+ server.shutdown();
+ logger.debug("Apex services RESTful client shut down");
+ }
+}
diff --git a/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestMain.java b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestMain.java
new file mode 100644
index 000000000..fcc29ed29
--- /dev/null
+++ b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestMain.java
@@ -0,0 +1,192 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.client.monitoring.rest;
+
+import java.io.PrintStream;
+
+/**
+ * User: ewatkmi Date: 31 Jul 2017
+ */
+public class ApexMonitoringRestMain {
+ // Services state
+ public enum ServicesState {
+ STOPPED, READY, INITIALIZING, RUNNING
+ };
+
+ private ServicesState state = ServicesState.STOPPED;
+
+ // The parameters for the client
+ private ApexMonitoringRestParameters parameters = null;
+
+ // Output and error streams for messages
+ private final PrintStream outStream;
+
+ // The Apex services client this class is running
+ private ApexMonitoringRest apexMonitoringRest = null;
+
+ /**
+ * Main method, main entry point for command
+ *
+ * @param args The command line arguments for the client
+ */
+ public static void main(final String[] args) {
+ try {
+ final ApexMonitoringRestMain restMain = new ApexMonitoringRestMain(args, System.out);
+ restMain.init();
+ } catch (final Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }
+
+ /**
+ * Constructor, kicks off the rest service
+ *
+ * @param args The command line arguments for the RESTful service
+ * @param outStream The stream for output messages
+ */
+ public ApexMonitoringRestMain(final String[] args, final PrintStream outStream) {
+ // Save the streams for output and error
+ this.outStream = outStream;
+
+ // Client parameter parsing
+ final ApexMonitoringRestParameterParser parser = new ApexMonitoringRestParameterParser();
+
+ try {
+ // Get and check the parameters
+ parameters = parser.parse(args);
+ } catch (final ApexMonitoringRestParameterException e) {
+ throw new ApexMonitoringRestParameterException(
+ "Apex Services REST endpoint (" + this.toString() + ") parameter error, " + e.getMessage() + '\n'
+ + parser.getHelp(ApexMonitoringRestMain.class.getCanonicalName()));
+ }
+
+ if (parameters.isHelpSet()) {
+ throw new ApexMonitoringRestParameterException(
+ parser.getHelp(ApexMonitoringRestMain.class.getCanonicalName()));
+ }
+
+ // Validate the parameters
+ final String validationMessage = parameters.validate();
+ if (validationMessage.length() > 0) {
+ throw new ApexMonitoringRestParameterException(
+ "Apex Services REST endpoint (" + this.toString() + ") parameters invalid, " + validationMessage
+ + '\n' + parser.getHelp(ApexMonitoringRestMain.class.getCanonicalName()));
+ }
+
+ state = ServicesState.READY;
+ }
+
+ /**
+ * Initialize the rest service
+ */
+ public void init() {
+ outStream.println("Apex Services REST endpoint (" + this.toString() + ") starting at "
+ + parameters.getBaseURI().toString() + " . . .");
+
+ try {
+ state = ServicesState.INITIALIZING;
+
+ // Start the REST service
+ apexMonitoringRest = new ApexMonitoringRest(parameters);
+
+ // Add a shutdown hook to shut down the rest services when the process is exiting
+ Runtime.getRuntime().addShutdownHook(new Thread(new ApexServicesShutdownHook()));
+
+ state = ServicesState.RUNNING;
+
+ if (parameters.getTimeToLive() == ApexMonitoringRestParameters.INFINITY_TIME_TO_LIVE) {
+ outStream.println("Apex Services REST endpoint (" + this.toString() + ") started at "
+ + parameters.getBaseURI().toString());
+ } else {
+ outStream.println("Apex Services REST endpoint (" + this.toString() + ") started");
+ }
+
+ // Find out how long is left to wait
+ long timeRemaining = parameters.getTimeToLive();
+ while (timeRemaining == ApexMonitoringRestParameters.INFINITY_TIME_TO_LIVE || timeRemaining > 0) {
+ // decrement the time to live in the non-infinity case
+ if (timeRemaining > 0) {
+ timeRemaining--;
+ }
+
+ // Wait for a second
+ Thread.sleep(1000);
+ }
+ } catch (final Exception e) {
+ outStream.println(
+ "Apex Services REST endpoint (" + this.toString() + ") failed at with error: " + e.getMessage());
+ } finally {
+ if (apexMonitoringRest != null) {
+ apexMonitoringRest.shutdown();
+ apexMonitoringRest = null;
+ }
+ state = ServicesState.STOPPED;
+ }
+
+ }
+
+ /**
+ * Get services state.
+ *
+ * @return the service state
+ */
+ public ServicesState getState() {
+ return state;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder ret = new StringBuilder();
+ ret.append(this.getClass().getSimpleName()).append(": Config=[").append(this.parameters).append("], State=")
+ .append(this.getState());
+ return ret.toString();
+ }
+
+ /**
+ * Explicitly shut down the services
+ */
+ public void shutdown() {
+ if (apexMonitoringRest != null) {
+ outStream.println("Apex Services REST endpoint (" + this.toString() + ") shutting down");
+ apexMonitoringRest.shutdown();
+ }
+ state = ServicesState.STOPPED;
+ outStream.println("Apex Services REST endpoint (" + this.toString() + ") shut down");
+ }
+
+ /**
+ * This class is a shutdown hook for the Apex services command
+ */
+ private class ApexServicesShutdownHook implements Runnable {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ @Override
+ public void run() {
+ if (apexMonitoringRest != null) {
+ apexMonitoringRest.shutdown();
+ }
+ }
+ }
+
+}
diff --git a/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameterException.java b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameterException.java
new file mode 100644
index 000000000..cbbc2940a
--- /dev/null
+++ b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameterException.java
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.client.monitoring.rest;
+
+/**
+ * A run time exception used to report parsing and parameter input errors
+ *
+ * User: ewatkmi Date: 31 Jul 2017
+ */
+public class ApexMonitoringRestParameterException extends IllegalArgumentException {
+ private static final long serialVersionUID = 6520231162404452427L;
+
+ /**
+ * Create an ApexServicesRestParameterException with a message.
+ *
+ * @param message the message
+ */
+ public ApexMonitoringRestParameterException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Create an ApexServicesRestParameterException with a message and an exception.
+ *
+ * @param message the message
+ * @param throwable The exception that caused the exception
+ */
+ public ApexMonitoringRestParameterException(final String message, final Throwable throwable) {
+ super(message, throwable);
+ }
+}
diff --git a/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameterParser.java b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameterParser.java
new file mode 100644
index 000000000..35ee6b4fa
--- /dev/null
+++ b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameterParser.java
@@ -0,0 +1,116 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.client.monitoring.rest;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+
+/**
+ * This class reads and handles command line parameters to the Apex RESTful services
+ *
+ * User: ewatkmi Date: 31 Jul 2017
+ */
+public class ApexMonitoringRestParameterParser {
+ // Apache Commons CLI options
+ Options options;
+
+ /**
+ * Construct the options for the CLI RESTful services
+ */
+ public ApexMonitoringRestParameterParser() {
+ options = new Options();
+ options.addOption("h", "help", false, "outputs the usage of this command");
+ options.addOption(Option.builder("p").longOpt("port").desc("port to use for the Apex Services REST calls")
+ .hasArg().argName("PORT").required(false).type(Number.class).build());
+ options.addOption(Option.builder("t").longOpt("time-to-live")
+ .desc("the amount of time in seconds that the server will run for before terminating").hasArg()
+ .argName("TIME_TO_LIVE").required(false).type(Number.class).build());
+ }
+
+ /**
+ * Parse the command line options.
+ *
+ * @param args the arguments
+ * @return parsed parameters
+ */
+ public ApexMonitoringRestParameters parse(final String[] args) {
+ CommandLine commandLine = null;
+ try {
+ commandLine = new DefaultParser().parse(options, args);
+ } catch (final ParseException e) {
+ throw new ApexMonitoringRestParameterException(
+ "invalid command line arguments specified : " + e.getMessage());
+ }
+
+ final ApexMonitoringRestParameters parameters = new ApexMonitoringRestParameters();
+ final String[] remainingArgs = commandLine.getArgs();
+
+ if (commandLine.getArgs().length > 0) {
+ throw new ApexMonitoringRestParameterException(
+ "too many command line arguments specified : " + Arrays.toString(remainingArgs));
+ }
+
+ if (commandLine.hasOption('h')) {
+ parameters.setHelp(true);
+ }
+ try {
+ if (commandLine.hasOption('p')) {
+ parameters.setRESTPort(((Number) commandLine.getParsedOptionValue("port")).intValue());
+ }
+ } catch (final ParseException e) {
+ throw new ApexMonitoringRestParameterException("error parsing argument \"port\" :" + e.getMessage(), e);
+ }
+ try {
+ if (commandLine.hasOption('t')) {
+ parameters.setTimeToLive(((Number) commandLine.getParsedOptionValue("time-to-live")).longValue());
+ }
+ } catch (final ParseException e) {
+ throw new ApexMonitoringRestParameterException("error parsing argument \"time-to-live\" :" + e.getMessage(),
+ e);
+ }
+
+ return parameters;
+ }
+
+ /**
+ * Get help information.
+ *
+ * @param mainClassName the main class name for the help output
+ * @return help string
+ */
+ public String getHelp(final String mainClassName) {
+ final StringWriter stringWriter = new StringWriter();
+ final PrintWriter stringPrintWriter = new PrintWriter(stringWriter);
+
+ final HelpFormatter helpFormatter = new HelpFormatter();
+ helpFormatter.printHelp(stringPrintWriter, 120, mainClassName + " [options...] ", "", options, 0, 0, "");
+
+ return stringWriter.toString();
+ }
+}
diff --git a/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameters.java b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameters.java
new file mode 100644
index 000000000..a1a8efc57
--- /dev/null
+++ b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestParameters.java
@@ -0,0 +1,115 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.client.monitoring.rest;
+
+import java.net.URI;
+
+/**
+ * This class reads and handles command line parameters to the Apex RESTful services
+ *
+ * User: ewatkmi Date: 31 Jul 2017
+ */
+public class ApexMonitoringRestParameters {
+ public static final int DEFAULT_REST_PORT = 18989;
+ public static final int INFINITY_TIME_TO_LIVE = -1;
+
+ // Base URI the HTTP server will listen on
+ private static final String DEFAULT_SERVER_URI_ROOT = "http://localhost:";
+ private static final String DEFAULT_REST_PATH = "/apexservices/";
+ private static final String DEFAULT_STATIC_PATH = "/";
+
+ // Package that will field REST requests
+ public static final String[] DEFAULT_PACKAGES =
+ new String[] { "org.onap.policy.apex.services.client.monitoring.rest" };
+
+ // The services parameters
+ private boolean helpSet = false;
+ private int restPort = DEFAULT_REST_PORT;
+ private long timeToLive = INFINITY_TIME_TO_LIVE;
+
+ public String validate() {
+ String validationMessage = "";
+ validationMessage += validatePort();
+ validationMessage += validateTimeToLive();
+
+ return validationMessage;
+ }
+
+ public URI getBaseURI() {
+ return URI.create(DEFAULT_SERVER_URI_ROOT + restPort + DEFAULT_REST_PATH);
+ }
+
+ public String[] getRESTPackages() {
+ return DEFAULT_PACKAGES;
+ }
+
+ public String getStaticPath() {
+ return DEFAULT_STATIC_PATH;
+ }
+
+ private String validatePort() {
+ if (restPort < 1024 || restPort > 65535) {
+ return "port must be greater than 1023 and less than 65536\n";
+ } else {
+ return "";
+ }
+ }
+
+ private String validateTimeToLive() {
+ if (timeToLive < -1) {
+ return "time to live must be greater than -1 (set to -1 to wait forever)\n";
+ } else {
+ return "";
+ }
+ }
+
+ public boolean isHelpSet() {
+ return helpSet;
+ }
+
+ public void setHelp(final boolean helpSet) {
+ this.helpSet = helpSet;
+ }
+
+ public int getRESTPort() {
+ return restPort;
+ }
+
+ public void setRESTPort(final int restPort) {
+ this.restPort = restPort;
+ }
+
+ public long getTimeToLive() {
+ return timeToLive;
+ }
+
+ public void setTimeToLive(final long timeToLive) {
+ this.timeToLive = timeToLive;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder ret = new StringBuilder();
+ ret.append(this.getClass().getSimpleName()).append(": URI=").append(this.getBaseURI()).append(", TTL=")
+ .append(this.getTimeToLive()).append("sec");
+ return ret.toString();
+ }
+}
diff --git a/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestResource.java b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestResource.java
new file mode 100644
index 000000000..84f29dfe2
--- /dev/null
+++ b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ApexMonitoringRestResource.java
@@ -0,0 +1,346 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.client.monitoring.rest;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onap.policy.apex.core.deployment.ApexDeploymentException;
+import org.onap.policy.apex.core.deployment.EngineServiceFacade;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.enginemodel.concepts.AxEngineModel;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The class represents the root resource exposed at the base URL<br>
+ * The url to access this resource would be in the form {@code <baseURL>/rest/....} <br>
+ * For example: a GET request to the following URL
+ * {@code http://localhost:18989/apexservices/rest/?hostName=localhost&port=12345}
+ *
+ * <b>Note:</b> An allocated {@code hostName} and {@code port} query parameter must be included in all requests.
+ * Datasets for different {@code hostName} are completely isolated from one another.
+ *
+ */
+@Path("monitoring/")
+@Produces({ MediaType.APPLICATION_JSON })
+@Consumes({ MediaType.APPLICATION_JSON })
+
+public class ApexMonitoringRestResource {
+ // Get a reference to the logger
+ private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexMonitoringRestResource.class);
+
+ // Set the maximum number of stored data entries to be stored for each engine
+ private static final int maxCachedEntries = 50;
+
+ // Set up a map separated by host and engine for the data
+ private static final HashMap<String, HashMap<String, List<Counter>>> cache =
+ new HashMap<String, HashMap<String, List<Counter>>>();
+
+ // Set up a map separated by host for storing the state of periodic events
+ private static final HashMap<String, Boolean> periodicEventsStateCache = new HashMap<String, Boolean>();
+
+ /**
+ * Constructor, a new resource director is created for each request.
+ */
+ public ApexMonitoringRestResource() {}
+
+ /**
+ * Query the engine service for data
+ *
+ * @param hostName the host name of the engine service to connect to.
+ * @param port the port number of the engine service to connect to.
+ * @return a Response object containing the engines service, status and context data in JSON
+ */
+ @GET
+ public Response createSession(@QueryParam("hostName") final String hostName, @QueryParam("port") final int port) {
+ final Gson gson = new Gson();
+ final String host = hostName + ":" + port;
+ final EngineServiceFacade engineServiceFacade = new EngineServiceFacade(hostName, port);
+
+ try {
+ engineServiceFacade.init();
+ } catch (final ApexDeploymentException e) {
+ final String errorMessage = "Error connecting to Apex Engine Service at " + host;
+ LOGGER.warn(errorMessage + "<br>", e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage + "\n" + e.getMessage())
+ .build();
+ }
+
+ final JsonObject responseObject = new JsonObject();
+
+ // Engine Service data
+ responseObject.addProperty("engine_id", engineServiceFacade.getKey().getID());
+ responseObject.addProperty("model_id",
+ engineServiceFacade.getApexModelKey() != null ? engineServiceFacade.getApexModelKey().getID()
+ : "Not Set");
+ responseObject.addProperty("server", hostName);
+ responseObject.addProperty("port", Integer.toString(port));
+ responseObject.addProperty("periodic_events", getPeriodicEventsState(host));
+
+ // Engine Status data
+ final JsonArray engineStatusList = new JsonArray();
+
+ for (final AxArtifactKey engineKey : engineServiceFacade.getEngineKeyArray()) {
+ try {
+ final JsonObject engineStatusObject = new JsonObject();
+ final AxEngineModel axEngineModel = engineServiceFacade.getEngineStatus(engineKey);
+ engineStatusObject.addProperty("timestamp", axEngineModel.getTimeStampString());
+ engineStatusObject.addProperty("id", engineKey.getID());
+ engineStatusObject.addProperty("status", axEngineModel.getState().toString());
+ engineStatusObject.addProperty("last_message", axEngineModel.getStats().getTimeStampString());
+ engineStatusObject.addProperty("up_time", axEngineModel.getStats().getUpTime() / 1000L);
+ engineStatusObject.addProperty("policy_executions", axEngineModel.getStats().getEventCount());
+ engineStatusObject.addProperty("last_policy_duration",
+ gson.toJson(
+ getValuesFromCache(host, engineKey.getID() + "_last_policy_duration",
+ axEngineModel.getTimestamp(), axEngineModel.getStats().getLastExecutionTime()),
+ List.class));
+ engineStatusObject.addProperty("average_policy_duration",
+ gson.toJson(getValuesFromCache(host, engineKey.getID() + "_average_policy_duration",
+ axEngineModel.getTimestamp(),
+ (long) axEngineModel.getStats().getAverageExecutionTime()), List.class));
+ engineStatusList.add(engineStatusObject);
+ } catch (final ApexException e) {
+ LOGGER.warn("Error getting status of engine with ID " + engineKey.getID() + "<br>", e);
+ }
+ }
+ responseObject.add("status", engineStatusList);
+
+ // Engine context data
+ final JsonArray engineContextList = new JsonArray();
+ for (final AxArtifactKey engineKey : engineServiceFacade.getEngineKeyArray()) {
+ try {
+ final String engineInfo = engineServiceFacade.getEngineInfo(engineKey);
+ if (engineInfo != null && !engineInfo.trim().isEmpty()) {
+ final JsonObject engineContextObject = new JsonObject();
+ engineContextObject.addProperty("id", engineKey.getID());
+ engineContextObject.addProperty("engine_info", engineInfo);
+ engineContextList.add(engineContextObject);
+ }
+ } catch (final ApexException e) {
+ LOGGER.warn("Error getting runtime information of engine with ID " + engineKey.getID() + "<br>", e);
+ }
+ }
+ responseObject.add("context", engineContextList);
+
+ return Response.ok(responseObject.toString(), MediaType.APPLICATION_JSON).build();
+ }
+
+ /**
+ * Start/Stop and Apex engine
+ *
+ * @param hostName the host name of the engine service to connect to.
+ * @param port the port number of the engine service to connect to.
+ * @param engineId the id of the engine to be started/stopped.
+ * @param startStop the parameter to start/stop the engine. Expects either "Start" or "Stop"
+ * @return a Response object of type 200
+ */
+ @GET
+ @Path("startstop/")
+ public Response startStop(@QueryParam("hostName") final String hostName, @QueryParam("port") final int port,
+ @QueryParam("engineId") final String engineId, @QueryParam("startstop") final String startStop) {
+ final EngineServiceFacade engineServiceFacade = new EngineServiceFacade(hostName, port);
+
+ try {
+ engineServiceFacade.init();
+ } catch (final ApexDeploymentException e) {
+ final String errorMessage = "Error connecting to Apex Engine Service at " + hostName + ":" + port;
+ LOGGER.warn(errorMessage + "<br>", e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage + "\n" + e.getMessage())
+ .build();
+ }
+
+ try {
+ final Map<String, String[]> parameterMap = new HashMap<String, String[]>();
+ parameterMap.put("hostname", new String[] { hostName });
+ parameterMap.put("port", new String[] { Integer.toString(port) });
+ parameterMap.put("AxArtifactKey#" + engineId, new String[] { startStop });
+ final AxArtifactKey engineKey = ParameterCheck.getEngineKey(parameterMap);
+ if (startStop.equals("Start")) {
+ engineServiceFacade.startEngine(engineKey);
+ } else if (startStop.equals("Stop")) {
+ engineServiceFacade.stopEngine(engineKey);
+ }
+ } catch (final Exception e) {
+ final String errorMessage = "Error calling " + startStop + " on Apex Engine: " + engineId;
+ LOGGER.warn(errorMessage + "<br>", e);
+ final StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw));
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage + "\n" + sw.toString())
+ .build();
+ }
+
+ return Response.ok("{}").build();
+ }
+
+ /**
+ * Start/Stop and Apex engine
+ *
+ * @param hostName the host name of the engine service to connect to.
+ * @param port the port number of the engine service to connect to.
+ * @param engineId the id of the engine to be started/stopped.
+ * @param startStop the parameter to start/stop the engine. Expects either "Start" or "Stop"
+ * @param period the time between each event in milliseconds
+ * @return a Response object of type 200
+ */
+ @GET
+ @Path("periodiceventstartstop/")
+ public Response periodiceventStartStop(@QueryParam("hostName") final String hostName,
+ @QueryParam("port") final int port, @QueryParam("engineId") final String engineId,
+ @QueryParam("startstop") final String startStop, @QueryParam("period") final long period) {
+ final EngineServiceFacade engineServiceFacade = new EngineServiceFacade(hostName, port);
+ final String host = hostName + ":" + port;
+ try {
+ engineServiceFacade.init();
+ final Map<String, String[]> parameterMap = new HashMap<String, String[]>();
+ parameterMap.put("hostname", new String[] { hostName });
+ parameterMap.put("port", new String[] { Integer.toString(port) });
+ parameterMap.put("AxArtifactKey#" + engineId, new String[] { startStop });
+ parameterMap.put("period", new String[] { Long.toString(period) });
+ final AxArtifactKey engineKey = ParameterCheck.getEngineKey(parameterMap);
+ if (startStop.equals("Start")) {
+ engineServiceFacade.startPerioidicEvents(engineKey, period);
+ setPeriodicEventsState(host, true);
+ } else if (startStop.equals("Stop")) {
+ engineServiceFacade.stopPerioidicEvents(engineKey);
+ setPeriodicEventsState(host, false);
+ }
+ } catch (final ApexDeploymentException e) {
+ final String errorMessage = "Error connecting to Apex Engine Service at " + host;
+ LOGGER.warn(errorMessage + "<br>", e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage + "\n" + e.getMessage())
+ .build();
+ }
+
+ return Response.ok("{}").build();
+ }
+
+ /**
+ * Check if periodic events are running
+ *
+ * @param host the engine's host url
+ * @return a boolean stating if periodic events are running for a given host
+ */
+ private Boolean getPeriodicEventsState(final String host) {
+ return periodicEventsStateCache.containsKey(host) ? periodicEventsStateCache.get(host) : false;
+ }
+
+ /**
+ * Sets the state of periodic events for a host
+ *
+ * @param host the engine's host url
+ * @param boolean that states if periodic events have been started or stopped
+ */
+ private void setPeriodicEventsState(final String host, final Boolean isRunning) {
+ periodicEventsStateCache.put(host, isRunning);
+ }
+
+ /**
+ * This method takes in the latest data entry for an engine, adds it to an existing data set and returns the full
+ * map for that host and engine
+ *
+ * @param host the engine's host url
+ * @param id the engines id
+ * @param timestamp the timestamp of the latest data entry
+ * @param latestValue the value of the latest data entry
+ * @return a list of {@code Counter} objects for that engine
+ */
+ private List<Counter> getValuesFromCache(final String host, final String id, final long timestamp,
+ final long latestValue) {
+ SlidingWindowList<Counter> valueList;
+
+ if (!cache.containsKey(host)) {
+ cache.put(host, new HashMap<String, List<Counter>>());
+ }
+
+ if (cache.get(host).containsKey(id)) {
+ valueList = (SlidingWindowList<Counter>) cache.get(host).get(id);
+ } else {
+ valueList = new SlidingWindowList<Counter>(maxCachedEntries);
+ }
+ valueList.add(new Counter(timestamp, latestValue));
+
+ cache.get(host).put(id, valueList);
+
+ return valueList;
+ }
+
+ /**
+ * A list of values that uses a FIFO sliding window of a fixed size.
+ */
+ public class SlidingWindowList<V> extends LinkedList<V> {
+ private static final long serialVersionUID = -7187277916025957447L;
+
+ private final int maxEntries;
+
+ public SlidingWindowList(final int maxEntries) {
+ this.maxEntries = maxEntries;
+ }
+
+ @Override
+ public boolean add(final V e) {
+ if (this.size() > (maxEntries - 1)) {
+ this.removeFirst();
+ }
+ return super.add(e);
+ };
+
+ }
+
+ /**
+ * A class used to storing a single data entry for an engine.
+ */
+ public class Counter {
+ private long timestamp;
+ private long value;
+
+ public Counter(final long timestamp, final long value) {
+ this.timestamp = timestamp;
+ this.value = value;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public long getValue() {
+ return value;
+ }
+ }
+}
diff --git a/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ParameterCheck.java b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ParameterCheck.java
new file mode 100644
index 000000000..8edeb54f1
--- /dev/null
+++ b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/ParameterCheck.java
@@ -0,0 +1,211 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.client.monitoring.rest;
+
+import java.util.Map;
+
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class ParameterCheck is used to check parameters passed to the servlet.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public final class ParameterCheck {
+ private static final int MAX_PORT = 65535;
+
+ /**
+ * private constructor to prevent subclassing of this utility class.
+ */
+ private ParameterCheck() {}
+
+ /**
+ * The Enum StartStop is used to hold .
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+ public enum StartStop {
+ /** Start of an Apex engine has been ordered. */
+ START,
+ /** Stop of an Apex engine has been ordered. */
+ STOP
+ };
+
+ private static final XLogger LOGGER = XLoggerFactory.getXLogger(ParameterCheck.class);
+
+ private static final String HOSTNAME_PAR = "hostname";
+ private static final String PORT_PAR = "port";
+ private static final String AXARTIFACTKEY_PAR = "AxArtifactKey";
+
+ /**
+ * Gets the host name.
+ *
+ * @param parameterMap the parameter map
+ * @return the host name
+ */
+ public static String getHostName(final Map<String, String[]> parameterMap) {
+ if (!parameterMap.containsKey(HOSTNAME_PAR)) {
+ LOGGER.warn("parameter \"" + HOSTNAME_PAR + "\" not found");
+ return null;
+ }
+
+ final String[] hostNameValue = parameterMap.get(HOSTNAME_PAR);
+
+ if (hostNameValue.length == 0 || hostNameValue[0].trim().length() == 0) {
+ LOGGER.warn("value of parameter \"" + HOSTNAME_PAR + "\" not found");
+ return null;
+ }
+
+ return hostNameValue[0];
+ }
+
+ /**
+ * Gets the port.
+ *
+ * @param parameterMap the parameter map
+ * @return the port
+ */
+ public static int getPort(final Map<String, String[]> parameterMap) {
+ if (!parameterMap.containsKey(PORT_PAR)) {
+ LOGGER.warn("parameter \"" + PORT_PAR + "\" not found");
+ return -1;
+ }
+
+ final String[] portValue = parameterMap.get(PORT_PAR);
+
+ if (portValue.length == 0 || portValue[0].trim().length() == 0) {
+ LOGGER.warn("value of parameter \"" + PORT_PAR + "\" not found");
+ return -1;
+ }
+
+ int port = -1;
+ try {
+ port = Integer.parseInt(portValue[0]);
+ } catch (final Exception e) {
+ LOGGER.warn("value \"" + portValue[0] + "\"of parameter \"" + PORT_PAR + "\" not a valid integer", e);
+ return -1;
+ }
+
+ if (port <= 0 || port > MAX_PORT) {
+ LOGGER.warn("value \"" + portValue[0] + "\"of parameter \"" + PORT_PAR
+ + "\" not a valid port between 0 and 65535");
+ return -1;
+ }
+
+ return port;
+ }
+
+ /**
+ * Gets the engine key.
+ *
+ * @param parameterMap the parameter map
+ * @return the engine key
+ */
+ public static AxArtifactKey getEngineKey(final Map<String, String[]> parameterMap) {
+ String artifactKeyParameter = null;
+ for (final String parameter : parameterMap.keySet()) {
+ // Check for an AxArtifactKey parameter
+ if (parameter.startsWith(AXARTIFACTKEY_PAR)) {
+ artifactKeyParameter = parameter;
+ break;
+ }
+ }
+ if (artifactKeyParameter == null) {
+ LOGGER.warn("parameter \"" + AXARTIFACTKEY_PAR + "\" not found");
+ return null;
+ }
+
+ final String[] axArtifactKeyArray = artifactKeyParameter.split("#");
+
+ if (axArtifactKeyArray.length != 2) {
+ LOGGER.warn("value \"" + artifactKeyParameter + "\" of parameter \"" + AXARTIFACTKEY_PAR + "\" not valid");
+ return null;
+ }
+
+ return new AxArtifactKey(axArtifactKeyArray[1]);
+ }
+
+ /**
+ * Gets the start stop.
+ *
+ * @param parameterMap the parameter map
+ * @param engineKey the engine key
+ * @return the start stop
+ */
+ public static ParameterCheck.StartStop getStartStop(final Map<String, String[]> parameterMap,
+ final AxArtifactKey engineKey) {
+ final String startStopPar = AXARTIFACTKEY_PAR + '#' + engineKey.getID();
+ if (!parameterMap.containsKey(startStopPar)) {
+ LOGGER.warn("parameter \"" + startStopPar + "\" not found");
+ return null;
+ }
+
+ final String[] startStopValue = parameterMap.get(startStopPar);
+
+ if (startStopValue.length == 0 || startStopValue[0].trim().length() == 0) {
+ LOGGER.warn("value of parameter \"" + startStopPar + "\" not found");
+ return null;
+ }
+
+ ParameterCheck.StartStop startStop;
+ if (startStopValue[0].equalsIgnoreCase("start")) {
+ startStop = ParameterCheck.StartStop.START;
+ } else if (startStopValue[0].equalsIgnoreCase("stop")) {
+ startStop = ParameterCheck.StartStop.STOP;
+ } else {
+ LOGGER.warn("value \"" + startStopValue[0] + "\"of parameter \"" + startStopPar
+ + "\" not \"start\" or \"stop\"");
+ return null;
+ }
+
+ return startStop;
+ }
+
+ /**
+ * Find and return a long value with the given name.
+ *
+ * @param parameterMap The parameter map containing the value
+ * @param longName The name of the long parameter
+ * @return The long value
+ */
+ public static long getLong(final Map<String, String[]> parameterMap, final String longName) {
+ if (!parameterMap.containsKey(longName)) {
+ LOGGER.warn("parameter \"" + longName + "\" not found");
+ return -1;
+ }
+
+ final String[] longValue = parameterMap.get(longName);
+
+ if (longValue.length == 0 || longValue[0].trim().length() == 0) {
+ LOGGER.warn("value of parameter \"" + longName + "\" not found");
+ return -1;
+ }
+
+ try {
+ return Long.parseLong(longValue[0]);
+ } catch (final Exception e) {
+ LOGGER.warn("value \"" + longValue[0] + "\"of parameter \"" + longName + "\" not a valid long", e);
+ return -1;
+ }
+ }
+}
diff --git a/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/package-info.java b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/package-info.java
new file mode 100644
index 000000000..d6c8d3c5e
--- /dev/null
+++ b/client/client-monitoring/src/main/java/org/onap/policy/apex/client/monitoring/rest/package-info.java
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Implements the RESTful monitoring client.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+
+package org.onap.policy.apex.client.monitoring.rest;