Add DMaaP simulator for CSIT testing 93/85593/1
authorliamfallon <liam.fallon@est.tech>
Wed, 17 Apr 2019 13:58:26 +0000 (13:58 +0000)
committerliamfallon <liam.fallon@est.tech>
Wed, 17 Apr 2019 13:58:26 +0000 (13:58 +0000)
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>
26 files changed:
models-sim/models-sim-dmaap/pom.xml [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimConstants.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimException.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/DmaapSimRuntimeException.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/DmaapSimParameterGroup.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/DmaapSimParameterHandler.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/parameters/RestServerParameters.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/provider/DmaapSimProvider.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/BaseRestControllerV1.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/CambriaMessageBodyHandler.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/DmaapSimRestControllerV1.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/DmaapSimRestServer.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/rest/JsonMessageBodyHandler.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/DmaapSimActivator.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/DmaapSimCommandLineArguments.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/java/org/onap/policy/models/sim/dmaap/startstop/Main.java [new file with mode: 0644]
models-sim/models-sim-dmaap/src/main/resources/version.txt [new file with mode: 0644]
models-sim/models-sim-dmaap/src/test/resources/logback-test.xml [new file with mode: 0644]
models-sim/models-sim-dmaap/src/test/resources/parameters/EmptyParameters.json [new file with mode: 0644]
models-sim/models-sim-dmaap/src/test/resources/parameters/InvalidParameters.json [new file with mode: 0644]
models-sim/models-sim-dmaap/src/test/resources/parameters/MinimumParameters.json [new file with mode: 0644]
models-sim/models-sim-dmaap/src/test/resources/parameters/NoParameters.json [new file with mode: 0644]
models-sim/models-sim-dmaap/src/test/resources/parameters/NormalParameters.json [new file with mode: 0644]
models-sim/models-sim-dmaap/src/test/resources/parameters/Parameters_InvalidName.json [new file with mode: 0644]
models-sim/pom.xml [new file with mode: 0644]
pom.xml

diff --git a/models-sim/models-sim-dmaap/pom.xml b/models-sim/models-sim-dmaap/pom.xml
new file mode 100644 (file)
index 0000000..b21926b
--- /dev/null
@@ -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 (file)
index 0000000..1682eb9
--- /dev/null
@@ -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 (file)
index 0000000..aaf8980
--- /dev/null
@@ -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 (file)
index 0000000..fe8b7e2
--- /dev/null
@@ -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 (file)
index 0000000..caae287
--- /dev/null
@@ -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 (file)
index 0000000..8eb76ec
--- /dev/null
@@ -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 (file)
index 0000000..c7269f6
--- /dev/null
@@ -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 (file)
index 0000000..42a653d
--- /dev/null
@@ -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 (file)
index 0000000..bcde4b5
--- /dev/null
@@ -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 (file)
index 0000000..e269ac0
--- /dev/null
@@ -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 (file)
index 0000000..e3fdd48
--- /dev/null
@@ -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 (file)
index 0000000..6853cc9
--- /dev/null
@@ -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 (file)
index 0000000..a3eebda
--- /dev/null
@@ -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 (file)
index 0000000..899c0e0
--- /dev/null
@@ -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 (file)
index 0000000..c0db8a7
--- /dev/null
@@ -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 (file)
index 0000000..878d008
--- /dev/null
@@ -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 (file)
index 0000000..d629db8
--- /dev/null
@@ -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 (file)
index 0000000..de7ef98
--- /dev/null
@@ -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 (file)
index 0000000..0637a08
--- /dev/null
@@ -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 (file)
index 0000000..de2040c
--- /dev/null
@@ -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 (file)
index 0000000..aeedf9d
--- /dev/null
@@ -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 (file)
index 0000000..7a73a41
--- /dev/null
@@ -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 (file)
index 0000000..a2a0366
--- /dev/null
@@ -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 (file)
index 0000000..fba033e
--- /dev/null
@@ -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 (file)
index 0000000..c6165cc
--- /dev/null
@@ -0,0 +1,36 @@
+<!--
+  ============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</groupId>
+    <artifactId>policy-models</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.onap.policy.models.sim</groupId>
+  <artifactId>policy-models-sim</artifactId>
+  <packaging>pom</packaging>
+  <name>${project.artifactId}</name>
+  <modules>
+      <module>models-sim-dmaap</module>
+  </modules>
+</project>
diff --git a/pom.xml b/pom.xml
index 9b10713..991534b 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -59,6 +59,7 @@
         <module>models-provider</module>
         <module>models-examples</module>
         <module>models-interactions</module>
+        <module>models-sim</module>
     </modules>
 
     <distributionManagement>