From 900920306a0be309f389880325558bb96ff76356 Mon Sep 17 00:00:00 2001 From: liamfallon Date: Wed, 17 Apr 2019 13:58:26 +0000 Subject: [PATCH] Add DMaaP simulator for CSIT testing A rudimentary DMaaP simulator that simply holds requests and responds to all readers with whatever message comes in on a topic. The simulator is placed in policy models for now but should be submitted to DMaaP. The simulator is now working but is still extremely rough. Issue-ID: POLICY-1643 Change-Id: I28645a73cf198fe825c897243b30cd34dc29f20d Signed-off-by: liamfallon --- models-sim/models-sim-dmaap/pom.xml | 81 +++++++ .../policy/models/sim/dmaap/DmaapSimConstants.java | 32 +++ .../policy/models/sim/dmaap/DmaapSimException.java | 56 +++++ .../models/sim/dmaap/DmaapSimRuntimeException.java | 56 +++++ .../dmaap/parameters/DmaapSimParameterGroup.java | 46 ++++ .../dmaap/parameters/DmaapSimParameterHandler.java | 85 ++++++++ .../sim/dmaap/parameters/RestServerParameters.java | 44 ++++ .../sim/dmaap/provider/DmaapSimProvider.java | 186 ++++++++++++++++ .../sim/dmaap/rest/BaseRestControllerV1.java | 116 ++++++++++ .../sim/dmaap/rest/CambriaMessageBodyHandler.java | 66 ++++++ .../sim/dmaap/rest/DmaapSimRestControllerV1.java | 116 ++++++++++ .../models/sim/dmaap/rest/DmaapSimRestServer.java | 138 ++++++++++++ .../sim/dmaap/rest/JsonMessageBodyHandler.java | 63 ++++++ .../sim/dmaap/startstop/DmaapSimActivator.java | 60 +++++ .../startstop/DmaapSimCommandLineArguments.java | 242 +++++++++++++++++++++ .../policy/models/sim/dmaap/startstop/Main.java | 146 +++++++++++++ .../src/main/resources/version.txt | 4 + .../src/test/resources/logback-test.xml | 54 +++++ .../test/resources/parameters/EmptyParameters.json | 1 + .../resources/parameters/InvalidParameters.json | 3 + .../resources/parameters/MinimumParameters.json | 7 + .../test/resources/parameters/NoParameters.json | 2 + .../resources/parameters/NormalParameters.json | 7 + .../parameters/Parameters_InvalidName.json | 9 + models-sim/pom.xml | 36 +++ pom.xml | 1 + 26 files changed, 1657 insertions(+) create mode 100644 models-sim/models-sim-dmaap/pom.xml create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimConstants.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimException.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimRuntimeException.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/DmaapSimParameterGroup.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/DmaapSimParameterHandler.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/RestServerParameters.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/provider/DmaapSimProvider.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/BaseRestControllerV1.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/CambriaMessageBodyHandler.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/DmaapSimRestControllerV1.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/DmaapSimRestServer.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/JsonMessageBodyHandler.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/DmaapSimActivator.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/DmaapSimCommandLineArguments.java create mode 100644 models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/Main.java create mode 100644 models-sim/models-sim-dmaap/src/main/resources/version.txt create mode 100644 models-sim/models-sim-dmaap/src/test/resources/logback-test.xml create mode 100644 models-sim/models-sim-dmaap/src/test/resources/parameters/EmptyParameters.json create mode 100644 models-sim/models-sim-dmaap/src/test/resources/parameters/InvalidParameters.json create mode 100644 models-sim/models-sim-dmaap/src/test/resources/parameters/MinimumParameters.json create mode 100644 models-sim/models-sim-dmaap/src/test/resources/parameters/NoParameters.json create mode 100644 models-sim/models-sim-dmaap/src/test/resources/parameters/NormalParameters.json create mode 100644 models-sim/models-sim-dmaap/src/test/resources/parameters/Parameters_InvalidName.json create mode 100644 models-sim/pom.xml diff --git a/models-sim/models-sim-dmaap/pom.xml b/models-sim/models-sim-dmaap/pom.xml new file mode 100644 index 000000000..b21926b5c --- /dev/null +++ b/models-sim/models-sim-dmaap/pom.xml @@ -0,0 +1,81 @@ + + + + 4.0.0 + + org.onap.policy.models.sim + policy-models-sim + 2.0.0-SNAPSHOT + + + policy-models-sim-dmaap + + ${project.artifactId} + A module that implements a very simple DMaaP simulator. + + + + commons-cli + commons-cli + + + org.onap.policy.common + common-parameters + ${policy.common.version} + + + org.onap.policy.common + utils + ${policy.common.version} + + + org.onap.policy.common + policy-endpoints + ${policy.common.version} + + + org.onap.policy.common + gson + ${policy.common.version} + + + + + + + + src/main/resources + true + + **/version.txt + + + + src/main/resources + false + + **/version.txt + + + + + diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimConstants.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimConstants.java new file mode 100644 index 000000000..1682eb991 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimConstants.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.models.sim.dmaap; + +/** + * Names of various items contained in the Registry. + */ +public class DmaapSimConstants { + + // Registry keys + public static final String REG_DMAAP_SIM_ACTIVATOR = "object:activator/dmaap-sim"; + + private DmaapSimConstants() { + super(); + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimException.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimException.java new file mode 100644 index 000000000..aaf8980f8 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimException.java @@ -0,0 +1,56 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap; + +/** + * This exception will be called if an error occurs in the DMaaP simulator. + */ +public class DmaapSimException extends Exception { + private static final long serialVersionUID = -8507246953751956974L; + + /** + * Instantiates a new exception with a message. + * + * @param message the message + */ + public DmaapSimException(final String message) { + super(message); + } + + /** + * Instantiates a new exception with a caused by exception. + * + * @param exp the exception that caused this exception to be thrown + */ + public DmaapSimException(final Exception exp) { + super(exp); + } + + /** + * Instantiates a new exception with a message and a caused by exception. + * + * @param message the message + * @param exp the exception that caused this exception to be thrown + */ + public DmaapSimException(final String message, final Exception exp) { + super(message, exp); + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimRuntimeException.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimRuntimeException.java new file mode 100644 index 000000000..fe8b7e21b --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimRuntimeException.java @@ -0,0 +1,56 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap; + +/** + * This runtime exception will be called if a runtime error occurs when using the DMaaP simulator. + */ +public class DmaapSimRuntimeException extends RuntimeException { + private static final long serialVersionUID = -8507246953751956974L; + + /** + * Instantiates a new policy pap runtime exception with a message. + * + * @param message the message + */ + public DmaapSimRuntimeException(final String message) { + super(message); + } + + /** + * Instantiates a new runtime exception with a caused by exception. + * + * @param exp the exception that caused this exception to be thrown + */ + public DmaapSimRuntimeException(final Exception exp) { + super(exp); + } + + /** + * Instantiates a new runtime exception with a message and a caused by exception. + * + * @param message the message + * @param exp the exception that caused this exception to be thrown + */ + public DmaapSimRuntimeException(final String message, final Exception exp) { + super(message, exp); + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/DmaapSimParameterGroup.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/DmaapSimParameterGroup.java new file mode 100644 index 000000000..caae287b8 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/DmaapSimParameterGroup.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap.parameters; + +import lombok.Getter; + +import org.onap.policy.common.parameters.ParameterGroupImpl; +import org.onap.policy.common.parameters.annotations.NotBlank; +import org.onap.policy.common.parameters.annotations.NotNull; + +/** + * Class to hold all parameters needed for the DMaaP simulator component. + */ +@NotNull +@NotBlank +@Getter +public class DmaapSimParameterGroup extends ParameterGroupImpl { + private RestServerParameters restServerParameters; + + /** + * Create the DMaaP simulator parameter group. + * + * @param name the parameter group name + */ + public DmaapSimParameterGroup(final String name) { + super(name); + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/DmaapSimParameterHandler.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/DmaapSimParameterHandler.java new file mode 100644 index 000000000..8eb76ec00 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/DmaapSimParameterHandler.java @@ -0,0 +1,85 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap.parameters; + +import java.io.File; + +import org.onap.policy.common.parameters.GroupValidationResult; +import org.onap.policy.common.utils.coder.Coder; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.models.sim.dmaap.DmaapSimException; +import org.onap.policy.models.sim.dmaap.startstop.DmaapSimCommandLineArguments; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class handles reading, parsing and validating of DMaaP simulator parameters from JSON files. + */ +public class DmaapSimParameterHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(DmaapSimParameterHandler.class); + + private static final Coder CODER = new StandardCoder(); + + /** + * Read the parameters from the parameter file. + * + * @param arguments the arguments passed to DMaaP simulator + * @return the parameters read from the configuration file + * @throws DmaapSimException on parameter exceptions + */ + public DmaapSimParameterGroup getParameters(final DmaapSimCommandLineArguments arguments) throws DmaapSimException { + DmaapSimParameterGroup dmaapSimParameterGroup = null; + + // Read the parameters + try { + // Read the parameters from JSON + File file = new File(arguments.getFullConfigurationFilePath()); + dmaapSimParameterGroup = CODER.decode(file, DmaapSimParameterGroup.class); + } catch (final CoderException e) { + final String errorMessage = "error reading parameters from \"" + arguments.getConfigurationFilePath() + + "\"\n" + "(" + e.getClass().getSimpleName() + "):" + e.getMessage(); + LOGGER.error(errorMessage, e); + throw new DmaapSimException(errorMessage, e); + } + + // The JSON processing returns null if there is an empty file + if (dmaapSimParameterGroup == null) { + final String errorMessage = "no parameters found in \"" + arguments.getConfigurationFilePath() + "\""; + LOGGER.error(errorMessage); + throw new DmaapSimException(errorMessage); + } + + // validate the parameters + final GroupValidationResult validationResult = dmaapSimParameterGroup.validate(); + if (!validationResult.isValid()) { + String returnMessage = + "validation error(s) on parameters from \"" + arguments.getConfigurationFilePath() + "\"\n"; + returnMessage += validationResult.getResult(); + + LOGGER.error(returnMessage); + throw new DmaapSimException(returnMessage); + } + + return dmaapSimParameterGroup; + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/RestServerParameters.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/RestServerParameters.java new file mode 100644 index 000000000..c7269f66d --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/RestServerParameters.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap.parameters; + +import lombok.Getter; +import org.onap.policy.common.parameters.ParameterGroupImpl; +import org.onap.policy.common.parameters.annotations.Min; +import org.onap.policy.common.parameters.annotations.NotBlank; +import org.onap.policy.common.parameters.annotations.NotNull; + +/** + * Class to hold all parameters needed for DMaaP simulator rest server. + */ +@NotNull +@NotBlank +@Getter +public class RestServerParameters extends ParameterGroupImpl { + private String host; + + @Min(value = 1) + private int port; + + public RestServerParameters() { + super("RestServerParameters"); + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/provider/DmaapSimProvider.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/provider/DmaapSimProvider.java new file mode 100644 index 000000000..42a653d6f --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/provider/DmaapSimProvider.java @@ -0,0 +1,186 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap.provider; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import javax.ws.rs.core.Response; + +import org.apache.commons.lang3.tuple.MutablePair; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.models.sim.dmaap.DmaapSimRuntimeException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provider to simulate DMaaP. + * + * @author Liam Fallon (liam.fallon@est.tech) + */ +public class DmaapSimProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(DmaapSimProvider.class); + + // Time for a get to wait before checking of a message has come + private static final long DMAAP_SIM_WAIT_TIME = 50; + + // recurring constants + private static final String WITH_TIMEOUT = " with timeout "; + + // The map of topic messages + private static final Map> topicMessageMap = new LinkedHashMap<>(); + + // The map of topic messages + private static final Map>> consumerGroupsMap = + new LinkedHashMap<>(); + + /** + * Process a DMaaP message. + * + * @param topicName The topic name + * @param dmaapMessage the message to process + * @return a response to the message + */ + public Response processDmaapMessagePut(final String topicName, final Object dmaapMessage) { + LOGGER.debug("Topic:" + topicName + ", Received DMaaP message: " + dmaapMessage); + + synchronized (topicMessageMap) { + SortedMap messageMap = topicMessageMap.get(topicName); + if (messageMap == null) { + messageMap = new TreeMap<>(); + topicMessageMap.put(topicName, messageMap); + LOGGER.debug("Topic:" + topicName + ", created topic message map"); + } + + int nextKey = (messageMap.isEmpty() ? 0 : messageMap.lastKey() + 1); + + messageMap.put(nextKey, dmaapMessage); + LOGGER.debug("Topic:" + topicName + ", cached DMaaP message " + nextKey + ": " + dmaapMessage); + } + + return Response.status(Response.Status.OK).entity("{\n \"serverTimeMs\": 0,\n \"count\": 1\n}").build(); + } + + /** + * Wait for and return a DMaaP message. + * + * @param topicName The topic to wait on + * @param consumerGroup the consumer group that is waiting + * @param consumerId the consumer ID that is waiting + * @param timeout the length of time to wait for + * @return the DMaaP message or + */ + public Response processDmaapMessageGet(final String topicName, final String consumerGroup, final String consumerId, + final int timeout) { + + LOGGER.debug("Topic:" + topicName + ", Request for DMaaP message: " + consumerGroup + ":" + consumerId + + WITH_TIMEOUT + timeout); + + MutablePair consumerGroupPair = null; + + synchronized (consumerGroupsMap) { + Map> consumerGroupMap = consumerGroupsMap.get(topicName); + if (consumerGroupMap == null) { + consumerGroupMap = new LinkedHashMap<>(); + consumerGroupsMap.put(topicName, consumerGroupMap); + LOGGER.trace("Topic:" + topicName + ", Created consumer map entry for consumer group " + consumerGroup); + } + + consumerGroupPair = consumerGroupMap.get(consumerGroup); + if (consumerGroupPair == null) { + consumerGroupPair = new MutablePair<>(-1, consumerId); + consumerGroupMap.put(consumerGroup, consumerGroupPair); + LOGGER.trace("Topic:" + topicName + ", Created consumer group entry for consumer group " + consumerGroup + + ":" + consumerId); + } + } + + long timeOfTimeout = System.currentTimeMillis() + timeout; + + do { + + Object waitingMessages = getWaitingMessages(topicName, consumerGroupPair); + if (waitingMessages != null) { + LOGGER.debug("Topic:" + topicName + ", Request for DMaaP message: " + consumerGroup + ":" + consumerId + + WITH_TIMEOUT + timeout + ", returning messages " + waitingMessages); + return Response.status(Response.Status.OK).entity(waitingMessages).build(); + } + + try { + Thread.sleep(DMAAP_SIM_WAIT_TIME); + } catch (InterruptedException ie) { + String errorMessage = "Interrupt on wait on simulation of DMaaP topic " + topicName + " for request ID " + + consumerGroup + ":" + consumerId + WITH_TIMEOUT + timeout; + LOGGER.warn(errorMessage, ie); + throw new DmaapSimRuntimeException(errorMessage, ie); + } + } + while (timeOfTimeout > System.currentTimeMillis()); + + LOGGER.trace("Topic:" + topicName + ", timed out waiting for messages : " + consumerGroup + ":" + consumerId + + WITH_TIMEOUT + timeout); + return Response.status(Response.Status.REQUEST_TIMEOUT).build(); + } + + /** + * Return any messages on this topic with a message number greater than the supplied message number. + * + * @param topicName the topic name to check + * @param consumerGroupPair the pair with the information on the last message retrieved + * @return the messages or null if there are none + */ + private Object getWaitingMessages(final String topicName, final MutablePair consumerGroupPair) { + String foundMessageList = "["; + + synchronized (topicMessageMap) { + SortedMap messageMap = topicMessageMap.get(topicName); + if (messageMap == null || messageMap.lastKey() <= consumerGroupPair.getLeft()) { + return null; + } + + boolean first = true; + for (Object dmaapMessage : messageMap.tailMap(consumerGroupPair.getLeft() + 1).values()) { + if (first) { + first = false; + } else { + foundMessageList += ","; + } + try { + foundMessageList += new StandardCoder().encode(dmaapMessage); + } catch (CoderException e) { + e.printStackTrace(); + } + } + foundMessageList += ']'; + + LOGGER.debug("Topic:" + topicName + ", returning DMaaP messages from " + consumerGroupPair.getLeft() + + " to " + messageMap.lastKey()); + synchronized (consumerGroupsMap) { + consumerGroupPair.setLeft(messageMap.lastKey()); + } + } + + return (foundMessageList.length() < 3 ? null : foundMessageList); + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/BaseRestControllerV1.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/BaseRestControllerV1.java new file mode 100644 index 000000000..bcde4b522 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/BaseRestControllerV1.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap.rest; + +import io.swagger.annotations.Api; +import io.swagger.annotations.BasicAuthDefinition; +import io.swagger.annotations.Info; +import io.swagger.annotations.SecurityDefinition; +import io.swagger.annotations.SwaggerDefinition; +import io.swagger.annotations.Tag; +import java.net.HttpURLConnection; +import java.util.UUID; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response.ResponseBuilder; + +/** + * Version v1 common superclass to provide DMaaP endpoints for the DMaaP simulator component. + */ +// @formatter:off +@Api(value = "DMaaP Simulator API") +@Produces("application/json") +@Consumes({"application/cambria", "application/json"}) +@SwaggerDefinition( + info = @Info(description = + "Simulator for DMaaP, follows API as described at " + + "\"https://onap.readthedocs.io/en/amsterdam/submodules/dmaap/messagerouter/messageservice.git/" + + "docs/message-router/message-router.html", version = "v1.0", + title = "Policy Administration"), + consumes = {MediaType.APPLICATION_JSON}, + produces = {MediaType.APPLICATION_JSON}, + schemes = {SwaggerDefinition.Scheme.HTTP, SwaggerDefinition.Scheme.HTTPS}, + tags = {@Tag(name = "dmaap-simulator", description = "DMaaP simulation")}, + securityDefinition = @SecurityDefinition(basicAuthDefinitions = {@BasicAuthDefinition(key = "basicAuth")})) +// @formatter:on +public class BaseRestControllerV1 { + public static final String EXTENSION_NAME = "interface info"; + + public static final String API_VERSION_NAME = "api-version"; + public static final String API_VERSION = "1.0.0"; + + public static final String LAST_MOD_NAME = "last-mod-release"; + public static final String LAST_MOD_RELEASE = "Dublin"; + + public static final String VERSION_MINOR_NAME = "X-MinorVersion"; + public static final String VERSION_MINOR_DESCRIPTION = + "Used to request or communicate a MINOR version back from the client" + + " to the server, and from the server back to the client"; + + public static final String VERSION_PATCH_NAME = "X-PatchVersion"; + public static final String VERSION_PATCH_DESCRIPTION = "Used only to communicate a PATCH version in a response for" + + " troubleshooting purposes only, and will not be provided by" + " the client on request"; + + public static final String VERSION_LATEST_NAME = "X-LatestVersion"; + public static final String VERSION_LATEST_DESCRIPTION = "Used only to communicate an API's latest version"; + + public static final String REQUEST_ID_NAME = "X-ONAP-RequestID"; + public static final String REQUEST_ID_HDR_DESCRIPTION = "Used to track REST transactions for logging purpose"; + public static final String REQUEST_ID_PARAM_DESCRIPTION = "RequestID for http transaction"; + + public static final String AUTHORIZATION_TYPE = "basicAuth"; + + public static final int AUTHENTICATION_ERROR_CODE = HttpURLConnection.HTTP_UNAUTHORIZED; + public static final int AUTHORIZATION_ERROR_CODE = HttpURLConnection.HTTP_FORBIDDEN; + public static final int SERVER_ERROR_CODE = HttpURLConnection.HTTP_INTERNAL_ERROR; + + public static final String AUTHENTICATION_ERROR_MESSAGE = "Authentication Error"; + public static final String AUTHORIZATION_ERROR_MESSAGE = "Authorization Error"; + public static final String SERVER_ERROR_MESSAGE = "Internal Server Error"; + + /** + * Adds version headers to the response. + * + * @param respBuilder response builder + * @return the response builder, with version headers + */ + public ResponseBuilder addVersionControlHeaders(ResponseBuilder respBuilder) { + return respBuilder.header(VERSION_MINOR_NAME, "0").header(VERSION_PATCH_NAME, "0").header(VERSION_LATEST_NAME, + API_VERSION); + } + + /** + * Adds logging headers to the response. + * + * @param respBuilder response builder + * @return the response builder, with version logging + */ + public ResponseBuilder addLoggingHeaders(ResponseBuilder respBuilder, UUID requestId) { + if (requestId == null) { + // Generate a random uuid if client does not embed requestId in rest request + return respBuilder.header(REQUEST_ID_NAME, UUID.randomUUID()); + } + + return respBuilder.header(REQUEST_ID_NAME, requestId); + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/CambriaMessageBodyHandler.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/CambriaMessageBodyHandler.java new file mode 100644 index 000000000..e269ac00b --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/CambriaMessageBodyHandler.java @@ -0,0 +1,66 @@ +/* + * ============LICENSE_START======================================================= ONAP + * ================================================================================ Copyright (C) 2019 AT&T Intellectual + * Property. 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.models.sim.dmaap.rest; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.Provider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provider that serializes and de-serializes JSON via gson. + */ +@Provider +@Consumes(CambriaMessageBodyHandler.MEDIA_TYPE_APPLICATION_CAMBRIA) +@Produces(CambriaMessageBodyHandler.MEDIA_TYPE_APPLICATION_CAMBRIA) +public class CambriaMessageBodyHandler implements MessageBodyReader { + // Media type for Cambria + public static final String MEDIA_TYPE_APPLICATION_CAMBRIA = "application/cambria"; + + public static final Logger logger = LoggerFactory.getLogger(CambriaMessageBodyHandler.class); + + @Override + public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return MEDIA_TYPE_APPLICATION_CAMBRIA.equals(mediaType.toString()); + } + + @Override + public String readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap httpHeaders, InputStream entityStream) + throws IOException { + + String cambriaString = ""; + try (BufferedReader bufferedReader = new BufferedReader( + new InputStreamReader(entityStream))) { + String line; + while ((line = bufferedReader.readLine()) != null) { + cambriaString += line; + } + + return cambriaString.substring(cambriaString.indexOf('{'), cambriaString.length()); + } + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/DmaapSimRestControllerV1.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/DmaapSimRestControllerV1.java new file mode 100644 index 000000000..e3fdd4884 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/DmaapSimRestControllerV1.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap.rest; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Authorization; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; + +import org.onap.policy.models.sim.dmaap.provider.DmaapSimProvider; + +/** + * Class to provide REST endpoints for DMaaP simulator component statistics. + */ +@Path("/events") +public class DmaapSimRestControllerV1 extends BaseRestControllerV1 { + + /** + * Get a DMaaP message. + * + * @param topicName topic to get message from + * @param consumerGroup consumer group that is getting the message + * @param consumerId consumer ID that is getting the message + * @param timeout timeout for the message + * @return the message + */ + @GET + @Path("{topicName}/{consumerGroup}/{consumerId}") + // @formatter:off + @ApiOperation( + value = "Get a DMaaP event on a topic", + notes = "Returns an event on a DMaaP topic", + response = Object.class, + authorizations = + @Authorization(value = AUTHORIZATION_TYPE) + ) + @ApiResponses( + value = { + @ApiResponse( + code = AUTHENTICATION_ERROR_CODE, + message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse( + code = AUTHORIZATION_ERROR_CODE, + message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse( + code = SERVER_ERROR_CODE, + message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public Response getDmaaapMessage(@PathParam("topicName") final String topicName, + @PathParam("consumerGroup") final String consumerGroup, @PathParam("consumerId") final String consumerId, + @QueryParam("timeout") final int timeout) { + + return new DmaapSimProvider().processDmaapMessageGet(topicName, consumerGroup, consumerId, timeout); + } + + /** + * Post a DMaaP message. + * + * @param topicName topic to get message from415 + * @return the response to the post + */ + @POST + @Path("{topicName}") + // @formatter:off + @ApiOperation( + value = "Post a DMaaP event on a topic", + notes = "Returns an event on a DMaaP topic", + response = Response.class, + authorizations = + @Authorization(value = AUTHORIZATION_TYPE) + ) + @ApiResponses( + value = { + @ApiResponse( + code = AUTHENTICATION_ERROR_CODE, + message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse( + code = AUTHORIZATION_ERROR_CODE, + message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse( + code = SERVER_ERROR_CODE, + message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public Response postDmaaapMessage(@PathParam("topicName") final String topicName, final Object dmaapMessage) { + + return new DmaapSimProvider().processDmaapMessagePut(topicName, dmaapMessage); + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/DmaapSimRestServer.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/DmaapSimRestServer.java new file mode 100644 index 000000000..6853cc9dc --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/DmaapSimRestServer.java @@ -0,0 +1,138 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap.rest; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.onap.policy.common.capabilities.Startable; +import org.onap.policy.common.endpoints.http.server.HttpServletServer; +import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; +import org.onap.policy.models.sim.dmaap.parameters.RestServerParameters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class to manage life cycle of DMaaP Simulator rest server. + */ +public class DmaapSimRestServer implements Startable { + + private static final Logger LOGGER = LoggerFactory.getLogger(DmaapSimRestServer.class); + + private List servers = new ArrayList<>(); + + private RestServerParameters restServerParameters; + + /** + * Constructor for instantiating DmaapSimRestServer. + * + * @param restServerParameters the rest server parameters + */ + public DmaapSimRestServer(final RestServerParameters restServerParameters) { + this.restServerParameters = restServerParameters; + } + + /** + * {@inheritDoc}. + */ + @Override + public boolean start() { + try { + servers = HttpServletServer.factory.build(getServerProperties()); + for (final HttpServletServer server : servers) { + server.start(); + } + } catch (final Exception exp) { + LOGGER.error("Failed to start DMaaP simulator http server", exp); + return false; + } + return true; + } + + /** + * Creates the server properties object using restServerParameters. + * + * @return the properties object + */ + private Properties getServerProperties() { + final Properties props = new Properties(); + props.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES, restServerParameters.getName()); + + final String svcpfx = + PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + restServerParameters.getName(); + + props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, restServerParameters.getHost()); + props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, + Integer.toString(restServerParameters.getPort())); + props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, + String.join(",", DmaapSimRestControllerV1.class.getName())); + props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "false"); + props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, "true"); + props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER, + CambriaMessageBodyHandler.class.getName() + "," + JsonMessageBodyHandler.class.getName()); + return props; + } + + /** + * {@inheritDoc}. + */ + @Override + public boolean stop() { + for (final HttpServletServer server : servers) { + try { + server.stop(); + } catch (final Exception exp) { + LOGGER.error("Failed to stop DMaaP simulator http server", exp); + } + } + return true; + } + + /** + * {@inheritDoc}. + */ + @Override + public void shutdown() { + stop(); + } + + /** + * {@inheritDoc}. + */ + @Override + public boolean isAlive() { + return !servers.isEmpty(); + } + + /** + * {@inheritDoc}. + */ + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("DmaapSimRestServer [servers="); + builder.append(servers); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/JsonMessageBodyHandler.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/JsonMessageBodyHandler.java new file mode 100644 index 000000000..a3eebda00 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/JsonMessageBodyHandler.java @@ -0,0 +1,63 @@ +/* + * ============LICENSE_START======================================================= ONAP + * ================================================================================ Copyright (C) 2019 AT&T Intellectual + * Property. 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.models.sim.dmaap.rest; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.Provider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provider that serializes and de-serializes JSON via gson. + */ +@Provider +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public class JsonMessageBodyHandler implements MessageBodyReader { + public static final Logger logger = LoggerFactory.getLogger(JsonMessageBodyHandler.class); + + @Override + public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return MediaType.APPLICATION_JSON.equals(mediaType.toString()); + } + + @Override + public String readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap httpHeaders, InputStream entityStream) + throws IOException { + + String jsonString = ""; + try (BufferedReader bufferedReader = new BufferedReader( + new InputStreamReader(entityStream))) { + String line; + while ((line = bufferedReader.readLine()) != null) { + jsonString += line; + } + + return jsonString; + } + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/DmaapSimActivator.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/DmaapSimActivator.java new file mode 100644 index 000000000..899c0e081 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/DmaapSimActivator.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap.startstop; + +import org.onap.policy.common.parameters.ParameterService; +import org.onap.policy.common.utils.services.ServiceManagerContainer; +import org.onap.policy.models.sim.dmaap.parameters.DmaapSimParameterGroup; +import org.onap.policy.models.sim.dmaap.rest.DmaapSimRestServer; + +/** + * This class activates the DMaaP simulator as a complete service. + */ +public class DmaapSimActivator extends ServiceManagerContainer { + /** + * The DMaaP simulator REST API server. + */ + private DmaapSimRestServer restServer; + + /** + * Instantiate the activator for the DMaaP simulator as a complete service. + * + * @param dmaapSimParameterGroup the parameters for the DMaaP simulator service + */ + public DmaapSimActivator(final DmaapSimParameterGroup dmaapSimParameterGroup) { + super("DMaaP Simulator"); + + // @formatter:off + addAction("DMaaP Simulator parameters", + () -> ParameterService.register(dmaapSimParameterGroup), + () -> ParameterService.deregister(dmaapSimParameterGroup.getName())); + + addAction("Create REST server", + () -> restServer = new DmaapSimRestServer(dmaapSimParameterGroup.getRestServerParameters()), + () -> restServer = null + ); + + addAction("REST server", + () -> restServer.start(), + () -> restServer.stop()); + // @formatter:on + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/DmaapSimCommandLineArguments.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/DmaapSimCommandLineArguments.java new file mode 100644 index 000000000..c0db8a7ed --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/DmaapSimCommandLineArguments.java @@ -0,0 +1,242 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap.startstop; + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URL; +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; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.sim.dmaap.DmaapSimException; +import org.onap.policy.models.sim.dmaap.DmaapSimRuntimeException; + + +/** + * This class reads and handles command line parameters for the DMaaP simulator service. + */ +public class DmaapSimCommandLineArguments { + private static final String FILE_MESSAGE_PREAMBLE = " file \""; + private static final int HELP_LINE_LENGTH = 120; + + private final Options options; + private String configurationFilePath = null; + + /** + * Construct the options for the CLI editor. + */ + public DmaapSimCommandLineArguments() { + //@formatter:off + options = new Options(); + options.addOption(Option.builder("h") + .longOpt("help") + .desc("outputs the usage of this command") + .required(false) + .type(Boolean.class) + .build()); + options.addOption(Option.builder("v") + .longOpt("version") + .desc("outputs the version of DMaaP simulator") + .required(false) + .type(Boolean.class) + .build()); + options.addOption(Option.builder("c") + .longOpt("config-file") + .desc("the full path to the configuration file to use, " + + "the configuration file must be a Json file containing the DMaaP simulator parameters") + .hasArg() + .argName("CONFIG_FILE") + .required(false) + .type(String.class) + .build()); + //@formatter:on + } + + /** + * Construct the options for the CLI editor and parse in the given arguments. + * + * @param args The command line arguments + */ + public DmaapSimCommandLineArguments(final String[] args) { + // Set up the options with the default constructor + this(); + + // Parse the arguments + try { + parse(args); + } catch (final DmaapSimException e) { + throw new DmaapSimRuntimeException("parse error on DMaaP simulator parameters", e); + } + } + + /** + * Parse the command line options. + * + * @param args The command line arguments + * @return a string with a message for help and version, or null if there is no message + * @throws DmaapSimException on command argument errors + */ + public String parse(final String[] args) throws DmaapSimException { + // Clear all our arguments + setConfigurationFilePath(null); + + CommandLine commandLine = null; + try { + commandLine = new DefaultParser().parse(options, args); + } catch (final ParseException e) { + throw new DmaapSimException("invalid command line arguments specified : " + e.getMessage()); + } + + // Arguments left over after Commons CLI does its stuff + final String[] remainingArgs = commandLine.getArgs(); + + if (remainingArgs.length > 0 && commandLine.hasOption('c') || remainingArgs.length > 0) { + throw new DmaapSimException("too many command line arguments specified : " + Arrays.toString(args)); + } + + if (remainingArgs.length == 1) { + configurationFilePath = remainingArgs[0]; + } + + if (commandLine.hasOption('h')) { + return help(Main.class.getCanonicalName()); + } + + if (commandLine.hasOption('v')) { + return version(); + } + + if (commandLine.hasOption('c')) { + setConfigurationFilePath(commandLine.getOptionValue('c')); + } + + return null; + } + + /** + * Validate the command line options. + * + * @throws DmaapSimException on command argument validation errors + */ + public void validate() throws DmaapSimException { + validateReadableFile("DMaaP simulator configuration", configurationFilePath); + } + + /** + * Print version information for DMaaP simulator. + * + * @return the version string + */ + public String version() { + return ResourceUtils.getResourceAsString("version.txt"); + } + + /** + * Print help information for DMaaP simulator. + * + * @param mainClassName the main class name + * @return the help string + */ + public String help(final String mainClassName) { + final HelpFormatter helpFormatter = new HelpFormatter(); + final StringWriter stringWriter = new StringWriter(); + final PrintWriter printWriter = new PrintWriter(stringWriter); + + helpFormatter.printHelp(printWriter, HELP_LINE_LENGTH, mainClassName + " [options...]", "options", options, 0, + 0, ""); + + return stringWriter.toString(); + } + + /** + * Gets the configuration file path. + * + * @return the configuration file path + */ + public String getConfigurationFilePath() { + return configurationFilePath; + } + + /** + * Gets the full expanded configuration file path. + * + * @return the configuration file path + */ + public String getFullConfigurationFilePath() { + return ResourceUtils.getFilePath4Resource(getConfigurationFilePath()); + } + + /** + * Sets the configuration file path. + * + * @param configurationFilePath the configuration file path + */ + public void setConfigurationFilePath(final String configurationFilePath) { + this.configurationFilePath = configurationFilePath; + + } + + /** + * Check set configuration file path. + * + * @return true, if check set configuration file path + */ + public boolean checkSetConfigurationFilePath() { + return configurationFilePath != null && configurationFilePath.length() > 0; + } + + /** + * Validate readable file. + * + * @param fileTag the file tag + * @param fileName the file name + * @throws DmaapSimException on the file name passed as a parameter + */ + private void validateReadableFile(final String fileTag, final String fileName) throws DmaapSimException { + if (fileName == null || fileName.length() == 0) { + throw new DmaapSimException(fileTag + " file was not specified as an argument"); + } + + // The file name refers to a resource on the local file system + final URL fileUrl = ResourceUtils.getUrl4Resource(fileName); + if (fileUrl == null) { + throw new DmaapSimException(fileTag + FILE_MESSAGE_PREAMBLE + fileName + "\" does not exist"); + } + + final File theFile = new File(fileUrl.getPath()); + if (!theFile.exists()) { + throw new DmaapSimException(fileTag + FILE_MESSAGE_PREAMBLE + fileName + "\" does not exist"); + } + if (!theFile.isFile()) { + throw new DmaapSimException(fileTag + FILE_MESSAGE_PREAMBLE + fileName + "\" is not a normal file"); + } + if (!theFile.canRead()) { + throw new DmaapSimException(fileTag + FILE_MESSAGE_PREAMBLE + fileName + "\" is ureadable"); + } + } +} diff --git a/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/Main.java b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/Main.java new file mode 100644 index 000000000..878d008a8 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/Main.java @@ -0,0 +1,146 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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.models.sim.dmaap.startstop; + +import java.util.Arrays; + +import org.onap.policy.common.utils.services.Registry; +import org.onap.policy.models.sim.dmaap.DmaapSimConstants; +import org.onap.policy.models.sim.dmaap.DmaapSimException; +import org.onap.policy.models.sim.dmaap.parameters.DmaapSimParameterGroup; +import org.onap.policy.models.sim.dmaap.parameters.DmaapSimParameterHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class initiates the DMaaP simulator component. + */ +public class Main { + + private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); + + private DmaapSimActivator activator; + private DmaapSimParameterGroup parameterGroup; + + /** + * Instantiates the DMaap Simulator service. + * + * @param args the command line arguments + */ + public Main(final String[] args) { + final String argumentString = Arrays.toString(args); + LOGGER.info("Starting DMaaP simulator service with arguments - {}", argumentString); + + // Check the arguments + final DmaapSimCommandLineArguments arguments = new DmaapSimCommandLineArguments(); + try { + // The arguments return a string if there is a message to print and we should exit + final String argumentMessage = arguments.parse(args); + if (argumentMessage != null) { + LOGGER.info(argumentMessage); + return; + } + // Validate that the arguments are sane + arguments.validate(); + } catch (final DmaapSimException e) { + LOGGER.error("start of DMaaP simulator service failed", e); + return; + } + + // Read the parameters + try { + parameterGroup = new DmaapSimParameterHandler().getParameters(arguments); + } catch (final Exception e) { + LOGGER.error("start of DMaaP simulator service failed", e); + return; + } + + // Now, create the activator for the DMaaP Simulator service + activator = new DmaapSimActivator(parameterGroup); + Registry.register(DmaapSimConstants.REG_DMAAP_SIM_ACTIVATOR, activator); + + // Start the activator + try { + activator.start(); + } catch (final RuntimeException e) { + LOGGER.error("start of DMaaP simulator service failed, used parameters are {}", Arrays.toString(args), e); + Registry.unregister(DmaapSimConstants.REG_DMAAP_SIM_ACTIVATOR); + return; + } + + // Add a shutdown hook to shut everything down in an orderly manner + Runtime.getRuntime().addShutdownHook(new DmaapSimShutdownHookClass()); + LOGGER.info("Started DMaaP simulator service"); + } + + /** + * Get the parameters specified in JSON. + * + * @return the parameters + */ + public DmaapSimParameterGroup getParameters() { + return parameterGroup; + } + + /** + * Shut down Execution. + * + * @throws DmaapSimException on shutdown errors + */ + public void shutdown() throws DmaapSimException { + // clear the parameterGroup variable + parameterGroup = null; + + // clear the DMaaP simulator activator + if (activator != null) { + activator.stop(); + } + } + + /** + * The Class DmaapSimShutdownHookClass terminates the DMaaP simulator service when its run method is called. + */ + private class DmaapSimShutdownHookClass extends Thread { + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + try { + // Shutdown the DMaaP simulator service and wait for everything to stop + activator.stop(); + } catch (final RuntimeException e) { + LOGGER.warn("error occured during shut down of the DMaaP simulator service", e); + } + } + } + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(final String[] args) { + new Main(args); + } +} diff --git a/models-sim/models-sim-dmaap/src/main/resources/version.txt b/models-sim/models-sim-dmaap/src/main/resources/version.txt new file mode 100644 index 000000000..d629db844 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/main/resources/version.txt @@ -0,0 +1,4 @@ +ONAP DMaaP simulator Service +Version: ${project.version} +Built (UTC): ${maven.build.timestamp} +ONAP https://wiki.onap.org \ No newline at end of file diff --git a/models-sim/models-sim-dmaap/src/test/resources/logback-test.xml b/models-sim/models-sim-dmaap/src/test/resources/logback-test.xml new file mode 100644 index 000000000..de7ef98da --- /dev/null +++ b/models-sim/models-sim-dmaap/src/test/resources/logback-test.xml @@ -0,0 +1,54 @@ + + + + + + DMaaPSim + + + + + + + %d %contextName [%t] %level %logger{36} - %msg%n + + + + + + + + + ${LOG_DIR}/apex.log + + %d %-5relative [procId=${processId}] [%thread] %-5level + %logger{26} - %msg %n %ex{full} + + + + + + + + + + + diff --git a/models-sim/models-sim-dmaap/src/test/resources/parameters/EmptyParameters.json b/models-sim/models-sim-dmaap/src/test/resources/parameters/EmptyParameters.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/models-sim/models-sim-dmaap/src/test/resources/parameters/EmptyParameters.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/models-sim/models-sim-dmaap/src/test/resources/parameters/InvalidParameters.json b/models-sim/models-sim-dmaap/src/test/resources/parameters/InvalidParameters.json new file mode 100644 index 000000000..de2040cc8 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/test/resources/parameters/InvalidParameters.json @@ -0,0 +1,3 @@ +{ + "name" : [] +} \ No newline at end of file diff --git a/models-sim/models-sim-dmaap/src/test/resources/parameters/MinimumParameters.json b/models-sim/models-sim-dmaap/src/test/resources/parameters/MinimumParameters.json new file mode 100644 index 000000000..aeedf9d6e --- /dev/null +++ b/models-sim/models-sim-dmaap/src/test/resources/parameters/MinimumParameters.json @@ -0,0 +1,7 @@ +{ + "name":"DMaapSim", + "restServerParameters":{ + "host":"0.0.0.0", + "port":6845 + } +} diff --git a/models-sim/models-sim-dmaap/src/test/resources/parameters/NoParameters.json b/models-sim/models-sim-dmaap/src/test/resources/parameters/NoParameters.json new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/models-sim/models-sim-dmaap/src/test/resources/parameters/NoParameters.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/models-sim/models-sim-dmaap/src/test/resources/parameters/NormalParameters.json b/models-sim/models-sim-dmaap/src/test/resources/parameters/NormalParameters.json new file mode 100644 index 000000000..a2a036645 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/test/resources/parameters/NormalParameters.json @@ -0,0 +1,7 @@ +{ + "name": "DMaapSim", + "restServerParameters": { + "host": "0.0.0.0", + "port": 6845 + } +} diff --git a/models-sim/models-sim-dmaap/src/test/resources/parameters/Parameters_InvalidName.json b/models-sim/models-sim-dmaap/src/test/resources/parameters/Parameters_InvalidName.json new file mode 100644 index 000000000..fba033e52 --- /dev/null +++ b/models-sim/models-sim-dmaap/src/test/resources/parameters/Parameters_InvalidName.json @@ -0,0 +1,9 @@ +{ + "name":" ", + "restServerParameters":{ + "host":"0.0.0.0", + "port":6969, + "userName":"dmaapsim", + "password":"zb!XztG34" + } +} diff --git a/models-sim/pom.xml b/models-sim/pom.xml new file mode 100644 index 000000000..c6165cc16 --- /dev/null +++ b/models-sim/pom.xml @@ -0,0 +1,36 @@ + + + + 4.0.0 + + org.onap.policy.models + policy-models + 2.0.0-SNAPSHOT + + + org.onap.policy.models.sim + policy-models-sim + pom + ${project.artifactId} + + models-sim-dmaap + + diff --git a/pom.xml b/pom.xml index 9b1071368..991534b5b 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,7 @@ models-provider models-examples models-interactions + models-sim -- 2.16.6