From c6d74e6cee17405b9d26506b06259ccb2f38c737 Mon Sep 17 00:00:00 2001 From: ramverma Date: Wed, 11 Jul 2018 14:21:13 +0100 Subject: Adding client deployment module to apex-pdp Change-Id: Idd74e9846c3fa75d305a9dde98a98d92dd0520a9 Issue-ID: POLICY-864 Signed-off-by: ramverma --- client/client-deployment/pom.xml | 191 +++++++++++++++++++ .../client/deployment/rest/ApexDeploymentRest.java | 84 ++++++++ .../deployment/rest/ApexDeploymentRestMain.java | 192 +++++++++++++++++++ .../rest/ApexDeploymentRestParameterException.java | 49 +++++ .../rest/ApexDeploymentRestParameterParser.java | 116 +++++++++++ .../rest/ApexDeploymentRestParameters.java | 115 +++++++++++ .../rest/ApexDeploymentRestResource.java | 146 ++++++++++++++ .../client/deployment/rest/ParameterCheck.java | 211 ++++++++++++++++++++ .../apex/client/deployment/rest/package-info.java | 27 +++ .../src/main/resources/webapp/WEB-INF/web.xml | 46 +++++ .../src/main/resources/webapp/index.html | 87 +++++++++ .../src/main/resources/webapp/js/ApexAjax.js | 84 ++++++++ .../main/resources/webapp/js/ApexEngineService.js | 101 ++++++++++ .../main/resources/webapp/js/ApexModelLoading.js | 63 ++++++ .../main/resources/webapp/js/ApexServicesMain.js | 147 ++++++++++++++ .../src/main/resources/webapp/js/ApexTable.js | 59 ++++++ .../src/main/resources/webapp/js/ApexUtils.js | 212 +++++++++++++++++++++ .../resources/16px/rowCollapsed_black_16px.svg | 19 ++ .../resources/16px/rowExpanded_black_16px.svg | 18 ++ .../webapp/resources/16px/settings_black_16px.svg | 20 ++ .../webapp/resources/systemBar/help_black.svg | 19 ++ .../webapp/resources/systemBar/logout_black.svg | 15 ++ 22 files changed, 2021 insertions(+) create mode 100644 client/client-deployment/pom.xml create mode 100644 client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRest.java create mode 100644 client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestMain.java create mode 100644 client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameterException.java create mode 100644 client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameterParser.java create mode 100644 client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameters.java create mode 100644 client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestResource.java create mode 100644 client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ParameterCheck.java create mode 100644 client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/package-info.java create mode 100644 client/client-deployment/src/main/resources/webapp/WEB-INF/web.xml create mode 100644 client/client-deployment/src/main/resources/webapp/index.html create mode 100644 client/client-deployment/src/main/resources/webapp/js/ApexAjax.js create mode 100644 client/client-deployment/src/main/resources/webapp/js/ApexEngineService.js create mode 100644 client/client-deployment/src/main/resources/webapp/js/ApexModelLoading.js create mode 100644 client/client-deployment/src/main/resources/webapp/js/ApexServicesMain.js create mode 100644 client/client-deployment/src/main/resources/webapp/js/ApexTable.js create mode 100644 client/client-deployment/src/main/resources/webapp/js/ApexUtils.js create mode 100644 client/client-deployment/src/main/resources/webapp/resources/16px/rowCollapsed_black_16px.svg create mode 100644 client/client-deployment/src/main/resources/webapp/resources/16px/rowExpanded_black_16px.svg create mode 100644 client/client-deployment/src/main/resources/webapp/resources/16px/settings_black_16px.svg create mode 100644 client/client-deployment/src/main/resources/webapp/resources/systemBar/help_black.svg create mode 100644 client/client-deployment/src/main/resources/webapp/resources/systemBar/logout_black.svg (limited to 'client/client-deployment') diff --git a/client/client-deployment/pom.xml b/client/client-deployment/pom.xml new file mode 100644 index 000000000..f4ecfe7af --- /dev/null +++ b/client/client-deployment/pom.xml @@ -0,0 +1,191 @@ + + + 4.0.0 + + org.onap.policy.apex-pdp.client + client + 2.0.0-SNAPSHOT + + + client-deployment + ${project.artifactId} + Web client for deploying models in Apex engine + + + + org.onap.policy.apex-pdp.core + core-deployment + ${project.version} + + + org.onap.policy.apex-pdp.client + client-common + ${project.version} + resources + zip + provided + + + org.glassfish.jersey.containers + jersey-container-grizzly2-http + ${version.jersey} + + + org.glassfish.jersey.media + jersey-media-multipart + ${version.jersey} + + + org.glassfish.jersey.containers + jersey-container-servlet-core + ${version.jersey} + + + org.glassfish.jersey.inject + jersey-hk2 + ${version.jersey} + + + commons-cli + commons-cli + ${version.commons-cli} + + + + + install + ${project.build.directory}/classes + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack-client-deployment-shared-resources + + unpack-dependencies + + generate-resources + + ${project.build.directory}/${project.artifactId}-${project.version} + client-common + ${project.groupId} + true + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + ${project.artifactId}-uber-${project.version} + true + deployment + + + *:* + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + reference.conf + + + log4j.properties + + + org.onap.policy.apex.client.deployment.rest.ApexDeploymentRestMain + + + + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + ui + src/main/resources/webapp + src/main/resources/webapp/WEB-INF/web.xml + + + + prepare-package + + war + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.0.0 + + + attach-artifacts + package + + attach-artifact + + + + + ${project.build.directory}/${project.artifactId}-${project.version}-ui.war + war + + + ${project.build.directory}/${project.artifactId}-uber-${project.version}.jar + uber.jar + + + + + + + + + \ No newline at end of file diff --git a/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRest.java b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRest.java new file mode 100644 index 000000000..b6ed37d80 --- /dev/null +++ b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRest.java @@ -0,0 +1,84 @@ +/*- + * ============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.deployment.rest; + +import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; +import org.glassfish.jersey.media.multipart.MultiPartFeature; +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 ApexDeploymentRest { + // Logger for this class + private static final XLogger logger = XLoggerFactory.getXLogger(ApexDeploymentRest.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 ApexDeploymentRest() { + this(new ApexDeploymentRestParameters()); + } + + /** + * Starts the HTTP server for the Apex services client + * + * @param parameters: The Apex parameters to use to start the server + */ + public ApexDeploymentRest(final ApexDeploymentRestParameters 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.client.deployment.rest package + final ResourceConfig rc = new ResourceConfig().packages(parameters.getRESTPackages()); + + // Add MultiPartFeature class for jersey-media-multipart + rc.register(MultiPartFeature.class); + + // 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( + ApexDeploymentRestMain.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-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestMain.java b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestMain.java new file mode 100644 index 000000000..6e7220487 --- /dev/null +++ b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestMain.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.deployment.rest; + +import java.io.PrintStream; + +/** + * User: ewatkmi Date: 31 Jul 2017 + */ +public class ApexDeploymentRestMain { + // Services state + public enum ServicesState { + STOPPED, READY, INITIALIZING, RUNNING + }; + + private ServicesState state = ServicesState.STOPPED; + + // The parameters for the client + private ApexDeploymentRestParameters parameters = null; + + // Output and error streams for messages + private final PrintStream outStream; + + // The Apex services client this class is running + private ApexDeploymentRest apexDeploymentRest = 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 ApexDeploymentRestMain restMain = new ApexDeploymentRestMain(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 ApexDeploymentRestMain(final String[] args, final PrintStream outStream) { + // Save the streams for output and error + this.outStream = outStream; + + // Client parameter parsing + final ApexDeploymentRestParameterParser parser = new ApexDeploymentRestParameterParser(); + + try { + // Get and check the parameters + parameters = parser.parse(args); + } catch (final ApexDeploymentRestParameterException e) { + throw new ApexDeploymentRestParameterException( + "Apex Services REST endpoint (" + this.toString() + ") parameter error, " + e.getMessage() + '\n' + + parser.getHelp(ApexDeploymentRestMain.class.getCanonicalName())); + } + + if (parameters.isHelpSet()) { + throw new ApexDeploymentRestParameterException( + parser.getHelp(ApexDeploymentRestMain.class.getCanonicalName())); + } + + // Validate the parameters + final String validationMessage = parameters.validate(); + if (validationMessage.length() > 0) { + throw new ApexDeploymentRestParameterException( + "Apex Services REST endpoint (" + this.toString() + ") parameters invalid, " + validationMessage + + '\n' + parser.getHelp(ApexDeploymentRestMain.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 + apexDeploymentRest = new ApexDeploymentRest(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() == ApexDeploymentRestParameters.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 == ApexDeploymentRestParameters.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 (apexDeploymentRest != null) { + apexDeploymentRest.shutdown(); + apexDeploymentRest = 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 (apexDeploymentRest != null) { + outStream.println("Apex Services REST endpoint (" + this.toString() + ") shutting down"); + apexDeploymentRest.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 (apexDeploymentRest != null) { + apexDeploymentRest.shutdown(); + } + } + } + +} diff --git a/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameterException.java b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameterException.java new file mode 100644 index 000000000..87785b7f3 --- /dev/null +++ b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameterException.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.deployment.rest; + +/** + * A run time exception used to report parsing and parameter input errors. + * + * User: ewatkmi Date: 31 Jul 2017 + */ +public class ApexDeploymentRestParameterException extends IllegalArgumentException { + private static final long serialVersionUID = 6520231162404452427L; + + /** + * Create an ApexServicesRestParameterException with a message + * + * @param message the message + */ + public ApexDeploymentRestParameterException(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 ApexDeploymentRestParameterException(final String message, final Throwable throwable) { + super(message, throwable); + } +} diff --git a/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameterParser.java b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameterParser.java new file mode 100644 index 000000000..35ad9cdde --- /dev/null +++ b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameterParser.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.deployment.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 ApexDeploymentRestParameterParser { + // Apache Commons CLI options + Options options; + + /** + * Construct the options for the CLI RESTful services + */ + public ApexDeploymentRestParameterParser() { + 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 the parsed arguments + */ + public ApexDeploymentRestParameters parse(final String[] args) { + CommandLine commandLine = null; + try { + commandLine = new DefaultParser().parse(options, args); + } catch (final ParseException e) { + throw new ApexDeploymentRestParameterException( + "invalid command line arguments specified : " + e.getMessage()); + } + + final ApexDeploymentRestParameters parameters = new ApexDeploymentRestParameters(); + final String[] remainingArgs = commandLine.getArgs(); + + if (commandLine.getArgs().length > 0) { + throw new ApexDeploymentRestParameterException( + "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 ApexDeploymentRestParameterException("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 ApexDeploymentRestParameterException("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-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameters.java b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameters.java new file mode 100644 index 000000000..6151506b8 --- /dev/null +++ b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestParameters.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.deployment.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 ApexDeploymentRestParameters { + 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[] { "com.ericsson.apex.services.client.deployment.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-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestResource.java b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestResource.java new file mode 100644 index 000000000..810b59cc1 --- /dev/null +++ b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ApexDeploymentRestResource.java @@ -0,0 +1,146 @@ +/*- + * ============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.deployment.rest; + +import com.google.gson.JsonObject; + +import java.io.InputStream; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +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.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.FormDataParam; +import org.onap.policy.apex.core.deployment.ApexDeploymentException; +import org.onap.policy.apex.core.deployment.EngineServiceFacade; +import org.slf4j.ext.XLogger; +import org.slf4j.ext.XLoggerFactory; + +/** + * The class represents the root resource exposed at the base URL
+ * The url to access this resource would be in the form {@code /rest/....}
+ * For example: a GET request to the following URL + * {@code http://localhost:18989/apexservices/rest/?hostName=localhost&port=12345} + * + * Note: 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("deployment/") +@Produces({ MediaType.APPLICATION_JSON }) +@Consumes({ MediaType.APPLICATION_JSON }) + +public class ApexDeploymentRestResource { + // Get a reference to the logger + private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexDeploymentRestResource.class); + + /** + * Constructor, a new resource director is created for each request. + */ + public ApexDeploymentRestResource() {} + + /** + * 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 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 + "
", 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)); + + return Response.ok(responseObject.toString(), MediaType.APPLICATION_JSON).build(); + } + + /** + * Upload a model. + * + * @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 uploadedInputStream input stream + * @param fileDetail details on the file + * @param ignoreConflicts conflict policy + * @param forceUpdate update policy + * @return a response object in plain text confirming the upload was successful + */ + @POST + @Path("modelupload/") + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response modelUpload(@FormDataParam("hostName") final String hostName, @FormDataParam("port") final int port, + @FormDataParam("file") final InputStream uploadedInputStream, + @FormDataParam("file") final FormDataContentDisposition fileDetail, + @FormDataParam("ignoreConflicts") final boolean ignoreConflicts, + @FormDataParam("forceUpdate") final boolean forceUpdate) { + 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 + "
", e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage + "\n" + e.getMessage()) + .build(); + } + + try { + engineServiceFacade.deployModel(fileDetail.getFileName(), uploadedInputStream, ignoreConflicts, + forceUpdate); + } catch (final Exception e) { + LOGGER.warn("Error updating model on engine service " + engineServiceFacade.getKey().getID(), e); + final String errorMessage = + "Error updating model on engine service " + engineServiceFacade.getKey().getID(); + LOGGER.warn(errorMessage + "
", e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage + "\n" + e.getMessage()) + .build(); + } + + return Response.ok("Model " + fileDetail.getFileName() + " deployed on engine service " + + engineServiceFacade.getKey().getID()).build(); + } + +} diff --git a/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ParameterCheck.java b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/ParameterCheck.java new file mode 100644 index 000000000..87e76cdf7 --- /dev/null +++ b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/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.deployment.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 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 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 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 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 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-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/package-info.java b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/rest/package-info.java new file mode 100644 index 000000000..997e411a6 --- /dev/null +++ b/client/client-deployment/src/main/java/org/onap/policy/apex/client/deployment/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 deployment for Apex. + * + * @author Liam Fallon (liam.fallon@ericsson.com) + */ + +package org.onap.policy.apex.client.deployment.rest; diff --git a/client/client-deployment/src/main/resources/webapp/WEB-INF/web.xml b/client/client-deployment/src/main/resources/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..b79cf362a --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/WEB-INF/web.xml @@ -0,0 +1,46 @@ + + + + + + + apex-services.rest + org.glassfish.jersey.servlet.ServletContainer + + jersey.config.server.provider.packages + org.onap.policy.apex.client.deployment.rest + + + jersey.config.server.provider.classnames + org.glassfish.jersey.media.multipart.MultiPartFeature + + 1 + + + apex-services.rest + /apexservices/* + + + \ No newline at end of file diff --git a/client/client-deployment/src/main/resources/webapp/index.html b/client/client-deployment/src/main/resources/webapp/index.html new file mode 100644 index 000000000..2ae25f901 --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/index.html @@ -0,0 +1,87 @@ + + + + + + +Apex Deployment + + + + + + + + + + + + + + +
+
Apex
+
+
+ +
+ +
+
+ Apex +
+ +
+ +
+

Apex Deployment

+
+ + + + +
+ + +

Engine Service

+
+ + +

Apex Model Loading

+
+ +
+
+ + + + + + + + + + + + + diff --git a/client/client-deployment/src/main/resources/webapp/js/ApexAjax.js b/client/client-deployment/src/main/resources/webapp/js/ApexAjax.js new file mode 100644 index 000000000..beb2cb11d --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/js/ApexAjax.js @@ -0,0 +1,84 @@ +/* + * ============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========================================================= + */ + +/* + * Send a GET request + */ +function ajax_get(requestURL, callback, hostName, port, params, errorCallback) { + var data = { + hostName : hostName, + port : port + }; + for ( var p in params) { + data[p] = params[p]; + } + return $.ajax({ + type : 'GET', + url : requestURL, + dataType : "json", + data : data, + success : function(data, textStatus, jqXHR) { + if (callback) { + callback(data); + } + }, + error : function(jqXHR, textStatus, errorThrown) { + if (jqXHR.status == 500 || jqXHR.status == 404) { + if (jqXHR.responseText.indexOf("cound not handshake with server") !== -1 || jqXHR.status == 404) { + clearEngineURL(); + getEngineURL(jqXHR.responseText); + } else { + apexErrorDialog_activate(document.body, jqXHR.responseText); + } + } + if (errorCallback) { + errorCallback(jqXHR, textStatus, errorThrown); + } + } + }); +} + +/* + * Send a POST request and add a file to its payload + */ +function ajax_upload(requestURL, callback, hostName, port, fileUrl, ignoreConflicts, forceUpdate) { + var formData = new FormData(); + formData.append("hostName", hostName); + formData.append("port", port); + formData.append("file", fileUrl); + formData.append("ignoreConflicts", ignoreConflicts); + formData.append("forceUpdate", forceUpdate); + return $.ajax({ + url : requestURL, + type : "POST", + contentType : false, + dataType : "text", + processData : false, + data : formData, + success : function(data, textStatus, jqXHR) { + callback(data); + }, + error : function(jqXHR, textStatus, errorThrown) { + if (jqXHR.status == 500) { + apexErrorDialog_activate(document.body, jqXHR.responseText); + } + } + }); +} diff --git a/client/client-deployment/src/main/resources/webapp/js/ApexEngineService.js b/client/client-deployment/src/main/resources/webapp/js/ApexEngineService.js new file mode 100644 index 000000000..f47c98f07 --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/js/ApexEngineService.js @@ -0,0 +1,101 @@ +/* + * ============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========================================================= + */ + +/* + * Create the Engine Service Table + */ +function createEngineServiceTable() { + var tableId = config.engineService.tableId; + var headers = config.engineService.headers; + var table = createEngineTable($("." + config.engineService.parent), tableId, headers.map(function(a) { + return a.title; + })); + var tableRow = document.createElement("tr"); + var tableData = ""; + for ( var h in headers) { + tableData += ""; + } + tableRow.innerHTML = tableData; + var actionTD = $(tableRow).find("#" + tableId + "_periodic_events"); + actionTD + .html(''); + var period = actionTD.find("#period"); + var switcher = actionTD.find(".ebSwitcher"); + switcher.css('display', 'inline-block'); + switcher.css('margin-left', '5px'); + switcher.css('vertical-align', 'middle'); + var checkbox = $(actionTD).find('input:checkbox:first'); + checkbox.change(function(event) { + var startstop; + if (checkbox.prop('checked')) { + startstop = "Stop"; + } else { + startstop = "Start"; + } + this.servicesCall.abort(); + ajax_get(restRootURL + "periodiceventstartstop", startStopCallback, this.engineURL.hostname, + this.engineURL.port, { + engineId : this.engineId, + startstop : startstop, + period : period.val() + }, resetPeriodicEvents); + }.bind(this)); + $(table).children("#engineTableBody").append(tableRow); +} + +/* + * Check for any changes in the Engine Service Table data and update only where + * necessary + */ +function setEngineServiceData(engineId, modelId, server, port, periodicEvents) { + this.engineId = engineId; + var tableId = config.engineService.tableId; + var headers = config.engineService.headers.map(function(a) { + return a.id; + }); + var data = [ engineId, server + ":" + port, modelId ]; + + var engineServiceTable = $("#engineServicesTable"); + + for ( var h in headers) { + var td = engineServiceTable.find("#" + tableId + "_" + headers[h]); + if (td.html() !== data[h]) { + engineServiceTable.find("#" + tableId + "_" + headers[h]).html(data[h]); + } + } + + var actionTD = engineServiceTable.find("#" + tableId + "_periodic_events"); + var checkbox = $(actionTD).find('input:checkbox:first'); + if (checkbox.is(":checked") === periodicEvents) { + checkbox.prop("checked", !checkbox.prop("checked")); + } +} + +/* + * Resets the switcher for Periodic Events in the Engine Service Table + */ +function resetPeriodicEvents() { + var engineServiceTable = $("#engineServicesTable"); + var periodicEventsTD = $(engineServiceTable).find("#engineServicesTable_periodic_events"); + var checkbox = $(periodicEventsTD).find('input:checkbox:first'); + if (checkbox.is(":checked")) { + checkbox.prop("checked", false); + } +} diff --git a/client/client-deployment/src/main/resources/webapp/js/ApexModelLoading.js b/client/client-deployment/src/main/resources/webapp/js/ApexModelLoading.js new file mode 100644 index 000000000..8bd051f0f --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/js/ApexModelLoading.js @@ -0,0 +1,63 @@ +/* + * ============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========================================================= + */ + +/* + * Create the div for uploading Apex models + */ +function createModelLoadingDiv() { + var fileLoader = document.createElement("input"); + fileLoader.setAttribute("type", "file"); + fileLoader.setAttribute("name", "apexModelFile"); + fileLoader.setAttribute("label", "Load Apex Model XML file"); + $('.modelLoading').append(fileLoader); + + var ignoreConflictsCheckbox = document.createElement("input"); + ignoreConflictsCheckbox.setAttribute("type", "checkbox"); + ignoreConflictsCheckbox.setAttribute("name", "ignoreContextConflicts"); + $('.modelLoading').append(ignoreConflictsCheckbox); + + ignoreConflictsLabel = document.createElement("label"); + ignoreConflictsLabel.setAttribute("class", "ignoreConflictsLabel"); + ignoreConflictsLabel.innerHTML = "Ignore Context Conflicts"; + $('.modelLoading').append(ignoreConflictsLabel); + + var forceUpdateCheckbox = document.createElement("input"); + forceUpdateCheckbox.setAttribute("type", "checkbox"); + forceUpdateCheckbox.setAttribute("name", "forceUpdate"); + $('.modelLoading').append(forceUpdateCheckbox); + + forceUpdateLabel = document.createElement("label"); + forceUpdateLabel.setAttribute("class", "ignoreConflictsLabel"); + forceUpdateLabel.innerHTML = "Force Update"; + $('.modelLoading').append(forceUpdateLabel); + + var submitButton = document.createElement("button"); + submitButton.setAttribute("class", "ebBtn"); + submitButton.innerHTML = "Load Apex Model XML file"; + $(submitButton).click( + function() { + var file = fileLoader.files[0]; + var ignoreConflicts = $(ignoreConflictsCheckbox).is(":checked"); + var forceUpdate = $(forceUpdateCheckbox).is(":checked"); + ajax_upload(restRootURL + "modelupload/", uploadCallback, this.engineURL.hostname, this.engineURL.port, + file, ignoreConflicts, forceUpdate); + }.bind(this)); + $('.modelLoading').append(submitButton); +} \ No newline at end of file diff --git a/client/client-deployment/src/main/resources/webapp/js/ApexServicesMain.js b/client/client-deployment/src/main/resources/webapp/js/ApexServicesMain.js new file mode 100644 index 000000000..a54815ab3 --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/js/ApexServicesMain.js @@ -0,0 +1,147 @@ +/* + * ============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========================================================= + */ + +var restRootURL; + +var config = { + refresh : 5000, + engineService : { + parent : "engineService", + tableId : "engineServicesTable", + headers : [ { + title : "Engine Service ID", + id : "engine_id" + }, { + title : "server:port", + id : "server_port" + }, { + title : "Model ID", + id : "model_id" + } ] + } +} + +/* + * Callback for showing model info + */ +function servicesCallback(data) { + // If engine url in cookie has not been cleared + if (localStorage.getItem("apex-monitor-services")) { + setEngineServiceData(data.engine_id, data.model_id, data.server, data.port, data.periodic_events); + + // Make content visible after data has been returned for the first time + if (!$(".content").is(':visible')) { + $(".content").fadeIn(); + } + + // Repeat the same request + setTimeout(function() { + this.servicesCall = ajax_get(restRootURL, servicesCallback, this.engineURL.hostname, this.engineURL.port); + }, config.refresh); + } +} + +/* + * Callback for uploading a model + */ +function uploadCallback(response) { + // Open a dialog showing the response + apexSuccessDialog_activate(document.body, response); +} + +/* + * Clears and resets all content on the page + */ +function setUpPage() { + // Clear each div + $('#content > div').each(function() { + $(this).empty(); + }); + + // Set up content div's + createEngineServiceTable(); + createModelLoadingDiv(); +} + +/* + * Retrieves the engine URL from the cookie. If it has not been set yet, then a + * dialog is shown asking for it + */ +function getEngineURL(message) { + // The engine URL is stored in a cookie using the key + // "apex-monitor-services" + var engineURL = localStorage.getItem("apex-monitor-services"); + + // This url is used to store the last known engine URL so that the user + // doesn't have to retype it every time + var oldEngineURL = localStorage.getItem("apex-monitor-services_old"); + + // If an engine URL is stored in the cookie + if (engineURL) { + // Parse the engine URL + this.engineURL = JSON.parse(engineURL); + + // Send a request with that engine URL + this.servicesCall = ajax_get(restRootURL, servicesCallback, this.engineURL.hostname, this.engineURL.port); + } else { + // Prompt for engine URL + apexDialogForm_activate(document.body, message); + } +} + +/* + * Clears the cookie and reset the page + */ +function clearEngineURL() { + // Remove engine URL from cookie + localStorage.removeItem("apex-monitor-services"); + + // Reset the page + setUpPage(); +} + +/* + * Called after the DOM is ready + */ +$(document).ready( + function() { + restRootURL = location.protocol + + "//" + + window.location.hostname + + (location.port ? ':' + location.port : '') + + (location.pathname.endsWith("/deployment/") ? location.pathname.substring(0, location.pathname + .indexOf("deployment/")) : location.pathname) + "apexservices/deployment/"; + + // Set up the structure of the page + setUpPage(); + + // Check cookies for engine URL + getEngineURL(); + + // Add click event to config icon for clearing engine URL + $(".ebSystemBar-config").click(function() { + // Clear the engine URL + clearEngineURL(); + + // Request the engine URL + getEngineURL(); + }); + + }); \ No newline at end of file diff --git a/client/client-deployment/src/main/resources/webapp/js/ApexTable.js b/client/client-deployment/src/main/resources/webapp/js/ApexTable.js new file mode 100644 index 000000000..20e3d08bd --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/js/ApexTable.js @@ -0,0 +1,59 @@ +/* + * ============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========================================================= + */ + +/* + * Create a table with given headers + */ +function createEngineTable(parent, id, tableHeaders) { + var table = createTable(id); + + var tableHead = document.createElement("thead"); + table.appendChild(tableHead); + tableHead.setAttribute("id", "engineTableHeader"); + + var tableHeaderRow = document.createElement("tr"); + tableHead.appendChild(tableHeaderRow); + tableHeaderRow.setAttribute("id", "engineTableHeaderRow"); + + for ( var t in tableHeaders) { + var tableHeader = document.createElement("th"); + tableHeaderRow.appendChild(tableHeader); + tableHeader.setAttribute("id", "engineTableHeader"); + tableHeader.appendChild(document.createTextNode(tableHeaders[t])); + } + + var tableBody = document.createElement("tbody"); + tableBody.setAttribute("id", "engineTableBody"); + table.appendChild(tableBody); + + parent.append(table); + + return table; +} + +/* + * Create a table and apply UISDK styles to it + */ +function createTable(id) { + var table = document.createElement("table"); + table.setAttribute("id", id); + table.setAttribute("class", "apexTable ebTable elTablelib-Table-table ebTable_striped"); + return table; +} \ No newline at end of file diff --git a/client/client-deployment/src/main/resources/webapp/js/ApexUtils.js b/client/client-deployment/src/main/resources/webapp/js/ApexUtils.js new file mode 100644 index 000000000..0f5e689fd --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/js/ApexUtils.js @@ -0,0 +1,212 @@ +/* + * ============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========================================================= + */ + +/* + * Crate a dialog with input, attach it to a given parent and show an optional message + */ +function apexDialogForm_activate(formParent, message) { + apexUtils_removeElement("apexDialogDiv"); + + var contentelement = document.createElement("apexDialogDiv"); + var formDiv = document.createElement("div"); + var backgroundDiv = document.createElement("div"); + backgroundDiv.setAttribute("id", "apexDialogDivBackground"); + backgroundDiv.setAttribute("class", "apexDialogDivBackground"); + + backgroundDiv.appendChild(formDiv); + contentelement.appendChild(backgroundDiv); + formParent.appendChild(contentelement); + + formDiv.setAttribute("id", "apexDialogDiv"); + formDiv.setAttribute("class", "apexDialogDiv"); + + var headingSpan = document.createElement("span"); + formDiv.appendChild(headingSpan); + + headingSpan.setAttribute("class", "headingSpan"); + headingSpan.innerHTML = "Apex Engine Configuration"; + + var form = document.createElement("apexDialog"); + formDiv.appendChild(form); + + form.setAttribute("id", "apexDialog"); + form.setAttribute("class", "form-style-1"); + form.setAttribute("method", "post"); + + if (message) { + var messageLI = document.createElement("li"); + messageLI.setAttribute("class", "dialogMessage"); + messageLI.innerHTML = message; + form.appendChild(messageLI); + } + + var urlLI = document.createElement("li"); + form.appendChild(urlLI); + + var urlLabel = document.createElement("label"); + urlLI.appendChild(urlLabel); + + urlLabel.setAttribute("for", "apexDialogUrlInput"); + urlLabel.innerHTML = "Apex Engine rest URL:"; + + var urlLabelSpan = document.createElement("span"); + urlLabel.appendChild(urlLabelSpan); + + urlLabelSpan.setAttribute("class", "required"); + urlLabelSpan.innerHTML = "*"; + + var engineUrl = localStorage.getItem("apex-monitor-services_old"); + + var urlInput = document.createElement("input"); + urlInput.setAttribute("id", "services_url_input"); + urlInput.setAttribute("placeholder", "localhost:12345"); + urlInput.value = (engineUrl && engineUrl !== "null") ? JSON.parse(engineUrl).hostname + ":" + + JSON.parse(engineUrl).port : ""; + urlLI.appendChild(urlInput); + + var inputLI = document.createElement("li"); + form.appendChild(inputLI); + + var submitInput = document.createElement("input"); + submitInput.setAttribute("id", "submit"); + submitInput.setAttribute("class", "button ebBtn"); + submitInput.setAttribute("type", "submit"); + submitInput.setAttribute("value", "Submit"); + submitInput.onclick = apexDialogForm_submitPressed; + inputLI.appendChild(submitInput); + + // Enter key press triggers submit + $(urlInput).keyup(function(event) { + if (event.keyCode == 13) { + $(submitInput).click(); + } + }); + + urlInput.focus(); +} + +/* + * Create a dialog for displaying text + */ +function apexTextDialog_activate(formParent, message, title) { + apexUtils_removeElement("apexDialogDiv"); + + var contentelement = document.createElement("div"); + contentelement.setAttribute("id", "apexDialogDiv") + var formDiv = document.createElement("div"); + var backgroundDiv = document.createElement("div"); + backgroundDiv.setAttribute("id", "apexDialogDivBackground"); + backgroundDiv.setAttribute("class", "apexDialogDivBackground"); + + backgroundDiv.appendChild(formDiv); + contentelement.appendChild(backgroundDiv); + formParent.appendChild(contentelement); + + formDiv.setAttribute("id", "apexErrorDialogDiv"); + formDiv.setAttribute("class", "apexDialogDiv apexErrorDialogDiv"); + + var headingSpan = document.createElement("span"); + formDiv.appendChild(headingSpan); + + headingSpan.setAttribute("class", "headingSpan"); + headingSpan.innerHTML = title; + + var form = document.createElement("div"); + formDiv.appendChild(form); + + form.setAttribute("id", "apexDialog"); + form.setAttribute("class", "form-style-1"); + form.setAttribute("method", "post"); + + if (message) { + var messageLI = document.createElement("li"); + messageLI.setAttribute("class", "dialogMessage"); + messageLI.innerHTML = message; + form.appendChild(messageLI); + } + + var inputLI = document.createElement("li"); + form.appendChild(inputLI); + + var cancelInput = document.createElement("input"); + cancelInput.setAttribute("class", "button ebBtn"); + cancelInput.setAttribute("type", "submit"); + cancelInput.setAttribute("value", "Close"); + cancelInput.onclick = newModelForm_cancelPressed; + form.appendChild(cancelInput); +} + +/* + * Create a Success dialog + */ +function apexSuccessDialog_activate(formParent, message) { + apexTextDialog_activate(formParent, message, "Success"); +} + +/* + * Create an Error dialog + */ +function apexErrorDialog_activate(formParent, message) { + apexTextDialog_activate(formParent, message, "Error"); +} + +/* + * Dialog cancel callback + */ +function newModelForm_cancelPressed() { + apexUtils_removeElement("apexDialogDivBackground"); +} + +/* + * Dialog submit callback + */ +function apexDialogForm_submitPressed() { + var url = $('#services_url_input').val(); + if (url && url.length > 0) { + var engineConfig = { + hostname : url.split(":")[0], + port : url.split(":")[1] + }; + localStorage.setItem("apex-monitor-services_old", JSON.stringify(engineConfig)); + localStorage.setItem("apex-monitor-services", JSON.stringify(engineConfig)); + apexUtils_removeElement("apexDialogDivBackground"); + getEngineURL(); + } +} + +/* + * Remove an element from the page + */ +function apexUtils_removeElement(elementname) { + var element = document.getElementById(elementname); + if (element != null) { + element.parentNode.removeChild(element); + } +} + +function getHomepageURL() { + var homepageURL = location.protocol + + "//" + + window.location.hostname + + (location.port ? ':' + location.port : '') + + (location.pathname.endsWith("/deployment/") ? location.pathname.substring(0, location.pathname + .indexOf("deployment/")) : location.pathname); + location.href = homepageURL; +} \ No newline at end of file diff --git a/client/client-deployment/src/main/resources/webapp/resources/16px/rowCollapsed_black_16px.svg b/client/client-deployment/src/main/resources/webapp/resources/16px/rowCollapsed_black_16px.svg new file mode 100644 index 000000000..6878c863c --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/resources/16px/rowCollapsed_black_16px.svg @@ -0,0 +1,19 @@ + + + +]> + + + + + + + + + + diff --git a/client/client-deployment/src/main/resources/webapp/resources/16px/rowExpanded_black_16px.svg b/client/client-deployment/src/main/resources/webapp/resources/16px/rowExpanded_black_16px.svg new file mode 100644 index 000000000..5e3e46a66 --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/resources/16px/rowExpanded_black_16px.svg @@ -0,0 +1,18 @@ + + + +]> + + + + + + + + + diff --git a/client/client-deployment/src/main/resources/webapp/resources/16px/settings_black_16px.svg b/client/client-deployment/src/main/resources/webapp/resources/16px/settings_black_16px.svg new file mode 100644 index 000000000..c347888e9 --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/resources/16px/settings_black_16px.svg @@ -0,0 +1,20 @@ + + + +]> + + + + + + + diff --git a/client/client-deployment/src/main/resources/webapp/resources/systemBar/help_black.svg b/client/client-deployment/src/main/resources/webapp/resources/systemBar/help_black.svg new file mode 100644 index 000000000..14fdf5d35 --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/resources/systemBar/help_black.svg @@ -0,0 +1,19 @@ + + + + + + diff --git a/client/client-deployment/src/main/resources/webapp/resources/systemBar/logout_black.svg b/client/client-deployment/src/main/resources/webapp/resources/systemBar/logout_black.svg new file mode 100644 index 000000000..af297acde --- /dev/null +++ b/client/client-deployment/src/main/resources/webapp/resources/systemBar/logout_black.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + -- cgit 1.2.3-korg