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 <liam.fallon@est.tech>
diff --git a/models-sim/models-sim-dmaap/pom.xml b/models-sim/models-sim-dmaap/pom.xml
new file mode 100644
index 0000000..b21926b
--- /dev/null
+++ b/models-sim/models-sim-dmaap/pom.xml
@@ -0,0 +1,81 @@
+<!--
+ ============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=========================================================
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.policy.models.sim</groupId>
+ <artifactId>policy-models-sim</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>policy-models-sim-dmaap</artifactId>
+
+ <name>${project.artifactId}</name>
+ <description>A module that implements a very simple DMaaP simulator.</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>common-parameters</artifactId>
+ <version>${policy.common.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>utils</artifactId>
+ <version>${policy.common.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>policy-endpoints</artifactId>
+ <version>${policy.common.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>gson</artifactId>
+ <version>${policy.common.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <!-- Output the version of the pap service -->
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/version.txt</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>false</filtering>
+ <excludes>
+ <exclude>**/version.txt</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+</project>
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 0000000..1682eb9
--- /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 0000000..aaf8980
--- /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 0000000..fe8b7e2
--- /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 0000000..caae287
--- /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 0000000..8eb76ec
--- /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 0000000..c7269f6
--- /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 0000000..42a653d
--- /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<String, SortedMap<Integer, Object>> topicMessageMap = new LinkedHashMap<>();
+
+ // The map of topic messages
+ private static final Map<String, Map<String, MutablePair<Integer, String>>> 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<Integer, Object> 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<Integer, String> consumerGroupPair = null;
+
+ synchronized (consumerGroupsMap) {
+ Map<String, MutablePair<Integer, String>> 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<Integer, String> consumerGroupPair) {
+ String foundMessageList = "[";
+
+ synchronized (topicMessageMap) {
+ SortedMap<Integer, Object> 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 0000000..bcde4b5
--- /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 0000000..e269ac0
--- /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<Object> {
+ // 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<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> 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 0000000..e3fdd48
--- /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 0000000..6853cc9
--- /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<HttpServletServer> 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 0000000..a3eebda
--- /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<Object> {
+ 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<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> 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 0000000..899c0e0
--- /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 0000000..c0db8a7
--- /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 0000000..878d008
--- /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 0000000..d629db8
--- /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 0000000..de7ef98
--- /dev/null
+++ b/models-sim/models-sim-dmaap/src/test/resources/logback-test.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============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=========================================================
+-->
+
+<configuration>
+
+ <contextName>DMaaPSim</contextName>
+ <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
+ <property name="LOG_DIR" value="${java.io.tmpdir}/pf_logging/" />
+
+ <!-- USE FOR STD OUT ONLY -->
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern>
+ </encoder>
+ </appender>
+
+ <root level="info">
+ <appender-ref ref="STDOUT" />
+ </root>
+
+ <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${LOG_DIR}/apex.log</file>
+ <encoder>
+ <pattern>%d %-5relative [procId=${processId}] [%thread] %-5level
+ %logger{26} - %msg %n %ex{full}</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.eclipse.jetty" level="info" additivity="false">
+ <appender-ref ref="STDOUT" />
+ </logger>
+
+ <logger name="org.onap.policy.models.sim.dmaap" level="trace" additivity="false">
+ <appender-ref ref="STDOUT" />
+ </logger>
+</configuration>
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 0000000..0637a08
--- /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 0000000..de2040c
--- /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 0000000..aeedf9d
--- /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 0000000..7a73a41
--- /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 0000000..a2a0366
--- /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 0000000..fba033e
--- /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"
+ }
+}