aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--feature-simulators/pom.xml53
-rw-r--r--feature-simulators/src/main/java/org/onap/policy/drools/simulators/DMaaPSimulatorJaxRs.java123
-rw-r--r--feature-simulators/src/test/java/org/onap/policy/drools/simulators/DMaaPSimulatorTest.java364
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java4
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java2
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java10
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java2
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/ControllerConfiguration.java46
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/DroolsConfiguration.java41
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java41
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java66
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/system/PolicyControllerFactory.java11
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngine.java82
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java2
-rw-r--r--pom.xml1
15 files changed, 730 insertions, 118 deletions
diff --git a/feature-simulators/pom.xml b/feature-simulators/pom.xml
new file mode 100644
index 00000000..767739bc
--- /dev/null
+++ b/feature-simulators/pom.xml
@@ -0,0 +1,53 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP Policy Engine - Drools PDP
+ ================================================================================
+ Copyright (C) 2017 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=========================================================
+ -->
+
+<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.drools-pdp</groupId>
+ <artifactId>drools-pdp</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>feature-simulators</artifactId>
+
+ <name>feature-simulators</name>
+
+ <properties>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.drools-pdp</groupId>
+ <artifactId>policy-endpoints</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/feature-simulators/src/main/java/org/onap/policy/drools/simulators/DMaaPSimulatorJaxRs.java b/feature-simulators/src/main/java/org/onap/policy/drools/simulators/DMaaPSimulatorJaxRs.java
new file mode 100644
index 00000000..bdabc6ee
--- /dev/null
+++ b/feature-simulators/src/main/java/org/onap/policy/drools/simulators/DMaaPSimulatorJaxRs.java
@@ -0,0 +1,123 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * feature-simulators
+ * ================================================================================
+ * Copyright (C) 2017 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.drools.simulators;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.BlockingQueue;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
+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.Context;
+import javax.ws.rs.core.MediaType;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Path("/events")
+public class DMaaPSimulatorJaxRs {
+
+ private static final Map<String, BlockingQueue<String>> queues = new ConcurrentHashMap<>();
+ private static final Logger logger = LoggerFactory.getLogger(DMaaPSimulatorJaxRs.class);
+ private static int responseCode = 200;
+
+ @GET
+ @Path("/{topicName}/{consumeGroup}/{consumerId}")
+ public String subscribe(@DefaultValue("0") @QueryParam("timeout") int timeout, @PathParam("topicName") String topicName,
+ @Context final HttpServletResponse httpResponse) {
+ int currentRespCode = responseCode;
+ httpResponse.setStatus(currentRespCode);
+ try {
+ httpResponse.flushBuffer();
+ } catch (IOException e) {
+ final Logger logger = LoggerFactory.getLogger(DMaaPSimulatorJaxRs.class);
+ logger.error("flushBuffer threw: ", e);
+ return "Got an error";
+ }
+
+ if (currentRespCode < 200 || currentRespCode >= 300)
+ {
+ return "You got response code: " + currentRespCode;
+ }
+ if (queues.containsKey(topicName)) {
+ BlockingQueue<String> queue = queues.get(topicName);
+ String response = "No Data";
+ try {
+ response = queue.poll(timeout, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ logger.debug("error in DMaaP simulator", e);
+ }
+ if (response == null) {
+ response = "No Data";
+ }
+ return response;
+ }
+ else if (timeout > 0) {
+ try {
+ Thread.sleep(timeout);
+ if (queues.containsKey(topicName)) {
+ BlockingQueue<String> queue = queues.get(topicName);
+ String response = queue.poll();
+ if (response == null) {
+ response = "No Data";
+ }
+ return response;
+ }
+ } catch (InterruptedException e) {
+ logger.debug("error in DMaaP simulator", e);
+ }
+ }
+ return "No topic";
+ }
+
+ @POST
+ @Path("/{topicName}")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public String publish(@PathParam("topicName") String topicName, String body) {
+ if (queues.containsKey(topicName)) {
+ BlockingQueue<String> queue = queues.get(topicName);
+ queue.offer(body);
+ }
+ else {
+ BlockingQueue<String> queue = new LinkedBlockingQueue<>();
+ queue.offer(body);
+ queues.put(topicName, queue);
+ }
+
+ return "";
+ }
+
+ @POST
+ @Path("/setStatus")
+ public String setStatus(@QueryParam("statusCode") int statusCode) {
+ responseCode = statusCode;
+ return "Status code set";
+ }
+}
diff --git a/feature-simulators/src/test/java/org/onap/policy/drools/simulators/DMaaPSimulatorTest.java b/feature-simulators/src/test/java/org/onap/policy/drools/simulators/DMaaPSimulatorTest.java
new file mode 100644
index 00000000..415c5206
--- /dev/null
+++ b/feature-simulators/src/test/java/org/onap/policy/drools/simulators/DMaaPSimulatorTest.java
@@ -0,0 +1,364 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * feature-simulators
+ * ================================================================================
+ * Copyright (C) 2017 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.drools.simulators;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.drools.http.server.HttpServletServer;
+import org.onap.policy.drools.utils.LoggerUtil;
+import org.onap.policy.drools.utils.NetworkUtil;
+
+public class DMaaPSimulatorTest {
+
+ private static final int DMAAPSIM_SERVER_PORT = 6670;
+ @BeforeClass
+ public static void setUpSimulator() {
+ LoggerUtil.setLevel("ROOT", "INFO");
+ LoggerUtil.setLevel("org.eclipse.jetty", "WARN");
+ try {
+ final HttpServletServer testServer = HttpServletServer.factory.build("dmaapSim",
+ "localhost", DMAAPSIM_SERVER_PORT, "/", false, true);
+ testServer.addServletClass("/*", DMaaPSimulatorJaxRs.class.getName());
+ testServer.waitedStart(5000);
+ if (!NetworkUtil.isTcpPortOpen("localhost", testServer.getPort(), 5, 10000L))
+ throw new IllegalStateException("cannot connect to port " + testServer.getPort());
+ } catch (final Exception e) {
+ fail(e.getMessage());
+ }
+ }
+
+ @AfterClass
+ public static void tearDownSimulator() {
+ HttpServletServer.factory.destroy();
+ }
+
+ @Test
+ public void testGetNoData() {
+ int timeout = 1000;
+ Pair <Integer, String> response = dmaapGet("myTopicNoData", timeout);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals("No topic", response.b);
+ }
+
+ @Test
+ public void testSinglePost() {
+ String myTopic = "myTopicSinglePost";
+ String testData = "This is some test data";
+ Pair<Integer, String> response = dmaapPost(myTopic, testData);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = dmaapGet(myTopic, 1000);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals(testData, response.b);
+ }
+
+ @Test
+ public void testOneTopicMultiPost() {
+ String[] data = {"data point 1", "data point 2", "something random"};
+ String myTopic = "myTopicMultiPost";
+ Pair<Integer, String> response = dmaapPost(myTopic, data[0]);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = dmaapPost(myTopic, data[1]);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = dmaapPost(myTopic, data[2]);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = dmaapGet(myTopic, 1000);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals(data[0], response.b);
+
+ response = dmaapGet(myTopic, 1000);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals(data[1], response.b);
+
+ response = dmaapGet(myTopic, 1000);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals(data[2], response.b);
+ }
+
+ @Test
+ public void testMultiTopic() {
+ String[][] data = {{"Topic one message one", "Topic one message two"}, {"Topic two message one", "Topic two message two"}};
+ String[] topics = {"topic1", "topic2"};
+
+ Pair<Integer, String> response = dmaapPost(topics[0], data[0][0]);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = dmaapGet(topics[0], 1000);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals(data[0][0], response.b);
+
+ response = dmaapGet(topics[1], 1000);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals("No topic", response.b);
+
+ response = dmaapPost(topics[1], data[1][0]);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = dmaapPost(topics[1], data[1][1]);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = dmaapPost(topics[0], data[0][1]);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = dmaapGet(topics[1], 1000);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals(data[1][0], response.b);
+
+ response = dmaapGet(topics[0], 1000);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals(data[0][1], response.b);
+
+ response = dmaapGet(topics[1], 1000);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals(data[1][1], response.b);
+
+ response = dmaapGet(topics[0], 1000);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertEquals("No Data", response.b);
+ }
+
+ @Test
+ public void testResponseCode() {
+ Pair<Integer, String> response = dmaapPost("myTopic", "myTopicData");
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = setStatus(503);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = dmaapGet("myTopic", 500);
+ assertNotNull(response);
+ assertEquals(503, response.a.intValue());
+ assertEquals("You got response code: 503", response.b);
+
+ response = setStatus(202);
+ assertNotNull(response);
+ assertNotNull(response.a);
+ assertNotNull(response.b);
+
+ response = dmaapGet("myTopic", 500);
+ assertNotNull(response);
+ assertEquals(202, response.a.intValue());
+ assertEquals("myTopicData", response.b);
+ }
+
+ private static Pair<Integer, String> dmaapGet (String topic, int timeout) {
+ return dmaapGet(topic, "1", "1", timeout);
+ }
+
+ private static Pair<Integer, String> dmaapGet (String topic, String consumerGroup, String consumerId, int timeout) {
+ String url = "http://localhost:" + DMAAPSIM_SERVER_PORT + "/events/" + topic + "/" + consumerGroup + "/" + consumerId + "?timeout=" + timeout;
+ try {
+ URLConnection conn = new URL(url).openConnection();
+ HttpURLConnection httpConn = null;
+ if (conn instanceof HttpURLConnection) {
+ httpConn = (HttpURLConnection) conn;
+ }
+ else {
+ fail("connection not set up right");
+ }
+ httpConn.setRequestMethod("GET");
+ httpConn.connect();
+ String response = "";
+ try (BufferedReader connReader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()))) {
+ String line;
+ while((line = connReader.readLine()) != null) {
+ response += line;
+ }
+ httpConn.disconnect();
+ return new Pair<Integer, String>(httpConn.getResponseCode(), response);
+ }
+ catch (IOException e) {
+ if (e.getMessage().startsWith("Server returned HTTP response code")) {
+ System.out.println("hi");
+ BufferedReader connReader = new BufferedReader(new InputStreamReader(httpConn.getErrorStream()));
+ String line;
+ while((line = connReader.readLine()) != null) {
+ response += line;
+ }
+ httpConn.disconnect();
+ return new Pair<Integer, String>(httpConn.getResponseCode(), response);
+ }
+ else {
+ fail("we got an exception: " + e);
+ }
+ }
+ }
+ catch (Exception e) {
+ fail("we got an exception" + e);
+ }
+
+ return null;
+ }
+
+ private static Pair<Integer, String> dmaapPost (String topic, String data) {
+ String url = "http://localhost:" + DMAAPSIM_SERVER_PORT + "/events/" + topic;
+ byte[] postData = data.getBytes(StandardCharsets.UTF_8);
+ try {
+ URLConnection conn = new URL(url).openConnection();
+ HttpURLConnection httpConn = null;
+ if (conn instanceof HttpURLConnection) {
+ httpConn = (HttpURLConnection) conn;
+ }
+ else {
+ fail("connection not set up right");
+ }
+ httpConn.setRequestMethod("POST");
+ httpConn.setDoOutput(true);
+ httpConn.setRequestProperty( "Content-Type", "text/plain");
+ httpConn.setRequestProperty("Content-Length", ""+postData.length);
+ httpConn.connect();
+ String response = "";
+ try (DataOutputStream connWriter = new DataOutputStream(httpConn.getOutputStream())) {
+ connWriter.write(postData);
+ connWriter.flush();
+ }
+ try (BufferedReader connReader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()))) {
+ String line;
+ while((line = connReader.readLine()) != null) {
+ response += line;
+ }
+ httpConn.disconnect();
+ return new Pair<Integer, String>(httpConn.getResponseCode(), response);
+ }
+ catch (IOException e) {
+ if (e.getMessage().startsWith("Server returned HTTP response code")) {
+ System.out.println("hi");
+ BufferedReader connReader = new BufferedReader(new InputStreamReader(httpConn.getErrorStream()));
+ String line;
+ while((line = connReader.readLine()) != null) {
+ response += line;
+ }
+ httpConn.disconnect();
+ return new Pair<Integer, String>(httpConn.getResponseCode(), response);
+ }
+ else {
+ fail("we got an exception: " + e);
+ }
+ }
+ }
+ catch (Exception e) {
+ fail("we got an exception: " + e);
+ }
+ return null;
+ }
+
+ private static Pair<Integer, String> setStatus (int status) {
+ String url = "http://localhost:" + DMAAPSIM_SERVER_PORT + "/events/setStatus?statusCode=" + status;
+ try {
+ URLConnection conn = new URL(url).openConnection();
+ HttpURLConnection httpConn = null;
+ if (conn instanceof HttpURLConnection) {
+ httpConn = (HttpURLConnection) conn;
+ }
+ else {
+ fail("connection not set up right");
+ }
+ httpConn.setRequestMethod("POST");
+ httpConn.connect();
+ String response = "";
+ try (BufferedReader connReader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()))) {
+ String line;
+ while((line = connReader.readLine()) != null) {
+ response += line;
+ }
+ httpConn.disconnect();
+ return new Pair<Integer, String>(httpConn.getResponseCode(), response);
+ }
+ catch (IOException e) {
+ if (e.getMessage().startsWith("Server returned HTTP response code")) {
+ System.out.println("hi");
+ BufferedReader connReader = new BufferedReader(new InputStreamReader(httpConn.getErrorStream()));
+ String line;
+ while((line = connReader.readLine()) != null) {
+ response += line;
+ }
+ httpConn.disconnect();
+ return new Pair<Integer, String>(httpConn.getResponseCode(), response);
+ }
+ else {
+ fail("we got an exception: " + e);
+ }
+ }
+ }
+ catch (Exception e) {
+ fail("we got an exception" + e);
+ }
+ return null;
+ }
+
+ private static class Pair<A, B> {
+ public final A a;
+ public final B b;
+
+ public Pair(A a, B b) {
+ this.a = a;
+ this.b = b;
+ }
+ }
+} \ No newline at end of file
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
index 9689776c..8a0073c0 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
@@ -100,12 +100,12 @@ public class MavenDroolsController implements DroolsController {
/**
* recent source events processed
*/
- protected final CircularFifoQueue<Object> recentSourceEvents = new CircularFifoQueue<Object>(10);
+ protected final CircularFifoQueue<Object> recentSourceEvents = new CircularFifoQueue<>(10);
/**
* recent sink events processed
*/
- protected final CircularFifoQueue<String> recentSinkEvents = new CircularFifoQueue<String>(10);
+ protected final CircularFifoQueue<String> recentSinkEvents = new CircularFifoQueue<>(10);
/**
* original Drools Model/Rules classloader hash
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java
index 2c4e40be..6dd542c3 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java
@@ -158,7 +158,7 @@ public class NullDroolsController implements DroolsController {
@Override
public Map<String, Integer> factClassNames(String sessionName)
throws IllegalArgumentException {
- return new HashMap<String,Integer>();
+ return new HashMap<>();
}
@Override
diff --git a/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java b/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java
index 905e50c2..b436ef97 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java
@@ -80,13 +80,15 @@ public class FileSystemPersistence implements SystemPersistence {
@Override
public void setConfigurationDir(String configDir) {
- if (configDir == null) {
- configDir = DEFAULT_CONFIGURATION_DIR;
+ String tempConfigDir = configDir;
+
+ if (tempConfigDir == null) {
+ tempConfigDir = DEFAULT_CONFIGURATION_DIR;
this.configurationDirectory = Paths.get(DEFAULT_CONFIGURATION_DIR);
}
- if (!configDir.equals(DEFAULT_CONFIGURATION_DIR))
- this.configurationDirectory = Paths.get(configDir);
+ if (!tempConfigDir.equals(DEFAULT_CONFIGURATION_DIR))
+ this.configurationDirectory = Paths.get(tempConfigDir);
if (Files.notExists(this.configurationDirectory)) {
try {
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java
index 0a52d254..12d0ffe5 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java
@@ -197,7 +197,7 @@ public class JsonProtocolFilter {
for (FilterRule filter: rules) {
if (filter.regex == null ||
filter.regex.isEmpty() ||
- filter.regex.equals(".*")) {
+ ".*".equals(filter.regex)) {
// Only check for presence
if (!event.has(filter.name)) {
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/ControllerConfiguration.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/ControllerConfiguration.java
index b0b8b504..845c4944 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/ControllerConfiguration.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/ControllerConfiguration.java
@@ -198,25 +198,13 @@ public class ControllerConfiguration {
protected boolean declaredProperty(String name, Object value) {
switch (name) {
case "name":
- if (value instanceof String) {
- setName(((String) value));
- } else {
- throw new IllegalArgumentException(("property \"name\" is of type \"java.lang.String\", but got "+ value.getClass().toString()));
- }
+ callSetName(value);
return true;
case "operation":
- if (value instanceof String) {
- setOperation(((String) value));
- } else {
- throw new IllegalArgumentException(("property \"operation\" is of type \"java.lang.String\", but got "+ value.getClass().toString()));
- }
+ callSetOperation(value);
return true;
case "drools":
- if (value instanceof DroolsConfiguration) {
- setDrools(((DroolsConfiguration) value));
- } else {
- throw new IllegalArgumentException(("property \"drools\" is of type \"org.onap.policy.drools.protocol.configuration.Drools\", but got "+ value.getClass().toString()));
- }
+ callSetDrools(value);
return true;
default:
return false;
@@ -250,13 +238,13 @@ public class ControllerConfiguration {
public void set(String name, Object value) {
if (!declaredProperty(name, value)) {
- getAdditionalProperties().put(name, ((Object) value));
+ getAdditionalProperties().put(name, (Object) value);
}
}
public ControllerConfiguration with(String name, Object value) {
if (!declaredProperty(name, value)) {
- getAdditionalProperties().put(name, ((Object) value));
+ getAdditionalProperties().put(name, (Object) value);
}
return this;
}
@@ -277,5 +265,29 @@ public class ControllerConfiguration {
ControllerConfiguration rhs = ((ControllerConfiguration) other);
return new EqualsBuilder().append(name, rhs.name).append(operation, rhs.operation).append(drools, rhs.drools).append(additionalProperties, rhs.additionalProperties).isEquals();
}
+
+ public void callSetName(Object value) {
+ if (value instanceof String) {
+ setName((String) value);
+ } else {
+ throw new IllegalArgumentException("property \"name\" is of type \"java.lang.String\", but got "+ value.getClass().toString());
+ }
+ }
+
+ public void callSetOperation(Object value) {
+ if (value instanceof String) {
+ setOperation((String) value);
+ } else {
+ throw new IllegalArgumentException("property \"operation\" is of type \"java.lang.String\", but got "+ value.getClass().toString());
+ }
+ }
+
+ public void callSetDrools(Object value) {
+ if (value instanceof DroolsConfiguration) {
+ setDrools((DroolsConfiguration) value);
+ } else {
+ throw new IllegalArgumentException("property \"drools\" is of type \"org.onap.policy.drools.protocol.configuration.Drools\", but got "+ value.getClass().toString());
+ }
+ }
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/DroolsConfiguration.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/DroolsConfiguration.java
index 4c672e7b..e822d88e 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/DroolsConfiguration.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/DroolsConfiguration.java
@@ -196,25 +196,13 @@ public class DroolsConfiguration {
protected boolean declaredProperty(String name, Object value) {
switch (name) {
case "artifactId":
- if (value instanceof String) {
- setArtifactId((String) value);
- } else {
- throw new IllegalArgumentException(("property \"artifactId\" is of type \"java.lang.String\", but got "+ value.getClass().toString()));
- }
+ callSetArtifactId(value);
return true;
case "groupId":
- if (value instanceof String) {
- setGroupId((String) value);
- } else {
- throw new IllegalArgumentException(("property \"groupId\" is of type \"java.lang.String\", but got "+ value.getClass().toString()));
- }
+ callSetGroupId(value);
return true;
case "version":
- if (value instanceof String) {
- setVersion((String) value);
- } else {
- throw new IllegalArgumentException(("property \"version\" is of type \"java.lang.String\", but got "+ value.getClass().toString()));
- }
+ callSetVersion(value);
return true;
default:
return false;
@@ -275,5 +263,28 @@ public class DroolsConfiguration {
DroolsConfiguration rhs = ((DroolsConfiguration) other);
return new EqualsBuilder().append(artifactId, rhs.artifactId).append(groupId, rhs.groupId).append(version, rhs.version).append(additionalProperties, rhs.additionalProperties).isEquals();
}
+
+ public void callSetArtifactId(Object value) {
+ if (value instanceof String) {
+ setArtifactId((String) value);
+ } else {
+ throw new IllegalArgumentException("property \"artifactId\" is of type \"java.lang.String\", but got "+ value.getClass().toString());
+ }
+ }
+
+ public void callSetGroupId(Object value) {
+ if (value instanceof String) {
+ setGroupId((String) value);
+ } else {
+ throw new IllegalArgumentException("property \"groupId\" is of type \"java.lang.String\", but got "+ value.getClass().toString());
+ }
+ }
+ public void callSetVersion(Object value) {
+ if (value instanceof String) {
+ setVersion((String) value);
+ } else {
+ throw new IllegalArgumentException("property \"version\" is of type \"java.lang.String\", but got "+ value.getClass().toString());
+ }
+ }
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java
index 8d6f9bfd..c7a227b1 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java
@@ -201,25 +201,13 @@ public class PdpdConfiguration {
protected boolean declaredProperty(String name, Object value) {
switch (name) {
case "requestID":
- if (value instanceof String) {
- setRequestID((String) value);
- } else {
- throw new IllegalArgumentException(("property \"requestID\" is of type \"java.lang.String\", but got "+ value.getClass().toString()));
- }
+ callSetRequestId(value);
return true;
case "entity":
- if (value instanceof String) {
- setEntity((String) value);
- } else {
- throw new IllegalArgumentException(("property \"entity\" is of type \"java.lang.String\", but got "+ value.getClass().toString()));
- }
+ callSetEntity(value);
return true;
case "controllers":
- if (value instanceof List) {
- setControllers((List<ControllerConfiguration> ) value);
- } else {
- throw new IllegalArgumentException(("property \"controllers\" is of type \"java.util.List<org.onap.policy.drools.protocol.configuration.Controller>\", but got "+ value.getClass().toString()));
- }
+ callSetControllers(value);
return true;
default:
return false;
@@ -280,5 +268,28 @@ public class PdpdConfiguration {
PdpdConfiguration rhs = (PdpdConfiguration) other;
return new EqualsBuilder().append(requestID, rhs.requestID).append(entity, rhs.entity).append(controllers, rhs.controllers).append(additionalProperties, rhs.additionalProperties).isEquals();
}
+
+ public void callSetRequestId(Object value) {
+ if (value instanceof String) {
+ setRequestID((String) value);
+ } else {
+ throw new IllegalArgumentException("property \"requestID\" is of type \"java.lang.String\", but got "+ value.getClass().toString());
+ }
+ }
+
+ public void callSetEntity(Object value) {
+ if (value instanceof String) {
+ setEntity((String) value);
+ } else {
+ throw new IllegalArgumentException("property \"entity\" is of type \"java.lang.String\", but got "+ value.getClass().toString());
+ }
+ }
+ public void callSetControllers(Object value) {
+ if (value instanceof List) {
+ setControllers((List<ControllerConfiguration> ) value);
+ } else {
+ throw new IllegalArgumentException("property \"controllers\" is of type \"java.util.List<org.onap.policy.drools.protocol.configuration.Controller>\", but got "+ value.getClass().toString());
+ }
+ }
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java b/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java
index 93bdc0b2..25f378a7 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java
@@ -1507,15 +1507,15 @@ public class RestManager {
}
final CodingResult result = new CodingResult();
- result.decoding = false;
- result.encoding = false;
- result.jsonEncoding = null;
+ result.setDecoding(false);
+ result.setEncoding(false);
+ result.setJsonEncoding(null);
Object event;
try {
event = EventProtocolCoder.manager.decode(policyController.getDrools().getGroupId(),
policyController.getDrools().getArtifactId(), topic, json);
- result.decoding = true;
+ result.setDecoding(true);
} catch (final Exception e) {
logger.debug("{}: cannot get policy-controller {} topic {} because of {}", this,
controllerName, topic, e.getMessage(), e);
@@ -1523,8 +1523,8 @@ public class RestManager {
}
try {
- result.jsonEncoding = EventProtocolCoder.manager.encode(topic, event);
- result.encoding = true;
+ result.setJsonEncoding(EventProtocolCoder.manager.encode(topic, event));
+ result.setEncoding(true);
} catch (final Exception e) {
// continue so to propagate decoding results ..
logger.debug("{}: cannot encode for policy-controller {} topic {} because of {}", this,
@@ -1978,15 +1978,15 @@ public class RestManager {
@ApiOperation(value = "all active loggers", responseContainer = "List")
@ApiResponses(value = {@ApiResponse(code = 500, message = "logging misconfiguration")})
public Response loggers() {
- final List<String> names = new ArrayList<String>();
+ final List<String> names = new ArrayList<>();
if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) {
logger.warn("The SLF4J logger factory is not configured for logback");
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(names).build();
}
final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
- for (final Logger logger : context.getLoggerList()) {
- names.add(logger.getName());
+ for (final Logger lgr : context.getLoggerList()) {
+ names.add(lgr.getName());
}
return Response.status(Status.OK).entity(names).build();
@@ -2006,12 +2006,12 @@ public class RestManager {
}
final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
- final ch.qos.logback.classic.Logger logger = context.getLogger(loggerName);
- if (logger == null) {
+ final ch.qos.logback.classic.Logger lgr = context.getLogger(loggerName);
+ if (lgr == null) {
return Response.status(Status.NOT_FOUND).build();
}
- final String loggerLevel = (logger.getLevel() != null) ? logger.getLevel().toString() : "";
+ final String loggerLevel = (lgr.getLevel() != null) ? lgr.getLevel().toString() : "";
return Response.status(Status.OK).entity(loggerLevel).build();
}
@@ -2081,27 +2081,59 @@ public class RestManager {
* serialized output
*/
- public String jsonEncoding;
+ private String jsonEncoding;
/**
* encoding result
*/
- public Boolean encoding;
+ private Boolean encoding;
/**
* decoding result
*/
- public Boolean decoding;
+ private Boolean decoding;
+
+ public String getJsonEncoding() {
+ return jsonEncoding;
+ }
+
+ public void setJsonEncoding(String jsonEncoding) {
+ this.jsonEncoding = jsonEncoding;
+ }
+
+ public Boolean getEncoding() {
+ return encoding;
+ }
+
+ public void setEncoding(Boolean encoding) {
+ this.encoding = encoding;
+ }
+
+ public Boolean getDecoding() {
+ return decoding;
+ }
+
+ public void setDecoding(Boolean decoding) {
+ this.decoding = decoding;
+ }
}
/**
* Generic Error Reporting class
*/
public static class Error {
- public String error;
+ private String error;
public Error(String error) {
- this.error = error;
+ this.setError(error);
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public void setError(String error) {
+ this.error = error;
}
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/PolicyControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyControllerFactory.java
index d0b625d7..8c188c0b 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/system/PolicyControllerFactory.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyControllerFactory.java
@@ -349,18 +349,19 @@ class IndexedPolicyControllerFactory implements PolicyControllerFactory {
* @throws IllegalArgumentException
*/
protected void unmanage(PolicyController controller) throws IllegalArgumentException {
- if (controller == null) {
+ PolicyController tempController = controller;
+ if (tempController == null) {
throw new IllegalArgumentException("Invalid Controller");
}
synchronized(this) {
- if (!this.policyControllers.containsKey(controller.getName())) {
+ if (!this.policyControllers.containsKey(tempController.getName())) {
return;
}
- controller = this.policyControllers.remove(controller.getName());
+ tempController = this.policyControllers.remove(tempController.getName());
- String coordinates = toKey(controller.getDrools().getGroupId(),
- controller.getDrools().getArtifactId());
+ String coordinates = toKey(tempController.getDrools().getGroupId(),
+ tempController.getDrools().getArtifactId());
this.coordinates2Controller.remove(coordinates);
}
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngine.java b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngine.java
index 583deacc..c90d8bea 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngine.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngine.java
@@ -387,7 +387,7 @@ class PolicyEngineManager implements PolicyEngine {
/**
* Policy Engine HTTP Servers
*/
- protected List<HttpServletServer> httpServers = new ArrayList<HttpServletServer>();
+ protected List<HttpServletServer> httpServers = new ArrayList<>();
/**
* gson parser to decode configuration requests
@@ -459,7 +459,7 @@ class PolicyEngineManager implements PolicyEngine {
TELEMETRY_SERVER_DEFAULT_HOST);
defaultConfig.put(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
+ TELEMETRY_SERVER_DEFAULT_NAME + PolicyProperties.PROPERTY_HTTP_PORT_SUFFIX,
- "" + TELEMETRY_SERVER_DEFAULT_PORT);
+ "" + Integer.toString(TELEMETRY_SERVER_DEFAULT_PORT));
defaultConfig.put(
PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
+ PolicyProperties.PROPERTY_HTTP_REST_PACKAGES_SUFFIX,
@@ -534,24 +534,25 @@ class PolicyEngineManager implements PolicyEngine {
public synchronized PolicyController createPolicyController(String name, Properties properties)
throws IllegalArgumentException, IllegalStateException {
+ String tempName = name;
// check if a PROPERTY_CONTROLLER_NAME property is present
// if so, override the given name
final String propertyControllerName =
properties.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME);
if (propertyControllerName != null && !propertyControllerName.isEmpty()) {
- if (!propertyControllerName.equals(name)) {
- throw new IllegalStateException("Proposed name (" + name + ") and properties name ("
+ if (!propertyControllerName.equals(tempName)) {
+ throw new IllegalStateException("Proposed name (" + tempName + ") and properties name ("
+ propertyControllerName + ") don't match");
}
- name = propertyControllerName;
+ tempName = propertyControllerName;
}
PolicyController controller;
for (final PolicyControllerFeatureAPI controllerFeature : PolicyControllerFeatureAPI.providers
.getList()) {
try {
- controller = controllerFeature.beforeCreate(name, properties);
+ controller = controllerFeature.beforeCreate(tempName, properties);
if (controller != null)
return controller;
} catch (final Exception e) {
@@ -560,7 +561,7 @@ class PolicyEngineManager implements PolicyEngine {
}
}
- controller = PolicyController.factory.build(name, properties);
+ controller = PolicyController.factory.build(tempName, properties);
if (this.isLocked())
controller.lock();
@@ -589,22 +590,8 @@ class PolicyEngineManager implements PolicyEngine {
final String entity = config.getEntity();
switch (entity) {
- case PdpdConfiguration.CONFIG_ENTITY_CONTROLLER:
- /* only this one supported for now */
- final List<ControllerConfiguration> configControllers = config.getControllers();
- if (configControllers == null || configControllers.isEmpty()) {
- if (logger.isInfoEnabled())
- logger.info("No controller configuration provided: " + config);
- return false;
- }
- final List<PolicyController> policyControllers =
- this.updatePolicyControllers(config.getControllers());
- if (policyControllers == null || policyControllers.isEmpty())
- return false;
- else if (policyControllers.size() == configControllers.size())
- return true;
-
- return false;
+ case PdpdConfiguration.CONFIG_ENTITY_CONTROLLER:
+ return controllerConfig(config);
default:
final String msg = "Configuration Entity is not supported: " + entity;
logger.warn(msg);
@@ -617,7 +604,7 @@ class PolicyEngineManager implements PolicyEngine {
List<ControllerConfiguration> configControllers)
throws IllegalArgumentException, IllegalStateException {
- final List<PolicyController> policyControllers = new ArrayList<PolicyController>();
+ final List<PolicyController> policyControllers = new ArrayList<>();
if (configControllers == null || configControllers.isEmpty()) {
if (logger.isInfoEnabled())
logger.info("No controller configuration provided: " + configControllers);
@@ -677,14 +664,14 @@ class PolicyEngineManager implements PolicyEngine {
logger.warn("controller " + controllerName + " does not exist. "
+ "Attempting recovery from disk");
- final Properties properties =
+ final Properties controllerProperties =
SystemPersistence.manager.getControllerProperties(controllerName);
/*
* returned properties cannot be null (per implementation) assert (properties != null)
*/
- if (properties == null) {
+ if (controllerProperties == null) {
throw new IllegalArgumentException(controllerName + " is invalid");
}
@@ -695,11 +682,11 @@ class PolicyEngineManager implements PolicyEngine {
* try to bring up bad controller in brainless mode, after having it working, apply the new
* create/update operation.
*/
- properties.setProperty(PolicyProperties.RULES_GROUPID, DroolsController.NO_GROUP_ID);
- properties.setProperty(PolicyProperties.RULES_ARTIFACTID, DroolsController.NO_ARTIFACT_ID);
- properties.setProperty(PolicyProperties.RULES_VERSION, DroolsController.NO_VERSION);
+ controllerProperties.setProperty(PolicyProperties.RULES_GROUPID, DroolsController.NO_GROUP_ID);
+ controllerProperties.setProperty(PolicyProperties.RULES_ARTIFACTID, DroolsController.NO_ARTIFACT_ID);
+ controllerProperties.setProperty(PolicyProperties.RULES_VERSION, DroolsController.NO_VERSION);
- policyController = PolicyEngine.manager.createPolicyController(controllerName, properties);
+ policyController = PolicyEngine.manager.createPolicyController(controllerName, controllerProperties);
/* fall through to do brain update operation */
}
@@ -1140,7 +1127,7 @@ class PolicyEngineManager implements PolicyEngine {
@JsonProperty("controllers")
@Override
public List<String> getPolicyControllerIds() {
- final List<String> controllerNames = new ArrayList<String>();
+ final List<String> controllerNames = new ArrayList<>();
for (final PolicyController controller : PolicyController.factory.inventory()) {
controllerNames.add(controller.getName());
}
@@ -1173,7 +1160,7 @@ class PolicyEngineManager implements PolicyEngine {
@Override
public List<String> getFeatures() {
- final List<String> features = new ArrayList<String>();
+ final List<String> features = new ArrayList<>();
for (final PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) {
features.add(feature.getName());
}
@@ -1231,12 +1218,12 @@ class PolicyEngineManager implements PolicyEngine {
if (this.isLocked())
throw new IllegalStateException("Policy Engine is locked");
- final List<? extends TopicSink> sinks = TopicEndpoint.manager.getTopicSinks(topic);
- if (sinks == null || sinks.isEmpty() || sinks.size() > 1)
+ final List<? extends TopicSink> topicSinks = TopicEndpoint.manager.getTopicSinks(topic);
+ if (topicSinks == null || topicSinks.isEmpty() || topicSinks.size() > 1)
throw new IllegalStateException(
- "Cannot ensure correct delivery on topic " + topic + ": " + sinks);
+ "Cannot ensure correct delivery on topic " + topic + ": " + topicSinks);
- return this.deliver(sinks.get(0).getTopicCommInfrastructure(), topic, event);
+ return this.deliver(topicSinks.get(0).getTopicCommInfrastructure(), topic, event);
}
@Override
@@ -1417,10 +1404,7 @@ class PolicyEngineManager implements PolicyEngine {
for (final PolicyController policyController : this.getPolicyControllers()) {
try {
policyController.stop();
- } catch (final Exception e) {
- logger.error("{}: cannot deactivate (stop) policy-controller {} because of {}", this,
- policyController, e.getMessage(), e);
- } catch (final LinkageError e) {
+ } catch (final Exception | LinkageError e) {
logger.error("{}: cannot deactivate (stop) policy-controller {} because of {}", this,
policyController, e.getMessage(), e);
}
@@ -1437,6 +1421,24 @@ class PolicyEngineManager implements PolicyEngine {
}
}
}
+
+ public boolean controllerConfig(PdpdConfiguration config) {
+ /* only this one supported for now */
+ final List<ControllerConfiguration> configControllers = config.getControllers();
+ if (configControllers == null || configControllers.isEmpty()) {
+ if (logger.isInfoEnabled())
+ logger.info("No controller configuration provided: " + config);
+ return false;
+ }
+ final List<PolicyController> policyControllers =
+ this.updatePolicyControllers(config.getControllers());
+ if (policyControllers == null || policyControllers.isEmpty())
+ return false;
+ else if (policyControllers.size() == configControllers.size())
+ return true;
+
+ return false;
+ }
@Override
public String toString() {
diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java b/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java
index e67e542f..0645bdc5 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java
@@ -74,7 +74,7 @@ public class AggregatedPolicyController implements PolicyController,
*/
@JsonIgnore
protected final HashMap<String, TopicSink> topic2Sinks =
- new HashMap<String, TopicSink>();
+ new HashMap<>();
/**
* Is this Policy Controller running (alive) ?
diff --git a/pom.xml b/pom.xml
index 8e25b619..44ae9b8b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -77,6 +77,7 @@
<module>feature-state-management</module>
<module>api-active-standby-management</module>
<module>feature-active-standby-management</module>
+ <module>feature-simulators</module>
<module>packages</module>
</modules>