summaryrefslogtreecommitdiffstats
path: root/policy-management/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'policy-management/src/main/java')
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java333
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java359
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java10
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureApi.java (renamed from policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureAPI.java)6
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java (renamed from policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureAPI.java)6
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/features/PolicyEngineFeatureApi.java (renamed from policy-management/src/main/java/org/onap/policy/drools/features/PolicyEngineFeatureAPI.java)6
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java963
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolDecoder.java33
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolEncoder.java33
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GenericEventProtocolCoder.java712
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolset.java249
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoder.java278
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java224
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java46
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java12
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/system/IndexedPolicyControllerFactory.java387
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/system/PolicyControllerFactory.java376
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngine.java1300
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngineManager.java1321
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java42
20 files changed, 3447 insertions, 3249 deletions
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java
index f91e6dc4..b641f24a 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java
@@ -20,25 +20,11 @@
package org.onap.policy.drools.controller;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
import java.util.Properties;
-import org.onap.policy.common.endpoints.event.comm.Topic;
-import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
import org.onap.policy.common.endpoints.event.comm.TopicSink;
import org.onap.policy.common.endpoints.event.comm.TopicSource;
-import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
-import org.onap.policy.drools.controller.internal.MavenDroolsController;
-import org.onap.policy.drools.controller.internal.NullDroolsController;
-import org.onap.policy.drools.properties.DroolsProperties;
-import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
-import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder;
-import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Drools Controller Factory to manage controller creation, destruction, and retrieval for
@@ -120,322 +106,3 @@ public interface DroolsControllerFactory {
*/
public List<DroolsController> inventory();
}
-
-
-/* ---------------- implementation ----------------- */
-
-/**
- * Factory of Drools Controllers indexed by the Maven coordinates.
- */
-class IndexedDroolsControllerFactory implements DroolsControllerFactory {
-
- /**
- * logger.
- */
- private static Logger logger = LoggerFactory.getLogger(MavenDroolsController.class);
-
- /**
- * Policy Controller Name Index.
- */
- protected HashMap<String, DroolsController> droolsControllers = new HashMap<>();
-
- /**
- * Null Drools Controller.
- */
- protected NullDroolsController nullDroolsController = new NullDroolsController();
-
-
- public IndexedDroolsControllerFactory() {
-
- /* Add a NULL controller which will always be present in the hash */
-
- DroolsController controller = new NullDroolsController();
- String controllerId = controller.getGroupId() + ":" + controller.getArtifactId();
-
- synchronized (this) {
- droolsControllers.put(controllerId, controller);
- }
- }
-
- @Override
- public DroolsController build(Properties properties, List<? extends TopicSource> eventSources,
- List<? extends TopicSink> eventSinks) throws LinkageError {
-
- String groupId = properties.getProperty(DroolsProperties.RULES_GROUPID);
- if (groupId == null || groupId.isEmpty()) {
- groupId = DroolsController.NO_GROUP_ID;
- }
-
- String artifactId = properties.getProperty(DroolsProperties.RULES_ARTIFACTID);
- if (artifactId == null || artifactId.isEmpty()) {
- artifactId = DroolsController.NO_ARTIFACT_ID;
- }
-
- String version = properties.getProperty(DroolsProperties.RULES_VERSION);
- if (version == null || version.isEmpty()) {
- version = DroolsController.NO_VERSION;
- }
-
- List<TopicCoderFilterConfiguration> topics2DecodedClasses2Filters = codersAndFilters(properties, eventSources);
-
- List<TopicCoderFilterConfiguration> topics2EncodedClasses2Filters = codersAndFilters(properties, eventSinks);
-
- return this.build(groupId, artifactId, version, topics2DecodedClasses2Filters, topics2EncodedClasses2Filters);
- }
-
- @Override
- public DroolsController build(String newGroupId, String newArtifactId, String newVersion,
- List<TopicCoderFilterConfiguration> decoderConfigurations,
- List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError {
-
- if (newGroupId == null || newGroupId.isEmpty()) {
- throw new IllegalArgumentException("Missing maven group-id coordinate");
- }
-
- if (newArtifactId == null || newArtifactId.isEmpty()) {
- throw new IllegalArgumentException("Missing maven artifact-id coordinate");
- }
-
- if (newVersion == null || newVersion.isEmpty()) {
- throw new IllegalArgumentException("Missing maven version coordinate");
- }
-
- String controllerId = newGroupId + ":" + newArtifactId;
- DroolsController controllerCopy = null;
- synchronized (this) {
- /*
- * The Null Drools Controller for no maven coordinates is always here so when no
- * coordinates present, this is the return point
- *
- * assert (controllerCopy instanceof NullDroolsController)
- */
- if (droolsControllers.containsKey(controllerId)) {
- controllerCopy = droolsControllers.get(controllerId);
- if (controllerCopy.getVersion().equalsIgnoreCase(newVersion)) {
- return controllerCopy;
- }
- }
- }
-
- if (controllerCopy != null) {
- /*
- * a controller keyed by group id + artifact id exists but with different version =>
- * version upgrade/downgrade
- */
-
- controllerCopy.updateToVersion(newGroupId, newArtifactId, newVersion, decoderConfigurations,
- encoderConfigurations);
-
- return controllerCopy;
- }
-
- /* new drools controller */
-
- DroolsController controller = new MavenDroolsController(newGroupId, newArtifactId, newVersion,
- decoderConfigurations, encoderConfigurations);
-
- synchronized (this) {
- droolsControllers.put(controllerId, controller);
- }
-
- return controller;
- }
-
- /**
- * find out decoder classes and filters.
- *
- * @param properties properties with information about decoders
- * @param topicEntities topic sources
- * @return list of topics, each with associated decoder classes, each with a list of associated
- * filters
- * @throws IllegalArgumentException invalid input data
- */
- protected List<TopicCoderFilterConfiguration> codersAndFilters(Properties properties,
- List<? extends Topic> topicEntities) {
-
- String propertyTopicEntityPrefix;
-
- List<TopicCoderFilterConfiguration> topics2DecodedClasses2Filters = new ArrayList<>();
-
- if (topicEntities == null || topicEntities.isEmpty()) {
- return topics2DecodedClasses2Filters;
- }
-
- for (Topic topic : topicEntities) {
-
- /* source or sink ? ueb or dmaap? */
- boolean isSource = topic instanceof TopicSource;
- CommInfrastructure commInfra = topic.getTopicCommInfrastructure();
- if (commInfra == CommInfrastructure.UEB) {
- if (isSource) {
- propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_UEB_SOURCE_TOPICS + ".";
- } else {
- propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_UEB_SINK_TOPICS + ".";
- }
- } else if (commInfra == CommInfrastructure.DMAAP) {
- if (isSource) {
- propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_DMAAP_SOURCE_TOPICS + ".";
- } else {
- propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_DMAAP_SINK_TOPICS + ".";
- }
- } else if (commInfra == CommInfrastructure.NOOP) {
- if (isSource) {
- propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_NOOP_SOURCE_TOPICS + ".";
- } else {
- propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS + ".";
- }
- } else {
- throw new IllegalArgumentException("Invalid Communication Infrastructure: " + commInfra);
- }
-
- // 1. first the topic
-
- String firstTopic = topic.getTopic();
-
- // 2. check if there is a custom decoder for this topic that the user prefers to use
- // instead of the ones provided in the platform
-
- String customGson = properties.getProperty(propertyTopicEntityPrefix + firstTopic
- + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_GSON_SUFFIX);
-
- CustomGsonCoder customGsonCoder = null;
- if (customGson != null && !customGson.isEmpty()) {
- try {
- customGsonCoder = new CustomGsonCoder(customGson);
- } catch (IllegalArgumentException e) {
- logger.warn("{}: cannot create custom-gson-coder {} because of {}", this, customGson,
- e.getMessage(), e);
- }
- }
-
- // 3. second the list of classes associated with each topic
-
- String eventClasses = properties
- .getProperty(propertyTopicEntityPrefix + firstTopic
- + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX);
-
- if (eventClasses == null || eventClasses.isEmpty()) {
- logger.warn("There are no event classes for topic {}", firstTopic);
- continue;
- }
-
- List<PotentialCoderFilter> classes2Filters = new ArrayList<>();
-
- List<String> topicClasses = new ArrayList<>(Arrays.asList(eventClasses.split("\\s*,\\s*")));
-
- for (String theClass : topicClasses) {
-
-
- // 4. third, for each coder class, get the filter expression
-
- String filter = properties
- .getProperty(propertyTopicEntityPrefix + firstTopic
- + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX
- + "." + theClass + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX);
-
- JsonProtocolFilter protocolFilter = new JsonProtocolFilter(filter);
- PotentialCoderFilter class2Filters = new PotentialCoderFilter(theClass, protocolFilter);
- classes2Filters.add(class2Filters);
- }
-
- TopicCoderFilterConfiguration topic2Classes2Filters =
- new TopicCoderFilterConfiguration(firstTopic, classes2Filters, customGsonCoder);
- topics2DecodedClasses2Filters.add(topic2Classes2Filters);
- }
-
- return topics2DecodedClasses2Filters;
- }
-
- @Override
- public void destroy(DroolsController controller) {
- unmanage(controller);
- controller.halt();
- }
-
- @Override
- public void destroy() {
- List<DroolsController> controllers = this.inventory();
- for (DroolsController controller : controllers) {
- controller.halt();
- }
-
- synchronized (this) {
- this.droolsControllers.clear();
- }
- }
-
- /**
- * unmanage the drools controller.
- *
- * @param controller the controller
- */
- protected void unmanage(DroolsController controller) {
- if (controller == null) {
- throw new IllegalArgumentException("No controller provided");
- }
-
- if (!controller.isBrained()) {
- logger.info("Drools Controller is NOT OPERATIONAL - nothing to destroy");
- return;
- }
-
- String controllerId = controller.getGroupId() + ":" + controller.getArtifactId();
- synchronized (this) {
- if (!this.droolsControllers.containsKey(controllerId)) {
- return;
- }
-
- droolsControllers.remove(controllerId);
- }
- }
-
- @Override
- public void shutdown(DroolsController controller) {
- this.unmanage(controller);
- controller.shutdown();
- }
-
- @Override
- public void shutdown() {
- List<DroolsController> controllers = this.inventory();
- for (DroolsController controller : controllers) {
- controller.shutdown();
- }
-
- synchronized (this) {
- this.droolsControllers.clear();
- }
- }
-
- @Override
- public DroolsController get(String groupId, String artifactId, String version) {
-
- if (groupId == null || artifactId == null || groupId.isEmpty() || artifactId.isEmpty()) {
- throw new IllegalArgumentException("Missing maven coordinates: " + groupId + ":" + artifactId);
- }
-
- String controllerId = groupId + ":" + artifactId;
-
- synchronized (this) {
- if (this.droolsControllers.containsKey(controllerId)) {
- return droolsControllers.get(controllerId);
- } else {
- throw new IllegalStateException("DroolController for " + controllerId + " not found");
- }
- }
- }
-
- @Override
- public List<DroolsController> inventory() {
- return new ArrayList<>(this.droolsControllers.values());
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("IndexedDroolsControllerFactory [#droolsControllers=").append(droolsControllers.size())
- .append("]");
- return builder.toString();
- }
-
-}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java
new file mode 100644
index 00000000..89e2a1a8
--- /dev/null
+++ b/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java
@@ -0,0 +1,359 @@
+/*
+ * ============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.drools.controller;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+import org.onap.policy.common.endpoints.event.comm.Topic;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.event.comm.TopicSource;
+import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.drools.controller.internal.MavenDroolsController;
+import org.onap.policy.drools.controller.internal.NullDroolsController;
+import org.onap.policy.drools.properties.DroolsProperties;
+import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
+import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
+import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder;
+import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Factory of Drools Controllers indexed by the Maven coordinates.
+ */
+class IndexedDroolsControllerFactory implements DroolsControllerFactory {
+
+ /**
+ * logger.
+ */
+ private static Logger logger = LoggerFactory.getLogger(MavenDroolsController.class);
+
+ /**
+ * Policy Controller Name Index.
+ */
+ protected HashMap<String, DroolsController> droolsControllers = new HashMap<>();
+
+ /**
+ * Null Drools Controller.
+ */
+ protected NullDroolsController nullDroolsController = new NullDroolsController();
+
+ /**
+ * Constructs the object.
+ */
+ public IndexedDroolsControllerFactory() {
+
+ /* Add a NULL controller which will always be present in the hash */
+
+ DroolsController controller = new NullDroolsController();
+ String controllerId = controller.getGroupId() + ":" + controller.getArtifactId();
+
+ synchronized (this) {
+ droolsControllers.put(controllerId, controller);
+ }
+ }
+
+ @Override
+ public DroolsController build(Properties properties, List<? extends TopicSource> eventSources,
+ List<? extends TopicSink> eventSinks) throws LinkageError {
+
+ String groupId = properties.getProperty(DroolsProperties.RULES_GROUPID);
+ if (groupId == null || groupId.isEmpty()) {
+ groupId = DroolsController.NO_GROUP_ID;
+ }
+
+ String artifactId = properties.getProperty(DroolsProperties.RULES_ARTIFACTID);
+ if (artifactId == null || artifactId.isEmpty()) {
+ artifactId = DroolsController.NO_ARTIFACT_ID;
+ }
+
+ String version = properties.getProperty(DroolsProperties.RULES_VERSION);
+ if (version == null || version.isEmpty()) {
+ version = DroolsController.NO_VERSION;
+ }
+
+ List<TopicCoderFilterConfiguration> topics2DecodedClasses2Filters = codersAndFilters(properties, eventSources);
+
+ List<TopicCoderFilterConfiguration> topics2EncodedClasses2Filters = codersAndFilters(properties, eventSinks);
+
+ return this.build(groupId, artifactId, version, topics2DecodedClasses2Filters, topics2EncodedClasses2Filters);
+ }
+
+ @Override
+ public DroolsController build(String newGroupId, String newArtifactId, String newVersion,
+ List<TopicCoderFilterConfiguration> decoderConfigurations,
+ List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError {
+
+ if (newGroupId == null || newGroupId.isEmpty()) {
+ throw new IllegalArgumentException("Missing maven group-id coordinate");
+ }
+
+ if (newArtifactId == null || newArtifactId.isEmpty()) {
+ throw new IllegalArgumentException("Missing maven artifact-id coordinate");
+ }
+
+ if (newVersion == null || newVersion.isEmpty()) {
+ throw new IllegalArgumentException("Missing maven version coordinate");
+ }
+
+ String controllerId = newGroupId + ":" + newArtifactId;
+ DroolsController controllerCopy = null;
+ synchronized (this) {
+ /*
+ * The Null Drools Controller for no maven coordinates is always here so when no
+ * coordinates present, this is the return point
+ *
+ * assert (controllerCopy instanceof NullDroolsController)
+ */
+ if (droolsControllers.containsKey(controllerId)) {
+ controllerCopy = droolsControllers.get(controllerId);
+ if (controllerCopy.getVersion().equalsIgnoreCase(newVersion)) {
+ return controllerCopy;
+ }
+ }
+ }
+
+ if (controllerCopy != null) {
+ /*
+ * a controller keyed by group id + artifact id exists but with different version =>
+ * version upgrade/downgrade
+ */
+
+ controllerCopy.updateToVersion(newGroupId, newArtifactId, newVersion, decoderConfigurations,
+ encoderConfigurations);
+
+ return controllerCopy;
+ }
+
+ /* new drools controller */
+
+ DroolsController controller = new MavenDroolsController(newGroupId, newArtifactId, newVersion,
+ decoderConfigurations, encoderConfigurations);
+
+ synchronized (this) {
+ droolsControllers.put(controllerId, controller);
+ }
+
+ return controller;
+ }
+
+ /**
+ * find out decoder classes and filters.
+ *
+ * @param properties properties with information about decoders
+ * @param topicEntities topic sources
+ * @return list of topics, each with associated decoder classes, each with a list of associated
+ * filters
+ * @throws IllegalArgumentException invalid input data
+ */
+ protected List<TopicCoderFilterConfiguration> codersAndFilters(Properties properties,
+ List<? extends Topic> topicEntities) {
+
+ String propertyTopicEntityPrefix;
+
+ List<TopicCoderFilterConfiguration> topics2DecodedClasses2Filters = new ArrayList<>();
+
+ if (topicEntities == null || topicEntities.isEmpty()) {
+ return topics2DecodedClasses2Filters;
+ }
+
+ for (Topic topic : topicEntities) {
+
+ /* source or sink ? ueb or dmaap? */
+ boolean isSource = topic instanceof TopicSource;
+ CommInfrastructure commInfra = topic.getTopicCommInfrastructure();
+ if (commInfra == CommInfrastructure.UEB) {
+ if (isSource) {
+ propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_UEB_SOURCE_TOPICS + ".";
+ } else {
+ propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_UEB_SINK_TOPICS + ".";
+ }
+ } else if (commInfra == CommInfrastructure.DMAAP) {
+ if (isSource) {
+ propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_DMAAP_SOURCE_TOPICS + ".";
+ } else {
+ propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_DMAAP_SINK_TOPICS + ".";
+ }
+ } else if (commInfra == CommInfrastructure.NOOP) {
+ if (isSource) {
+ propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_NOOP_SOURCE_TOPICS + ".";
+ } else {
+ propertyTopicEntityPrefix = PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS + ".";
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid Communication Infrastructure: " + commInfra);
+ }
+
+ // 1. first the topic
+
+ String firstTopic = topic.getTopic();
+
+ // 2. check if there is a custom decoder for this topic that the user prefers to use
+ // instead of the ones provided in the platform
+
+ String customGson = properties.getProperty(propertyTopicEntityPrefix + firstTopic
+ + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_GSON_SUFFIX);
+
+ CustomGsonCoder customGsonCoder = null;
+ if (customGson != null && !customGson.isEmpty()) {
+ try {
+ customGsonCoder = new CustomGsonCoder(customGson);
+ } catch (IllegalArgumentException e) {
+ logger.warn("{}: cannot create custom-gson-coder {} because of {}", this, customGson,
+ e.getMessage(), e);
+ }
+ }
+
+ // 3. second the list of classes associated with each topic
+
+ String eventClasses = properties
+ .getProperty(propertyTopicEntityPrefix + firstTopic
+ + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX);
+
+ if (eventClasses == null || eventClasses.isEmpty()) {
+ logger.warn("There are no event classes for topic {}", firstTopic);
+ continue;
+ }
+
+ List<PotentialCoderFilter> classes2Filters = new ArrayList<>();
+
+ List<String> topicClasses = new ArrayList<>(Arrays.asList(eventClasses.split("\\s*,\\s*")));
+
+ for (String theClass : topicClasses) {
+
+
+ // 4. third, for each coder class, get the filter expression
+
+ String filter = properties
+ .getProperty(propertyTopicEntityPrefix + firstTopic
+ + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX
+ + "." + theClass + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX);
+
+ JsonProtocolFilter protocolFilter = new JsonProtocolFilter(filter);
+ PotentialCoderFilter class2Filters = new PotentialCoderFilter(theClass, protocolFilter);
+ classes2Filters.add(class2Filters);
+ }
+
+ TopicCoderFilterConfiguration topic2Classes2Filters =
+ new TopicCoderFilterConfiguration(firstTopic, classes2Filters, customGsonCoder);
+ topics2DecodedClasses2Filters.add(topic2Classes2Filters);
+ }
+
+ return topics2DecodedClasses2Filters;
+ }
+
+ @Override
+ public void destroy(DroolsController controller) {
+ unmanage(controller);
+ controller.halt();
+ }
+
+ @Override
+ public void destroy() {
+ List<DroolsController> controllers = this.inventory();
+ for (DroolsController controller : controllers) {
+ controller.halt();
+ }
+
+ synchronized (this) {
+ this.droolsControllers.clear();
+ }
+ }
+
+ /**
+ * unmanage the drools controller.
+ *
+ * @param controller the controller
+ */
+ protected void unmanage(DroolsController controller) {
+ if (controller == null) {
+ throw new IllegalArgumentException("No controller provided");
+ }
+
+ if (!controller.isBrained()) {
+ logger.info("Drools Controller is NOT OPERATIONAL - nothing to destroy");
+ return;
+ }
+
+ String controllerId = controller.getGroupId() + ":" + controller.getArtifactId();
+ synchronized (this) {
+ if (!this.droolsControllers.containsKey(controllerId)) {
+ return;
+ }
+
+ droolsControllers.remove(controllerId);
+ }
+ }
+
+ @Override
+ public void shutdown(DroolsController controller) {
+ this.unmanage(controller);
+ controller.shutdown();
+ }
+
+ @Override
+ public void shutdown() {
+ List<DroolsController> controllers = this.inventory();
+ for (DroolsController controller : controllers) {
+ controller.shutdown();
+ }
+
+ synchronized (this) {
+ this.droolsControllers.clear();
+ }
+ }
+
+ @Override
+ public DroolsController get(String groupId, String artifactId, String version) {
+
+ if (groupId == null || artifactId == null || groupId.isEmpty() || artifactId.isEmpty()) {
+ throw new IllegalArgumentException("Missing maven coordinates: " + groupId + ":" + artifactId);
+ }
+
+ String controllerId = groupId + ":" + artifactId;
+
+ synchronized (this) {
+ if (this.droolsControllers.containsKey(controllerId)) {
+ return droolsControllers.get(controllerId);
+ } else {
+ throw new IllegalStateException("DroolController for " + controllerId + " not found");
+ }
+ }
+ }
+
+ @Override
+ public List<DroolsController> inventory() {
+ return new ArrayList<>(this.droolsControllers.values());
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("IndexedDroolsControllerFactory [#droolsControllers=").append(droolsControllers.size())
+ .append("]");
+ return builder.toString();
+ }
+
+}
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 97312042..d0b98450 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
@@ -45,7 +45,7 @@ import org.onap.policy.drools.controller.DroolsController;
import org.onap.policy.drools.core.PolicyContainer;
import org.onap.policy.drools.core.PolicySession;
import org.onap.policy.drools.core.jmx.PdpJmx;
-import org.onap.policy.drools.features.DroolsControllerFeatureAPI;
+import org.onap.policy.drools.features.DroolsControllerFeatureApi;
import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
import org.onap.policy.drools.protocol.coders.EventProtocolParams;
import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
@@ -538,7 +538,7 @@ public class MavenDroolsController implements DroolsController {
// Broadcast
- for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
+ for (DroolsControllerFeatureApi feature : DroolsControllerFeatureApi.providers.getList()) {
try {
if (feature.beforeInsert(this, event)) {
return true;
@@ -554,7 +554,7 @@ public class MavenDroolsController implements DroolsController {
logger.warn(this + "Failed to inject into PolicyContainer {}", this.getSessionNames());
}
- for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
+ for (DroolsControllerFeatureApi feature : DroolsControllerFeatureApi.providers.getList()) {
try {
if (feature.afterInsert(this, event, successInject)) {
return true;
@@ -576,7 +576,7 @@ public class MavenDroolsController implements DroolsController {
logger.info("{}DELIVER: {} FROM {} TO {}", this, event, this, sink);
}
- for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
+ for (DroolsControllerFeatureApi feature : DroolsControllerFeatureApi.providers.getList()) {
try {
if (feature.beforeDeliver(this, sink, event)) {
return true;
@@ -613,7 +613,7 @@ public class MavenDroolsController implements DroolsController {
boolean success = sink.send(json);
- for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
+ for (DroolsControllerFeatureApi feature : DroolsControllerFeatureApi.providers.getList()) {
try {
if (feature.afterDeliver(this, sink, event, json, success)) {
return true;
diff --git a/policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureAPI.java b/policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureApi.java
index d11bd145..d5a16a12 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureAPI.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureApi.java
@@ -28,7 +28,7 @@ import org.onap.policy.drools.controller.DroolsController;
/**
* Drools Controller Feature API. Hooks into the Drools Controller operations.
*/
-public interface DroolsControllerFeatureAPI extends OrderedService {
+public interface DroolsControllerFeatureApi extends OrderedService {
/**
* intercepts before the Drools Controller gives the Policy Container a fact to
@@ -78,6 +78,6 @@ public interface DroolsControllerFeatureAPI extends OrderedService {
/**
* Feature providers implementing this interface.
*/
- public static final OrderedServiceImpl<DroolsControllerFeatureAPI> providers =
- new OrderedServiceImpl<>(DroolsControllerFeatureAPI.class);
+ public static final OrderedServiceImpl<DroolsControllerFeatureApi> providers =
+ new OrderedServiceImpl<>(DroolsControllerFeatureApi.class);
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureAPI.java b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java
index 914b073f..c9e78c6a 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureAPI.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java
@@ -26,13 +26,13 @@ import org.onap.policy.common.utils.services.OrderedService;
import org.onap.policy.common.utils.services.OrderedServiceImpl;
import org.onap.policy.drools.system.PolicyController;
-public interface PolicyControllerFeatureAPI extends OrderedService {
+public interface PolicyControllerFeatureApi extends OrderedService {
/**
* Feature providers implementing this interface.
*/
- OrderedServiceImpl<PolicyControllerFeatureAPI> providers =
- new OrderedServiceImpl<>(PolicyControllerFeatureAPI.class);
+ OrderedServiceImpl<PolicyControllerFeatureApi> providers =
+ new OrderedServiceImpl<>(PolicyControllerFeatureApi.class);
/**
* called before creating a controller with name 'name' and
diff --git a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyEngineFeatureAPI.java b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyEngineFeatureApi.java
index 9b099909..bd834c4d 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyEngineFeatureAPI.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyEngineFeatureApi.java
@@ -31,12 +31,12 @@ import org.onap.policy.drools.system.PolicyEngine;
* Policy Engine Feature API.
* Provides Interception Points during the Policy Engine lifecycle.
*/
-public interface PolicyEngineFeatureAPI extends OrderedService {
+public interface PolicyEngineFeatureApi extends OrderedService {
/**
* Feature providers implementing this interface.
*/
- public static final OrderedServiceImpl<PolicyEngineFeatureAPI> providers =
- new OrderedServiceImpl<>(PolicyEngineFeatureAPI.class);
+ public static final OrderedServiceImpl<PolicyEngineFeatureApi> providers =
+ new OrderedServiceImpl<>(PolicyEngineFeatureApi.class);
/**
* intercept before the Policy Engine is commanded to boot.
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java
index 1297ff8c..62a0cbe2 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java
@@ -21,15 +21,8 @@
package org.onap.policy.drools.protocol.coders;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Coder (Encoder/Decoder) of Events.
@@ -349,959 +342,3 @@ public interface EventProtocolCoder {
*/
public String encode(String topic, Object event, DroolsController droolsController);
}
-
-/**
- * Protocol Coder that does its best attempt to decode/encode, selecting the best class and best fitted json parsing
- * tools.
- */
-class MultiplexorEventProtocolCoder implements EventProtocolCoder {
-
- /**
- * Logger.
- */
- private static Logger logger = LoggerFactory.getLogger(MultiplexorEventProtocolCoder.class);
-
- /**
- * Decoders.
- */
- protected EventProtocolDecoder decoders = new EventProtocolDecoder();
-
- /**
- * Encoders.
- */
- protected EventProtocolEncoder encoders = new EventProtocolEncoder();
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public void addDecoder(EventProtocolParams eventProtocolParams) {
- logger.info(
- "{}: add-decoder {}:{}:{}:{}:{}:{}:{}",
- this,
- eventProtocolParams.getGroupId(),
- eventProtocolParams.getArtifactId(),
- eventProtocolParams.getTopic(),
- eventProtocolParams.getEventClass(),
- eventProtocolParams.getProtocolFilter(),
- eventProtocolParams.getCustomGsonCoder(),
- eventProtocolParams.getModelClassLoaderHash());
- this.decoders.add(eventProtocolParams);
- }
-
- /**
- * {@inheritDoc}.
- *
- * @param eventProtocolParams parameter object for event encoder
- */
- @Override
- public void addEncoder(EventProtocolParams eventProtocolParams) {
- logger.info(
- "{}: add-decoder {}:{}:{}:{}:{}:{}:{}",
- this,
- eventProtocolParams.getGroupId(),
- eventProtocolParams.getArtifactId(),
- eventProtocolParams.getTopic(),
- eventProtocolParams.getEventClass(),
- eventProtocolParams.getProtocolFilter(),
- eventProtocolParams.getCustomGsonCoder(),
- eventProtocolParams.getModelClassLoaderHash());
- this.encoders.add(eventProtocolParams);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public void removeDecoders(String groupId, String artifactId, String topic) {
- logger.info("{}: remove-decoder {}:{}:{}", this, groupId, artifactId, topic);
- this.decoders.remove(groupId, artifactId, topic);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public void removeEncoders(String groupId, String artifactId, String topic) {
- logger.info("{}: remove-encoder {}:{}:{}", this, groupId, artifactId, topic);
- this.encoders.remove(groupId, artifactId, topic);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public boolean isDecodingSupported(String groupId, String artifactId, String topic) {
- return this.decoders.isCodingSupported(groupId, artifactId, topic);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public boolean isEncodingSupported(String groupId, String artifactId, String topic) {
- return this.encoders.isCodingSupported(groupId, artifactId, topic);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public Object decode(String groupId, String artifactId, String topic, String json) {
- logger.debug("{}: decode {}:{}:{}:{}", this, groupId, artifactId, topic, json);
- return this.decoders.decode(groupId, artifactId, topic, json);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public String encode(String groupId, String artifactId, String topic, Object event) {
- logger.debug("{}: encode {}:{}:{}:{}", this, groupId, artifactId, topic, event);
- return this.encoders.encode(groupId, artifactId, topic, event);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public String encode(String topic, Object event) {
- logger.debug("{}: encode {}:{}", this, topic, event);
- return this.encoders.encode(topic, event);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public String encode(String topic, Object event, DroolsController droolsController) {
- logger.debug("{}: encode {}:{}:{}", this, topic, event, droolsController);
- return this.encoders.encode(topic, event, droolsController);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic) {
- return this.decoders.getFilters(groupId, artifactId, topic);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public CoderFilters getDecoderFilters(
- String groupId, String artifactId, String topic, String classname) {
- return this.decoders.getFilters(groupId, artifactId, topic, classname);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public List<CoderFilters> getDecoderFilters(String groupId, String artifactId) {
- return this.decoders.getFilters(groupId, artifactId);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) {
- ProtocolCoderToolset decoderToolsets =
- this.decoders.getCoders(groupId, artifactId, topic);
- if (decoderToolsets == null) {
- throw new IllegalArgumentException(
- "Decoders not found for " + groupId + ":" + artifactId + ":" + topic);
- }
-
- return decoderToolsets;
- }
-
- /**
- * get all deocders by maven coordinates and topic.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @return list of decoders
- * @throws IllegalArgumentException if invalid input
- */
- @Override
- public List<ProtocolCoderToolset> getDecoders(String groupId, String artifactId) {
-
- List<ProtocolCoderToolset> decoderToolsets =
- this.decoders.getCoders(groupId, artifactId);
- if (decoderToolsets == null) {
- throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId);
- }
-
- return new ArrayList<>(decoderToolsets);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic) {
- return this.encoders.getFilters(groupId, artifactId, topic);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public CoderFilters getEncoderFilters(
- String groupId, String artifactId, String topic, String classname) {
- return this.encoders.getFilters(groupId, artifactId, topic, classname);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public List<CoderFilters> getEncoderFilters(String groupId, String artifactId) {
- return this.encoders.getFilters(groupId, artifactId);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass) {
- return this.encoders.getReverseFilters(topic, encodedClass);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public DroolsController getDroolsController(String topic, Object encodedClass) {
- return this.encoders.getDroolsController(topic, encodedClass);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public List<DroolsController> getDroolsControllers(String topic, Object encodedClass) {
- return this.encoders.getDroolsControllers(topic, encodedClass);
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public String toString() {
- return "MultiplexorEventProtocolCoder [decoders="
- + decoders
- + ", encoders="
- + encoders
- + "]";
- }
-}
-
-/**
- * This protocol Coder that does its best attempt to decode/encode, selecting the best class and best fitted json
- * parsing tools.
- */
-abstract class GenericEventProtocolCoder {
-
- private static final String INVALID_ARTIFACT_ID_MSG = "Invalid artifact id";
-
- private static final String INVALID_GROUP_ID_MSG = "Invalid group id";
-
- private static final String INVALID_TOPIC_MSG = "Invalid Topic";
-
- private static final String UNSUPPORTED_MSG = "Unsupported";
-
- private static final String MISSING_CLASS = "class must be provided";
-
- private static Logger logger = LoggerFactory.getLogger(GenericEventProtocolCoder.class);
-
- /**
- * Mapping topic:controller-id -> /<protocol-decoder-toolset/> where protocol-coder-toolset contains
- * a gson-protocol-coder-toolset.
- */
- protected final HashMap<String, ProtocolCoderToolset> coders =
- new HashMap<>();
-
- /**
- * Mapping topic + classname -> Protocol Set.
- */
- protected final HashMap<String, List<ProtocolCoderToolset>>
- reverseCoders = new HashMap<>();
-
- GenericEventProtocolCoder() {
- super();
- }
-
- /**
- * Index a new coder.
- *
- * @param eventProtocolParams parameter object for event encoder
- * @throw IllegalArgumentException if an invalid parameter is passed
- */
- public void add(EventProtocolParams eventProtocolParams) {
- if (eventProtocolParams.getGroupId() == null || eventProtocolParams.getGroupId().isEmpty()) {
- throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
- }
-
- if (eventProtocolParams.getArtifactId() == null || eventProtocolParams.getArtifactId().isEmpty()) {
- throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
- }
-
- if (eventProtocolParams.getTopic() == null || eventProtocolParams.getTopic().isEmpty()) {
- throw new IllegalArgumentException(INVALID_TOPIC_MSG);
- }
-
- if (eventProtocolParams.getEventClass() == null) {
- throw new IllegalArgumentException("Invalid Event Class");
- }
-
- String key = this.codersKey(eventProtocolParams.getGroupId(), eventProtocolParams.getArtifactId(),
- eventProtocolParams.getTopic());
- String reverseKey = this.reverseCodersKey(eventProtocolParams.getTopic(), eventProtocolParams.getEventClass());
-
- synchronized (this) {
- if (coders.containsKey(key)) {
- ProtocolCoderToolset toolset = coders.get(key);
-
- logger.info("{}: adding coders for existing {}: {}", this, key, toolset);
-
- toolset
- .addCoder(
- eventProtocolParams.getEventClass(),
- eventProtocolParams.getProtocolFilter(),
- eventProtocolParams.getModelClassLoaderHash());
-
- if (!reverseCoders.containsKey(reverseKey)) {
- logger.info(
- "{}: adding new reverse coders (multiple classes case) for {}:{}: {}",
- this,
- reverseKey,
- key,
- toolset);
-
- List<ProtocolCoderToolset> reverseMappings =
- new ArrayList<>();
- reverseMappings.add(toolset);
- reverseCoders.put(reverseKey, reverseMappings);
- }
- return;
- }
-
- GsonProtocolCoderToolset coderTools =
- new GsonProtocolCoderToolset(eventProtocolParams, key);
-
- logger.info("{}: adding coders for new {}: {}", this, key, coderTools);
-
- coders.put(key, coderTools);
-
- if (reverseCoders.containsKey(reverseKey)) {
- // There is another controller (different group id/artifact id/topic)
- // that shares the class and the topic.
-
- List<ProtocolCoderToolset> toolsets =
- reverseCoders.get(reverseKey);
- boolean present = false;
- for (ProtocolCoderToolset parserSet : toolsets) {
- // just doublecheck
- present = parserSet.getControllerId().equals(key);
- if (present) {
- /* anomaly */
- logger.error(
- "{}: unexpected toolset reverse mapping found for {}:{}: {}",
- this,
- reverseKey,
- key,
- parserSet);
- }
- }
-
- if (present) {
- return;
- } else {
- logger.info("{}: adding coder set for {}: {} ", this, reverseKey, coderTools);
- toolsets.add(coderTools);
- }
- } else {
- List<ProtocolCoderToolset> toolsets = new ArrayList<>();
- toolsets.add(coderTools);
-
- logger.info("{}: adding toolset for reverse key {}: {}", this, reverseKey, toolsets);
- reverseCoders.put(reverseKey, toolsets);
- }
- }
- }
-
- /**
- * produces key for indexing toolset entries.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @param topic topic
- * @return index key
- */
- protected String codersKey(String groupId, String artifactId, String topic) {
- return groupId + ":" + artifactId + ":" + topic;
- }
-
- /**
- * produces a key for the reverse index.
- *
- * @param topic topic
- * @param eventClass coded class
- * @return reverse index key
- */
- protected String reverseCodersKey(String topic, String eventClass) {
- return topic + ":" + eventClass;
- }
-
- /**
- * remove coder.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @param topic topic
- * @throws IllegalArgumentException if invalid input
- */
- public void remove(String groupId, String artifactId, String topic) {
-
- if (groupId == null || groupId.isEmpty()) {
- throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
- }
-
- if (artifactId == null || artifactId.isEmpty()) {
- throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
- }
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException(INVALID_TOPIC_MSG);
- }
-
- String key = this.codersKey(groupId, artifactId, topic);
-
- synchronized (this) {
- if (coders.containsKey(key)) {
- ProtocolCoderToolset coderToolset = coders.remove(key);
-
- logger.info("{}: removed toolset for {}: {}", this, key, coderToolset);
-
- for (CoderFilters codeFilter : coderToolset.getCoders()) {
- String className = codeFilter.getCodedClass();
- String reverseKey = this.reverseCodersKey(topic, className);
- if (this.reverseCoders.containsKey(reverseKey)) {
- List<ProtocolCoderToolset> toolsets =
- this.reverseCoders.get(reverseKey);
- Iterator<ProtocolCoderToolset> toolsetsIter =
- toolsets.iterator();
- while (toolsetsIter.hasNext()) {
- ProtocolCoderToolset toolset = toolsetsIter.next();
- if (toolset.getControllerId().equals(key)) {
- logger.info(
- "{}: removed coder from toolset for {} from reverse mapping", this, reverseKey);
- toolsetsIter.remove();
- }
- }
-
- if (this.reverseCoders.get(reverseKey).isEmpty()) {
- logger.info("{}: removing reverse mapping for {}: ", this, reverseKey);
- this.reverseCoders.remove(reverseKey);
- }
- }
- }
- }
- }
- }
-
- /**
- * does it support coding.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @param topic topic
- * @return true if its is codable
- */
- public boolean isCodingSupported(String groupId, String artifactId, String topic) {
-
- if (groupId == null || groupId.isEmpty()) {
- throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
- }
-
- if (artifactId == null || artifactId.isEmpty()) {
- throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
- }
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException(INVALID_TOPIC_MSG);
- }
-
- String key = this.codersKey(groupId, artifactId, topic);
- synchronized (this) {
- return coders.containsKey(key);
- }
- }
-
- /**
- * decode a json string into an Object.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @param topic topic
- * @param json json string to convert to object
- * @return the decoded object
- * @throws IllegalArgumentException if invalid argument is provided
- * @throws UnsupportedOperationException if the operation cannot be performed
- */
- public Object decode(String groupId, String artifactId, String topic, String json) {
-
- if (!isCodingSupported(groupId, artifactId, topic)) {
- throw new IllegalArgumentException(
- "Unsupported:" + codersKey(groupId, artifactId, topic) + " for encoding");
- }
-
- String key = this.codersKey(groupId, artifactId, topic);
- ProtocolCoderToolset coderTools = coders.get(key);
- try {
- Object event = coderTools.decode(json);
- if (event != null) {
- return event;
- }
- } catch (Exception e) {
- logger.debug("{}, cannot decode {}", this, json, e);
- }
-
- throw new UnsupportedOperationException("Cannot decode with gson");
- }
-
- /**
- * encode an object into a json string.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @param topic topic
- * @param event object to convert to string
- * @return the json string
- * @throws IllegalArgumentException if invalid argument is provided
- * @throws UnsupportedOperationException if the operation cannot be performed
- */
- public String encode(String groupId, String artifactId, String topic, Object event) {
-
- if (!isCodingSupported(groupId, artifactId, topic)) {
- throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
- }
-
- if (event == null) {
- throw new IllegalArgumentException("Unsupported topic:" + topic);
- }
-
- // reuse the decoder set, since there must be affinity in the model
- String key = this.codersKey(groupId, artifactId, topic);
- return this.encodeInternal(key, event);
- }
-
- /**
- * encode an object into a json string.
- *
- * @param topic topic
- * @param event object to convert to string
- * @return the json string
- * @throws IllegalArgumentException if invalid argument is provided
- * @throws UnsupportedOperationException if the operation cannot be performed
- */
- public String encode(String topic, Object event) {
-
- if (event == null) {
- throw new IllegalArgumentException("Invalid encoded class");
- }
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException("Invalid topic");
- }
-
- String reverseKey = this.reverseCodersKey(topic, event.getClass().getName());
- if (!this.reverseCoders.containsKey(reverseKey)) {
- throw new IllegalArgumentException("no reverse coder has been found");
- }
-
- List<ProtocolCoderToolset> toolsets =
- this.reverseCoders.get(reverseKey);
-
- String key =
- codersKey(
- toolsets.get(0).getGroupId(), toolsets.get(0).getArtifactId(), topic);
- return this.encodeInternal(key, event);
- }
-
- /**
- * encode an object into a json string.
- *
- * @param topic topic
- * @param encodedClass object to convert to string
- * @return the json string
- * @throws IllegalArgumentException if invalid argument is provided
- * @throws UnsupportedOperationException if the operation cannot be performed
- */
- public String encode(String topic, Object encodedClass, DroolsController droolsController) {
-
- if (encodedClass == null) {
- throw new IllegalArgumentException("Invalid encoded class");
- }
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException("Invalid topic");
- }
-
- String key = codersKey(droolsController.getGroupId(), droolsController.getArtifactId(), topic);
- return this.encodeInternal(key, encodedClass);
- }
-
- /**
- * encode an object into a json string.
- *
- * @param key identifier
- * @param event object to convert to string
- * @return the json string
- * @throws IllegalArgumentException if invalid argument is provided
- * @throws UnsupportedOperationException if the operation cannot be performed
- */
- protected String encodeInternal(String key, Object event) {
-
- logger.debug("{}: encode for {}: {}", this, key, event);
-
- ProtocolCoderToolset coderTools = coders.get(key);
- try {
- String json = coderTools.encode(event);
- if (json != null && !json.isEmpty()) {
- return json;
- }
- } catch (Exception e) {
- logger.warn("{}: cannot encode (first) for {}: {}", this, key, event, e);
- }
-
- throw new UnsupportedOperationException("Cannot decode with gson");
- }
-
- /**
- * Drools creators.
- *
- * @param topic topic
- * @param encodedClass encoded class
- * @return list of controllers
- * @throws IllegalStateException illegal state
- * @throws IllegalArgumentException argument
- */
- protected List<DroolsController> droolsCreators(String topic, Object encodedClass) {
-
- List<DroolsController> droolsControllers = new ArrayList<>();
-
- String reverseKey = this.reverseCodersKey(topic, encodedClass.getClass().getName());
- if (!this.reverseCoders.containsKey(reverseKey)) {
- logger.warn("{}: no reverse mapping for {}", this, reverseKey);
- return droolsControllers;
- }
-
- List<ProtocolCoderToolset> toolsets =
- this.reverseCoders.get(reverseKey);
-
- // There must be multiple toolsets associated with <topic,classname> reverseKey
- // case 2 different controllers use the same models and register the same encoder for
- // the same topic. This is assumed not to occur often but for the purpose of encoding
- // but there should be no side-effects. Ownership is crosscheck against classname and
- // classloader reference.
-
- if (toolsets == null || toolsets.isEmpty()) {
- throw new IllegalStateException(
- "No Encoders toolsets available for topic "
- + topic
- + " encoder "
- + encodedClass.getClass().getName());
- }
-
- for (ProtocolCoderToolset encoderSet : toolsets) {
- // figure out the right toolset
- String groupId = encoderSet.getGroupId();
- String artifactId = encoderSet.getArtifactId();
- List<CoderFilters> coderFilters = encoderSet.getCoders();
- for (CoderFilters coder : coderFilters) {
- if (coder.getCodedClass().equals(encodedClass.getClass().getName())) {
- DroolsController droolsController = DroolsController.factory.get(groupId, artifactId, "");
- if (droolsController.ownsCoder(
- encodedClass.getClass(), coder.getModelClassLoaderHash())) {
- droolsControllers.add(droolsController);
- }
- }
- }
- }
-
- if (droolsControllers.isEmpty()) {
- throw new IllegalStateException(
- "No Encoders toolsets available for "
- + topic
- + ":"
- + encodedClass.getClass().getName());
- }
-
- return droolsControllers;
- }
-
- /**
- * get all filters by maven coordinates and topic.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @param topic topic
- * @return list of coders
- * @throws IllegalArgumentException if invalid input
- */
- public List<CoderFilters> getFilters(String groupId, String artifactId, String topic) {
-
- if (!isCodingSupported(groupId, artifactId, topic)) {
- throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
- }
-
- String key = this.codersKey(groupId, artifactId, topic);
- ProtocolCoderToolset coderTools = coders.get(key);
- return coderTools.getCoders();
- }
-
- /**
- * get all coders by maven coordinates and topic.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @return list of coders
- * @throws IllegalArgumentException if invalid input
- */
- public List<CoderFilters> getFilters(String groupId, String artifactId) {
-
- if (groupId == null || groupId.isEmpty()) {
- throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
- }
-
- if (artifactId == null || artifactId.isEmpty()) {
- throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
- }
-
- String key = this.codersKey(groupId, artifactId, "");
-
- List<CoderFilters> codersFilters = new ArrayList<>();
- for (Map.Entry<String, ProtocolCoderToolset> entry :
- coders.entrySet()) {
- if (entry.getKey().startsWith(key)) {
- codersFilters.addAll(entry.getValue().getCoders());
- }
- }
-
- return codersFilters;
- }
-
- /**
- * get all filters by maven coordinates, topic, and classname.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @param topic topic
- * @param classname classname
- * @return list of coders
- * @throws IllegalArgumentException if invalid input
- */
- public CoderFilters getFilters(
- String groupId, String artifactId, String topic, String classname) {
-
- if (!isCodingSupported(groupId, artifactId, topic)) {
- throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
- }
-
- if (classname == null || classname.isEmpty()) {
- throw new IllegalArgumentException("classname must be provided");
- }
-
- String key = this.codersKey(groupId, artifactId, topic);
- ProtocolCoderToolset coderTools = coders.get(key);
- return coderTools.getCoder(classname);
- }
-
- /**
- * get all coders by maven coordinates and topic.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @param topic topic
- * @return list of coders
- * @throws IllegalArgumentException if invalid input
- */
- public ProtocolCoderToolset getCoders(
- String groupId, String artifactId, String topic) {
-
- if (!isCodingSupported(groupId, artifactId, topic)) {
- throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
- }
-
- String key = this.codersKey(groupId, artifactId, topic);
- return coders.get(key);
- }
-
- /**
- * get all coders by maven coordinates and topic.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @return list of coders
- * @throws IllegalArgumentException if invalid input
- */
- public List<ProtocolCoderToolset> getCoders(
- String groupId, String artifactId) {
-
- if (groupId == null || groupId.isEmpty()) {
- throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
- }
-
- if (artifactId == null || artifactId.isEmpty()) {
- throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
- }
-
- String key = this.codersKey(groupId, artifactId, "");
-
- List<ProtocolCoderToolset> coderToolset = new ArrayList<>();
- for (Map.Entry<String, ProtocolCoderToolset> entry :
- coders.entrySet()) {
- if (entry.getKey().startsWith(key)) {
- coderToolset.add(entry.getValue());
- }
- }
-
- return coderToolset;
- }
-
- /**
- * get coded based on class and topic.
- *
- * @param topic topic
- * @param codedClass class
- * @return list of reverse filters
- */
- public List<CoderFilters> getReverseFilters(String topic, String codedClass) {
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException(UNSUPPORTED_MSG);
- }
-
- if (codedClass == null) {
- throw new IllegalArgumentException(MISSING_CLASS);
- }
-
- String key = this.reverseCodersKey(topic, codedClass);
- List<ProtocolCoderToolset> toolsets = this.reverseCoders.get(key);
- if (toolsets == null) {
- throw new IllegalArgumentException("No Coder found for " + key);
- }
-
- List<CoderFilters> coderFilters = new ArrayList<>();
- for (ProtocolCoderToolset toolset : toolsets) {
- coderFilters.addAll(toolset.getCoders());
- }
-
- return coderFilters;
- }
-
- /**
- * returns group and artifact id of the creator of the encoder.
- *
- * @param topic topic
- * @param fact fact
- * @return the drools controller
- */
- DroolsController getDroolsController(String topic, Object fact) {
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException(UNSUPPORTED_MSG);
- }
-
- if (fact == null) {
- throw new IllegalArgumentException(MISSING_CLASS);
- }
-
- List<DroolsController> droolsControllers = droolsCreators(topic, fact);
-
- if (droolsControllers.isEmpty()) {
- throw new IllegalArgumentException("Invalid Topic: " + topic);
- }
-
- if (droolsControllers.size() > 1) {
- logger.warn(
- "{}: multiple drools-controller {} for {}:{} ",
- this,
- droolsControllers,
- topic,
- fact.getClass().getName());
- // continue
- }
- return droolsControllers.get(0);
- }
-
- /**
- * returns group and artifact id of the creator of the encoder.
- *
- * @param topic topic
- * @param fact fact
- * @return list of drools controllers
- */
- List<DroolsController> getDroolsControllers(String topic, Object fact) {
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException(UNSUPPORTED_MSG);
- }
-
- if (fact == null) {
- throw new IllegalArgumentException(MISSING_CLASS);
- }
-
- List<DroolsController> droolsControllers = droolsCreators(topic, fact);
- if (droolsControllers.size() > 1) {
- // unexpected
- logger.warn(
- "{}: multiple drools-controller {} for {}:{} ",
- this,
- droolsControllers,
- topic,
- fact.getClass().getName());
- // continue
- }
- return droolsControllers;
- }
-
- @Override
- public String toString() {
- return "GenericEventProtocolCoder [coders="
- + coders.keySet()
- + ", reverseCoders="
- + reverseCoders.keySet()
- + "]";
- }
-}
-
-class EventProtocolDecoder extends GenericEventProtocolCoder {
-
- public EventProtocolDecoder() {
- super();
- }
-
- @Override
- public String toString() {
- return "EventProtocolDecoder [toString()=" + super.toString() + "]";
- }
-}
-
-class EventProtocolEncoder extends GenericEventProtocolCoder {
-
- public EventProtocolEncoder() {
- super();
- }
-
- @Override
- public String toString() {
- return "EventProtocolEncoder [toString()=" + super.toString() + "]";
- }
-}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolDecoder.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolDecoder.java
new file mode 100644
index 00000000..6bb3a623
--- /dev/null
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolDecoder.java
@@ -0,0 +1,33 @@
+/*
+ * ============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.drools.protocol.coders;
+
+class EventProtocolDecoder extends GenericEventProtocolCoder {
+
+ public EventProtocolDecoder() {
+ super();
+ }
+
+ @Override
+ public String toString() {
+ return "EventProtocolDecoder [toString()=" + super.toString() + "]";
+ }
+}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolEncoder.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolEncoder.java
new file mode 100644
index 00000000..461c66a8
--- /dev/null
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolEncoder.java
@@ -0,0 +1,33 @@
+/*
+ * ============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.drools.protocol.coders;
+
+class EventProtocolEncoder extends GenericEventProtocolCoder {
+
+ public EventProtocolEncoder() {
+ super();
+ }
+
+ @Override
+ public String toString() {
+ return "EventProtocolEncoder [toString()=" + super.toString() + "]";
+ }
+}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GenericEventProtocolCoder.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GenericEventProtocolCoder.java
new file mode 100644
index 00000000..8643da3d
--- /dev/null
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GenericEventProtocolCoder.java
@@ -0,0 +1,712 @@
+/*
+ * ============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.drools.protocol.coders;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This protocol Coder that does its best attempt to decode/encode, selecting the best class and best fitted json
+ * parsing tools.
+ */
+abstract class GenericEventProtocolCoder {
+
+ private static final String INVALID_ARTIFACT_ID_MSG = "Invalid artifact id";
+
+ private static final String INVALID_GROUP_ID_MSG = "Invalid group id";
+
+ private static final String INVALID_TOPIC_MSG = "Invalid Topic";
+
+ private static final String UNSUPPORTED_MSG = "Unsupported";
+
+ private static final String MISSING_CLASS = "class must be provided";
+
+ private static Logger logger = LoggerFactory.getLogger(GenericEventProtocolCoder.class);
+
+ /**
+ * Mapping topic:controller-id -> /<protocol-decoder-toolset/> where protocol-coder-toolset contains
+ * a gson-protocol-coder-toolset.
+ */
+ protected final HashMap<String, ProtocolCoderToolset> coders =
+ new HashMap<>();
+
+ /**
+ * Mapping topic + classname -> Protocol Set.
+ */
+ protected final HashMap<String, List<ProtocolCoderToolset>>
+ reverseCoders = new HashMap<>();
+
+ GenericEventProtocolCoder() {
+ super();
+ }
+
+ /**
+ * Index a new coder.
+ *
+ * @param eventProtocolParams parameter object for event encoder
+ * @throw IllegalArgumentException if an invalid parameter is passed
+ */
+ public void add(EventProtocolParams eventProtocolParams) {
+ if (eventProtocolParams.getGroupId() == null || eventProtocolParams.getGroupId().isEmpty()) {
+ throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
+ }
+
+ if (eventProtocolParams.getArtifactId() == null || eventProtocolParams.getArtifactId().isEmpty()) {
+ throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
+ }
+
+ if (eventProtocolParams.getTopic() == null || eventProtocolParams.getTopic().isEmpty()) {
+ throw new IllegalArgumentException(INVALID_TOPIC_MSG);
+ }
+
+ if (eventProtocolParams.getEventClass() == null) {
+ throw new IllegalArgumentException("Invalid Event Class");
+ }
+
+ String key = this.codersKey(eventProtocolParams.getGroupId(), eventProtocolParams.getArtifactId(),
+ eventProtocolParams.getTopic());
+ String reverseKey = this.reverseCodersKey(eventProtocolParams.getTopic(), eventProtocolParams.getEventClass());
+
+ synchronized (this) {
+ if (coders.containsKey(key)) {
+ ProtocolCoderToolset toolset = coders.get(key);
+
+ logger.info("{}: adding coders for existing {}: {}", this, key, toolset);
+
+ toolset
+ .addCoder(
+ eventProtocolParams.getEventClass(),
+ eventProtocolParams.getProtocolFilter(),
+ eventProtocolParams.getModelClassLoaderHash());
+
+ if (!reverseCoders.containsKey(reverseKey)) {
+ logger.info(
+ "{}: adding new reverse coders (multiple classes case) for {}:{}: {}",
+ this,
+ reverseKey,
+ key,
+ toolset);
+
+ List<ProtocolCoderToolset> reverseMappings =
+ new ArrayList<>();
+ reverseMappings.add(toolset);
+ reverseCoders.put(reverseKey, reverseMappings);
+ }
+ return;
+ }
+
+ GsonProtocolCoderToolset coderTools =
+ new GsonProtocolCoderToolset(eventProtocolParams, key);
+
+ logger.info("{}: adding coders for new {}: {}", this, key, coderTools);
+
+ coders.put(key, coderTools);
+
+ if (reverseCoders.containsKey(reverseKey)) {
+ // There is another controller (different group id/artifact id/topic)
+ // that shares the class and the topic.
+
+ List<ProtocolCoderToolset> toolsets =
+ reverseCoders.get(reverseKey);
+ boolean present = false;
+ for (ProtocolCoderToolset parserSet : toolsets) {
+ // just doublecheck
+ present = parserSet.getControllerId().equals(key);
+ if (present) {
+ /* anomaly */
+ logger.error(
+ "{}: unexpected toolset reverse mapping found for {}:{}: {}",
+ this,
+ reverseKey,
+ key,
+ parserSet);
+ }
+ }
+
+ if (present) {
+ return;
+ } else {
+ logger.info("{}: adding coder set for {}: {} ", this, reverseKey, coderTools);
+ toolsets.add(coderTools);
+ }
+ } else {
+ List<ProtocolCoderToolset> toolsets = new ArrayList<>();
+ toolsets.add(coderTools);
+
+ logger.info("{}: adding toolset for reverse key {}: {}", this, reverseKey, toolsets);
+ reverseCoders.put(reverseKey, toolsets);
+ }
+ }
+ }
+
+ /**
+ * produces key for indexing toolset entries.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @param topic topic
+ * @return index key
+ */
+ protected String codersKey(String groupId, String artifactId, String topic) {
+ return groupId + ":" + artifactId + ":" + topic;
+ }
+
+ /**
+ * produces a key for the reverse index.
+ *
+ * @param topic topic
+ * @param eventClass coded class
+ * @return reverse index key
+ */
+ protected String reverseCodersKey(String topic, String eventClass) {
+ return topic + ":" + eventClass;
+ }
+
+ /**
+ * remove coder.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @param topic topic
+ * @throws IllegalArgumentException if invalid input
+ */
+ public void remove(String groupId, String artifactId, String topic) {
+
+ if (groupId == null || groupId.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
+ }
+
+ if (artifactId == null || artifactId.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
+ }
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_TOPIC_MSG);
+ }
+
+ String key = this.codersKey(groupId, artifactId, topic);
+
+ synchronized (this) {
+ if (coders.containsKey(key)) {
+ ProtocolCoderToolset coderToolset = coders.remove(key);
+
+ logger.info("{}: removed toolset for {}: {}", this, key, coderToolset);
+
+ for (CoderFilters codeFilter : coderToolset.getCoders()) {
+ String className = codeFilter.getCodedClass();
+ String reverseKey = this.reverseCodersKey(topic, className);
+ if (this.reverseCoders.containsKey(reverseKey)) {
+ List<ProtocolCoderToolset> toolsets =
+ this.reverseCoders.get(reverseKey);
+ Iterator<ProtocolCoderToolset> toolsetsIter =
+ toolsets.iterator();
+ while (toolsetsIter.hasNext()) {
+ ProtocolCoderToolset toolset = toolsetsIter.next();
+ if (toolset.getControllerId().equals(key)) {
+ logger.info(
+ "{}: removed coder from toolset for {} from reverse mapping", this, reverseKey);
+ toolsetsIter.remove();
+ }
+ }
+
+ if (this.reverseCoders.get(reverseKey).isEmpty()) {
+ logger.info("{}: removing reverse mapping for {}: ", this, reverseKey);
+ this.reverseCoders.remove(reverseKey);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * does it support coding.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @param topic topic
+ * @return true if its is codable
+ */
+ public boolean isCodingSupported(String groupId, String artifactId, String topic) {
+
+ if (groupId == null || groupId.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
+ }
+
+ if (artifactId == null || artifactId.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
+ }
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_TOPIC_MSG);
+ }
+
+ String key = this.codersKey(groupId, artifactId, topic);
+ synchronized (this) {
+ return coders.containsKey(key);
+ }
+ }
+
+ /**
+ * decode a json string into an Object.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @param topic topic
+ * @param json json string to convert to object
+ * @return the decoded object
+ * @throws IllegalArgumentException if invalid argument is provided
+ * @throws UnsupportedOperationException if the operation cannot be performed
+ */
+ public Object decode(String groupId, String artifactId, String topic, String json) {
+
+ if (!isCodingSupported(groupId, artifactId, topic)) {
+ throw new IllegalArgumentException(
+ "Unsupported:" + codersKey(groupId, artifactId, topic) + " for encoding");
+ }
+
+ String key = this.codersKey(groupId, artifactId, topic);
+ ProtocolCoderToolset coderTools = coders.get(key);
+ try {
+ Object event = coderTools.decode(json);
+ if (event != null) {
+ return event;
+ }
+ } catch (Exception e) {
+ logger.debug("{}, cannot decode {}", this, json, e);
+ }
+
+ throw new UnsupportedOperationException("Cannot decode with gson");
+ }
+
+ /**
+ * encode an object into a json string.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @param topic topic
+ * @param event object to convert to string
+ * @return the json string
+ * @throws IllegalArgumentException if invalid argument is provided
+ * @throws UnsupportedOperationException if the operation cannot be performed
+ */
+ public String encode(String groupId, String artifactId, String topic, Object event) {
+
+ if (!isCodingSupported(groupId, artifactId, topic)) {
+ throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
+ }
+
+ if (event == null) {
+ throw new IllegalArgumentException("Unsupported topic:" + topic);
+ }
+
+ // reuse the decoder set, since there must be affinity in the model
+ String key = this.codersKey(groupId, artifactId, topic);
+ return this.encodeInternal(key, event);
+ }
+
+ /**
+ * encode an object into a json string.
+ *
+ * @param topic topic
+ * @param event object to convert to string
+ * @return the json string
+ * @throws IllegalArgumentException if invalid argument is provided
+ * @throws UnsupportedOperationException if the operation cannot be performed
+ */
+ public String encode(String topic, Object event) {
+
+ if (event == null) {
+ throw new IllegalArgumentException("Invalid encoded class");
+ }
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException("Invalid topic");
+ }
+
+ String reverseKey = this.reverseCodersKey(topic, event.getClass().getName());
+ if (!this.reverseCoders.containsKey(reverseKey)) {
+ throw new IllegalArgumentException("no reverse coder has been found");
+ }
+
+ List<ProtocolCoderToolset> toolsets =
+ this.reverseCoders.get(reverseKey);
+
+ String key =
+ codersKey(
+ toolsets.get(0).getGroupId(), toolsets.get(0).getArtifactId(), topic);
+ return this.encodeInternal(key, event);
+ }
+
+ /**
+ * encode an object into a json string.
+ *
+ * @param topic topic
+ * @param encodedClass object to convert to string
+ * @return the json string
+ * @throws IllegalArgumentException if invalid argument is provided
+ * @throws UnsupportedOperationException if the operation cannot be performed
+ */
+ public String encode(String topic, Object encodedClass, DroolsController droolsController) {
+
+ if (encodedClass == null) {
+ throw new IllegalArgumentException("Invalid encoded class");
+ }
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException("Invalid topic");
+ }
+
+ String key = codersKey(droolsController.getGroupId(), droolsController.getArtifactId(), topic);
+ return this.encodeInternal(key, encodedClass);
+ }
+
+ /**
+ * encode an object into a json string.
+ *
+ * @param key identifier
+ * @param event object to convert to string
+ * @return the json string
+ * @throws IllegalArgumentException if invalid argument is provided
+ * @throws UnsupportedOperationException if the operation cannot be performed
+ */
+ protected String encodeInternal(String key, Object event) {
+
+ logger.debug("{}: encode for {}: {}", this, key, event);
+
+ ProtocolCoderToolset coderTools = coders.get(key);
+ try {
+ String json = coderTools.encode(event);
+ if (json != null && !json.isEmpty()) {
+ return json;
+ }
+ } catch (Exception e) {
+ logger.warn("{}: cannot encode (first) for {}: {}", this, key, event, e);
+ }
+
+ throw new UnsupportedOperationException("Cannot decode with gson");
+ }
+
+ /**
+ * Drools creators.
+ *
+ * @param topic topic
+ * @param encodedClass encoded class
+ * @return list of controllers
+ * @throws IllegalStateException illegal state
+ * @throws IllegalArgumentException argument
+ */
+ protected List<DroolsController> droolsCreators(String topic, Object encodedClass) {
+
+ List<DroolsController> droolsControllers = new ArrayList<>();
+
+ String reverseKey = this.reverseCodersKey(topic, encodedClass.getClass().getName());
+ if (!this.reverseCoders.containsKey(reverseKey)) {
+ logger.warn("{}: no reverse mapping for {}", this, reverseKey);
+ return droolsControllers;
+ }
+
+ List<ProtocolCoderToolset> toolsets =
+ this.reverseCoders.get(reverseKey);
+
+ // There must be multiple toolsets associated with <topic,classname> reverseKey
+ // case 2 different controllers use the same models and register the same encoder for
+ // the same topic. This is assumed not to occur often but for the purpose of encoding
+ // but there should be no side-effects. Ownership is crosscheck against classname and
+ // classloader reference.
+
+ if (toolsets == null || toolsets.isEmpty()) {
+ throw new IllegalStateException(
+ "No Encoders toolsets available for topic "
+ + topic
+ + " encoder "
+ + encodedClass.getClass().getName());
+ }
+
+ for (ProtocolCoderToolset encoderSet : toolsets) {
+ // figure out the right toolset
+ String groupId = encoderSet.getGroupId();
+ String artifactId = encoderSet.getArtifactId();
+ List<CoderFilters> coderFilters = encoderSet.getCoders();
+ for (CoderFilters coder : coderFilters) {
+ if (coder.getCodedClass().equals(encodedClass.getClass().getName())) {
+ DroolsController droolsController = DroolsController.factory.get(groupId, artifactId, "");
+ if (droolsController.ownsCoder(
+ encodedClass.getClass(), coder.getModelClassLoaderHash())) {
+ droolsControllers.add(droolsController);
+ }
+ }
+ }
+ }
+
+ if (droolsControllers.isEmpty()) {
+ throw new IllegalStateException(
+ "No Encoders toolsets available for "
+ + topic
+ + ":"
+ + encodedClass.getClass().getName());
+ }
+
+ return droolsControllers;
+ }
+
+ /**
+ * get all filters by maven coordinates and topic.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @param topic topic
+ * @return list of coders
+ * @throws IllegalArgumentException if invalid input
+ */
+ public List<CoderFilters> getFilters(String groupId, String artifactId, String topic) {
+
+ if (!isCodingSupported(groupId, artifactId, topic)) {
+ throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
+ }
+
+ String key = this.codersKey(groupId, artifactId, topic);
+ ProtocolCoderToolset coderTools = coders.get(key);
+ return coderTools.getCoders();
+ }
+
+ /**
+ * get all coders by maven coordinates and topic.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @return list of coders
+ * @throws IllegalArgumentException if invalid input
+ */
+ public List<CoderFilters> getFilters(String groupId, String artifactId) {
+
+ if (groupId == null || groupId.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
+ }
+
+ if (artifactId == null || artifactId.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
+ }
+
+ String key = this.codersKey(groupId, artifactId, "");
+
+ List<CoderFilters> codersFilters = new ArrayList<>();
+ for (Map.Entry<String, ProtocolCoderToolset> entry :
+ coders.entrySet()) {
+ if (entry.getKey().startsWith(key)) {
+ codersFilters.addAll(entry.getValue().getCoders());
+ }
+ }
+
+ return codersFilters;
+ }
+
+ /**
+ * get all filters by maven coordinates, topic, and classname.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @param topic topic
+ * @param classname classname
+ * @return list of coders
+ * @throws IllegalArgumentException if invalid input
+ */
+ public CoderFilters getFilters(
+ String groupId, String artifactId, String topic, String classname) {
+
+ if (!isCodingSupported(groupId, artifactId, topic)) {
+ throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
+ }
+
+ if (classname == null || classname.isEmpty()) {
+ throw new IllegalArgumentException("classname must be provided");
+ }
+
+ String key = this.codersKey(groupId, artifactId, topic);
+ ProtocolCoderToolset coderTools = coders.get(key);
+ return coderTools.getCoder(classname);
+ }
+
+ /**
+ * get all coders by maven coordinates and topic.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @param topic topic
+ * @return list of coders
+ * @throws IllegalArgumentException if invalid input
+ */
+ public ProtocolCoderToolset getCoders(
+ String groupId, String artifactId, String topic) {
+
+ if (!isCodingSupported(groupId, artifactId, topic)) {
+ throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
+ }
+
+ String key = this.codersKey(groupId, artifactId, topic);
+ return coders.get(key);
+ }
+
+ /**
+ * get all coders by maven coordinates and topic.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @return list of coders
+ * @throws IllegalArgumentException if invalid input
+ */
+ public List<ProtocolCoderToolset> getCoders(
+ String groupId, String artifactId) {
+
+ if (groupId == null || groupId.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
+ }
+
+ if (artifactId == null || artifactId.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
+ }
+
+ String key = this.codersKey(groupId, artifactId, "");
+
+ List<ProtocolCoderToolset> coderToolset = new ArrayList<>();
+ for (Map.Entry<String, ProtocolCoderToolset> entry :
+ coders.entrySet()) {
+ if (entry.getKey().startsWith(key)) {
+ coderToolset.add(entry.getValue());
+ }
+ }
+
+ return coderToolset;
+ }
+
+ /**
+ * get coded based on class and topic.
+ *
+ * @param topic topic
+ * @param codedClass class
+ * @return list of reverse filters
+ */
+ public List<CoderFilters> getReverseFilters(String topic, String codedClass) {
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException(UNSUPPORTED_MSG);
+ }
+
+ if (codedClass == null) {
+ throw new IllegalArgumentException(MISSING_CLASS);
+ }
+
+ String key = this.reverseCodersKey(topic, codedClass);
+ List<ProtocolCoderToolset> toolsets = this.reverseCoders.get(key);
+ if (toolsets == null) {
+ throw new IllegalArgumentException("No Coder found for " + key);
+ }
+
+ List<CoderFilters> coderFilters = new ArrayList<>();
+ for (ProtocolCoderToolset toolset : toolsets) {
+ coderFilters.addAll(toolset.getCoders());
+ }
+
+ return coderFilters;
+ }
+
+ /**
+ * returns group and artifact id of the creator of the encoder.
+ *
+ * @param topic topic
+ * @param fact fact
+ * @return the drools controller
+ */
+ DroolsController getDroolsController(String topic, Object fact) {
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException(UNSUPPORTED_MSG);
+ }
+
+ if (fact == null) {
+ throw new IllegalArgumentException(MISSING_CLASS);
+ }
+
+ List<DroolsController> droolsControllers = droolsCreators(topic, fact);
+
+ if (droolsControllers.isEmpty()) {
+ throw new IllegalArgumentException("Invalid Topic: " + topic);
+ }
+
+ if (droolsControllers.size() > 1) {
+ logger.warn(
+ "{}: multiple drools-controller {} for {}:{} ",
+ this,
+ droolsControllers,
+ topic,
+ fact.getClass().getName());
+ // continue
+ }
+ return droolsControllers.get(0);
+ }
+
+ /**
+ * returns group and artifact id of the creator of the encoder.
+ *
+ * @param topic topic
+ * @param fact fact
+ * @return list of drools controllers
+ */
+ List<DroolsController> getDroolsControllers(String topic, Object fact) {
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException(UNSUPPORTED_MSG);
+ }
+
+ if (fact == null) {
+ throw new IllegalArgumentException(MISSING_CLASS);
+ }
+
+ List<DroolsController> droolsControllers = droolsCreators(topic, fact);
+ if (droolsControllers.size() > 1) {
+ // unexpected
+ logger.warn(
+ "{}: multiple drools-controller {} for {}:{} ",
+ this,
+ droolsControllers,
+ topic,
+ fact.getClass().getName());
+ // continue
+ }
+ return droolsControllers;
+ }
+
+ @Override
+ public String toString() {
+ return "GenericEventProtocolCoder [coders="
+ + coders.keySet()
+ + ", reverseCoders="
+ + reverseCoders.keySet()
+ + "]";
+ }
+}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolset.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolset.java
new file mode 100644
index 00000000..57976a3e
--- /dev/null
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolset.java
@@ -0,0 +1,249 @@
+/*
+ * ============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.drools.protocol.coders;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.time.Instant;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
+import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tools used for encoding/decoding using GSON.
+ */
+class GsonProtocolCoderToolset extends ProtocolCoderToolset {
+ /**
+ * Logger.
+ */
+ private static final Logger logger = LoggerFactory.getLogger(GsonProtocolCoderToolset.class);
+
+ /**
+ * Formatter for JSON encoding/decoding.
+ */
+ @JsonIgnore
+ @GsonJsonIgnore
+ public static final DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSxxx");
+
+ @JsonIgnore
+ @GsonJsonIgnore
+ public static final DateTimeFormatter zuluFormat = DateTimeFormatter.ISO_INSTANT;
+
+ /**
+ * Adapter for ZonedDateTime.
+ */
+ public static class GsonUtcAdapter implements JsonSerializer<ZonedDateTime>, JsonDeserializer<ZonedDateTime> {
+ @Override
+ public ZonedDateTime deserialize(JsonElement element, Type type,
+ JsonDeserializationContext context) {
+ try {
+ return ZonedDateTime.parse(element.getAsString(), format);
+ } catch (final Exception e) {
+ logger.info("GsonUTCAdapter: cannot parse {} because of {}", element, e.getMessage(), e);
+ }
+ return null;
+ }
+
+ @Override
+ public JsonElement serialize(ZonedDateTime datetime, Type type,
+ JsonSerializationContext context) {
+ return new JsonPrimitive(datetime.format(format));
+ }
+ }
+
+ public static class GsonInstantAdapter implements JsonSerializer<Instant>, JsonDeserializer<Instant> {
+
+ @Override
+ public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
+ return Instant.ofEpochMilli(json.getAsLong());
+ }
+
+ @Override
+ public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive(src.toEpochMilli());
+ }
+
+ }
+
+
+ /**
+ * decoder.
+ */
+ @JsonIgnore
+ @GsonJsonIgnore
+ protected final Gson decoder = new GsonBuilder().disableHtmlEscaping()
+ .registerTypeAdapter(ZonedDateTime.class, new GsonUtcAdapter())
+ .registerTypeAdapter(Instant.class, new GsonInstantAdapter()).create();
+
+ /**
+ * encoder.
+ */
+ @JsonIgnore
+ @GsonJsonIgnore
+ protected final Gson encoder = new GsonBuilder().disableHtmlEscaping()
+ .registerTypeAdapter(ZonedDateTime.class, new GsonUtcAdapter())
+ .registerTypeAdapter(Instant.class, new GsonInstantAdapter()).create();
+
+ /**
+ * Toolset to encode/decode tools associated with a topic.
+ *
+ * @param eventProtocolParams parameter object for event encoder
+ * @param controllerId controller id
+ */
+ public GsonProtocolCoderToolset(EventProtocolParams eventProtocolParams, String controllerId) {
+ super(eventProtocolParams, controllerId);
+ }
+
+ /**
+ * gets the Gson decoder.
+ *
+ * @return the Gson decoder
+ */
+ @JsonIgnore
+ @GsonJsonIgnore
+ protected Gson getDecoder() {
+ return this.decoder;
+ }
+
+ /**
+ * gets the Gson encoder.
+ *
+ * @return the Gson encoder
+ */
+ @JsonIgnore
+ @GsonJsonIgnore
+ protected Gson getEncoder() {
+ return this.encoder;
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public Object decode(String json) {
+
+ final DroolsController droolsController =
+ DroolsController.factory.get(this.groupId, this.artifactId, "");
+ if (droolsController == null) {
+ logger.warn("{}: no drools-controller to process {}", this, json);
+ throw new IllegalStateException("no drools-controller to process event");
+ }
+
+ final CoderFilters decoderFilter = this.filter(json);
+ if (decoderFilter == null) {
+ logger.debug("{}: no decoder to process {}", this, json);
+ throw new UnsupportedOperationException("no decoder to process event");
+ }
+
+ Class<?> decoderClass;
+ try {
+ decoderClass = droolsController.fetchModelClass(decoderFilter.getCodedClass());
+ if (decoderClass == null) {
+ logger.warn("{}: cannot fetch application class {}", this, decoderFilter.getCodedClass());
+ throw new IllegalStateException(
+ "cannot fetch application class " + decoderFilter.getCodedClass());
+ }
+ } catch (final Exception e) {
+ logger.warn("{}: cannot fetch application class {} because of {}", this,
+ decoderFilter.getCodedClass(), e.getMessage());
+ throw new UnsupportedOperationException(
+ "cannot fetch application class " + decoderFilter.getCodedClass(), e);
+ }
+
+ if (this.customCoder != null) {
+ try {
+ final Class<?> gsonClassContainer =
+ droolsController.fetchModelClass(this.customCoder.getClassContainer());
+ final Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField);
+ final Object gsonObject = gsonField.get(null);
+ final Method fromJsonMethod = gsonObject.getClass().getDeclaredMethod("fromJson",
+ new Class[] {String.class, Class.class});
+ return fromJsonMethod.invoke(gsonObject, json, decoderClass);
+ } catch (final Exception e) {
+ logger.warn("{}: cannot fetch application class {} because of {}", this,
+ decoderFilter.getCodedClass(), e.getMessage());
+ throw new UnsupportedOperationException(
+ "cannot fetch application class " + decoderFilter.getCodedClass(), e);
+ }
+ } else {
+ try {
+ return this.decoder.fromJson(json, decoderClass);
+ } catch (final Exception e) {
+ logger.warn("{} cannot decode {} into {} because of {}", this, json, decoderClass.getName(),
+ e.getMessage(), e);
+ throw new UnsupportedOperationException(
+ "cannont decode into " + decoderFilter.getCodedClass(), e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public String encode(Object event) {
+
+ if (this.customCoder != null) {
+ try {
+ final DroolsController droolsController =
+ DroolsController.factory.get(this.groupId, this.artifactId, null);
+ final Class<?> gsonClassContainer =
+ droolsController.fetchModelClass(this.customCoder.getClassContainer());
+ final Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField);
+ final Object gsonObject = gsonField.get(null);
+ final Method toJsonMethod =
+ gsonObject.getClass().getDeclaredMethod("toJson", new Class[] {Object.class});
+ return (String) toJsonMethod.invoke(gsonObject, event);
+ } catch (final Exception e) {
+ logger.warn("{} cannot custom-encode {} because of {}", this, event, e.getMessage(), e);
+ throw new UnsupportedOperationException("event cannot be encoded", e);
+ }
+ } else {
+ try {
+ return this.encoder.toJson(event);
+ } catch (final Exception e) {
+ logger.warn("{} cannot encode {} because of {}", this, event, e.getMessage(), e);
+ throw new UnsupportedOperationException("event cannot be encoded", e);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("GsonProtocolCoderToolset [toString()=").append(super.toString()).append("]");
+ return builder.toString();
+ }
+}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoder.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoder.java
new file mode 100644
index 00000000..a8f3c3a3
--- /dev/null
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoder.java
@@ -0,0 +1,278 @@
+/*
+ * ============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.drools.protocol.coders;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.onap.policy.drools.controller.DroolsController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Protocol Coder that does its best attempt to decode/encode, selecting the best class and best fitted json parsing
+ * tools.
+ */
+class MultiplexorEventProtocolCoder implements EventProtocolCoder {
+
+ /**
+ * Logger.
+ */
+ private static Logger logger = LoggerFactory.getLogger(MultiplexorEventProtocolCoder.class);
+
+ /**
+ * Decoders.
+ */
+ protected EventProtocolDecoder decoders = new EventProtocolDecoder();
+
+ /**
+ * Encoders.
+ */
+ protected EventProtocolEncoder encoders = new EventProtocolEncoder();
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void addDecoder(EventProtocolParams eventProtocolParams) {
+ logger.info(
+ "{}: add-decoder {}:{}:{}:{}:{}:{}:{}",
+ this,
+ eventProtocolParams.getGroupId(),
+ eventProtocolParams.getArtifactId(),
+ eventProtocolParams.getTopic(),
+ eventProtocolParams.getEventClass(),
+ eventProtocolParams.getProtocolFilter(),
+ eventProtocolParams.getCustomGsonCoder(),
+ eventProtocolParams.getModelClassLoaderHash());
+ this.decoders.add(eventProtocolParams);
+ }
+
+ /**
+ * {@inheritDoc}.
+ *
+ * @param eventProtocolParams parameter object for event encoder
+ */
+ @Override
+ public void addEncoder(EventProtocolParams eventProtocolParams) {
+ logger.info(
+ "{}: add-decoder {}:{}:{}:{}:{}:{}:{}",
+ this,
+ eventProtocolParams.getGroupId(),
+ eventProtocolParams.getArtifactId(),
+ eventProtocolParams.getTopic(),
+ eventProtocolParams.getEventClass(),
+ eventProtocolParams.getProtocolFilter(),
+ eventProtocolParams.getCustomGsonCoder(),
+ eventProtocolParams.getModelClassLoaderHash());
+ this.encoders.add(eventProtocolParams);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void removeDecoders(String groupId, String artifactId, String topic) {
+ logger.info("{}: remove-decoder {}:{}:{}", this, groupId, artifactId, topic);
+ this.decoders.remove(groupId, artifactId, topic);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void removeEncoders(String groupId, String artifactId, String topic) {
+ logger.info("{}: remove-encoder {}:{}:{}", this, groupId, artifactId, topic);
+ this.encoders.remove(groupId, artifactId, topic);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public boolean isDecodingSupported(String groupId, String artifactId, String topic) {
+ return this.decoders.isCodingSupported(groupId, artifactId, topic);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public boolean isEncodingSupported(String groupId, String artifactId, String topic) {
+ return this.encoders.isCodingSupported(groupId, artifactId, topic);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public Object decode(String groupId, String artifactId, String topic, String json) {
+ logger.debug("{}: decode {}:{}:{}:{}", this, groupId, artifactId, topic, json);
+ return this.decoders.decode(groupId, artifactId, topic, json);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public String encode(String groupId, String artifactId, String topic, Object event) {
+ logger.debug("{}: encode {}:{}:{}:{}", this, groupId, artifactId, topic, event);
+ return this.encoders.encode(groupId, artifactId, topic, event);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public String encode(String topic, Object event) {
+ logger.debug("{}: encode {}:{}", this, topic, event);
+ return this.encoders.encode(topic, event);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public String encode(String topic, Object event, DroolsController droolsController) {
+ logger.debug("{}: encode {}:{}:{}", this, topic, event, droolsController);
+ return this.encoders.encode(topic, event, droolsController);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic) {
+ return this.decoders.getFilters(groupId, artifactId, topic);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public CoderFilters getDecoderFilters(
+ String groupId, String artifactId, String topic, String classname) {
+ return this.decoders.getFilters(groupId, artifactId, topic, classname);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public List<CoderFilters> getDecoderFilters(String groupId, String artifactId) {
+ return this.decoders.getFilters(groupId, artifactId);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) {
+ ProtocolCoderToolset decoderToolsets =
+ this.decoders.getCoders(groupId, artifactId, topic);
+ if (decoderToolsets == null) {
+ throw new IllegalArgumentException(
+ "Decoders not found for " + groupId + ":" + artifactId + ":" + topic);
+ }
+
+ return decoderToolsets;
+ }
+
+ /**
+ * get all deocders by maven coordinates and topic.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @return list of decoders
+ * @throws IllegalArgumentException if invalid input
+ */
+ @Override
+ public List<ProtocolCoderToolset> getDecoders(String groupId, String artifactId) {
+
+ List<ProtocolCoderToolset> decoderToolsets =
+ this.decoders.getCoders(groupId, artifactId);
+ if (decoderToolsets == null) {
+ throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId);
+ }
+
+ return new ArrayList<>(decoderToolsets);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic) {
+ return this.encoders.getFilters(groupId, artifactId, topic);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public CoderFilters getEncoderFilters(
+ String groupId, String artifactId, String topic, String classname) {
+ return this.encoders.getFilters(groupId, artifactId, topic, classname);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public List<CoderFilters> getEncoderFilters(String groupId, String artifactId) {
+ return this.encoders.getFilters(groupId, artifactId);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass) {
+ return this.encoders.getReverseFilters(topic, encodedClass);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public DroolsController getDroolsController(String topic, Object encodedClass) {
+ return this.encoders.getDroolsController(topic, encodedClass);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public List<DroolsController> getDroolsControllers(String topic, Object encodedClass) {
+ return this.encoders.getDroolsControllers(topic, encodedClass);
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public String toString() {
+ return "MultiplexorEventProtocolCoder [decoders="
+ + decoders
+ + ", encoders="
+ + encoders
+ + "]";
+ }
+}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java
index 394e73af..a4add9ce 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java
@@ -21,27 +21,10 @@
package org.onap.policy.drools.protocol.coders;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.time.Instant;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
-import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
-import org.onap.policy.drools.controller.DroolsController;
import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters;
import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomCoder;
import org.slf4j.Logger;
@@ -309,210 +292,3 @@ public abstract class ProtocolCoderToolset {
return builder.toString();
}
}
-
-/**
- * Tools used for encoding/decoding using GSON.
- */
-class GsonProtocolCoderToolset extends ProtocolCoderToolset {
- /**
- * Logger.
- */
- private static final Logger logger = LoggerFactory.getLogger(GsonProtocolCoderToolset.class);
-
- /**
- * Formatter for JSON encoding/decoding.
- */
- @JsonIgnore
- @GsonJsonIgnore
- public static final DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSxxx");
-
- @JsonIgnore
- @GsonJsonIgnore
- public static final DateTimeFormatter zuluFormat = DateTimeFormatter.ISO_INSTANT;
-
- /**
- * Adapter for ZonedDateTime.
- */
- public static class GsonUTCAdapter implements JsonSerializer<ZonedDateTime>, JsonDeserializer<ZonedDateTime> {
- @Override
- public ZonedDateTime deserialize(JsonElement element, Type type,
- JsonDeserializationContext context) {
- try {
- return ZonedDateTime.parse(element.getAsString(), format);
- } catch (final Exception e) {
- logger.info("GsonUTCAdapter: cannot parse {} because of {}", element, e.getMessage(), e);
- }
- return null;
- }
-
- @Override
- public JsonElement serialize(ZonedDateTime datetime, Type type,
- JsonSerializationContext context) {
- return new JsonPrimitive(datetime.format(format));
- }
- }
-
- public static class GsonInstantAdapter implements JsonSerializer<Instant>, JsonDeserializer<Instant> {
-
- @Override
- public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
- return Instant.ofEpochMilli(json.getAsLong());
- }
-
- @Override
- public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) {
- return new JsonPrimitive(src.toEpochMilli());
- }
-
- }
-
-
- /**
- * decoder.
- */
- @JsonIgnore
- @GsonJsonIgnore
- protected final Gson decoder = new GsonBuilder().disableHtmlEscaping()
- .registerTypeAdapter(ZonedDateTime.class, new GsonUTCAdapter())
- .registerTypeAdapter(Instant.class, new GsonInstantAdapter()).create();
-
- /**
- * encoder.
- */
- @JsonIgnore
- @GsonJsonIgnore
- protected final Gson encoder = new GsonBuilder().disableHtmlEscaping()
- .registerTypeAdapter(ZonedDateTime.class, new GsonUTCAdapter())
- .registerTypeAdapter(Instant.class, new GsonInstantAdapter()).create();
-
- /**
- * Toolset to encode/decode tools associated with a topic.
- *
- * @param eventProtocolParams parameter object for event encoder
- * @param controllerId controller id
- */
- public GsonProtocolCoderToolset(EventProtocolParams eventProtocolParams, String controllerId) {
- super(eventProtocolParams, controllerId);
- }
-
- /**
- * gets the Gson decoder.
- *
- * @return the Gson decoder
- */
- @JsonIgnore
- @GsonJsonIgnore
- protected Gson getDecoder() {
- return this.decoder;
- }
-
- /**
- * gets the Gson encoder.
- *
- * @return the Gson encoder
- */
- @JsonIgnore
- @GsonJsonIgnore
- protected Gson getEncoder() {
- return this.encoder;
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public Object decode(String json) {
-
- final DroolsController droolsController =
- DroolsController.factory.get(this.groupId, this.artifactId, "");
- if (droolsController == null) {
- logger.warn("{}: no drools-controller to process {}", this, json);
- throw new IllegalStateException("no drools-controller to process event");
- }
-
- final CoderFilters decoderFilter = this.filter(json);
- if (decoderFilter == null) {
- logger.debug("{}: no decoder to process {}", this, json);
- throw new UnsupportedOperationException("no decoder to process event");
- }
-
- Class<?> decoderClass;
- try {
- decoderClass = droolsController.fetchModelClass(decoderFilter.getCodedClass());
- if (decoderClass == null) {
- logger.warn("{}: cannot fetch application class {}", this, decoderFilter.getCodedClass());
- throw new IllegalStateException(
- "cannot fetch application class " + decoderFilter.getCodedClass());
- }
- } catch (final Exception e) {
- logger.warn("{}: cannot fetch application class {} because of {}", this,
- decoderFilter.getCodedClass(), e.getMessage());
- throw new UnsupportedOperationException(
- "cannot fetch application class " + decoderFilter.getCodedClass(), e);
- }
-
- if (this.customCoder != null) {
- try {
- final Class<?> gsonClassContainer =
- droolsController.fetchModelClass(this.customCoder.getClassContainer());
- final Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField);
- final Object gsonObject = gsonField.get(null);
- final Method fromJsonMethod = gsonObject.getClass().getDeclaredMethod("fromJson",
- new Class[] {String.class, Class.class});
- return fromJsonMethod.invoke(gsonObject, json, decoderClass);
- } catch (final Exception e) {
- logger.warn("{}: cannot fetch application class {} because of {}", this,
- decoderFilter.getCodedClass(), e.getMessage());
- throw new UnsupportedOperationException(
- "cannot fetch application class " + decoderFilter.getCodedClass(), e);
- }
- } else {
- try {
- return this.decoder.fromJson(json, decoderClass);
- } catch (final Exception e) {
- logger.warn("{} cannot decode {} into {} because of {}", this, json, decoderClass.getName(),
- e.getMessage(), e);
- throw new UnsupportedOperationException(
- "cannont decode into " + decoderFilter.getCodedClass(), e);
- }
- }
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public String encode(Object event) {
-
- if (this.customCoder != null) {
- try {
- final DroolsController droolsController =
- DroolsController.factory.get(this.groupId, this.artifactId, null);
- final Class<?> gsonClassContainer =
- droolsController.fetchModelClass(this.customCoder.getClassContainer());
- final Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField);
- final Object gsonObject = gsonField.get(null);
- final Method toJsonMethod =
- gsonObject.getClass().getDeclaredMethod("toJson", new Class[] {Object.class});
- return (String) toJsonMethod.invoke(gsonObject, event);
- } catch (final Exception e) {
- logger.warn("{} cannot custom-encode {} because of {}", this, event, e.getMessage(), e);
- throw new UnsupportedOperationException("event cannot be encoded", e);
- }
- } else {
- try {
- return this.encoder.toJson(event);
- } catch (final Exception e) {
- logger.warn("{} cannot encode {} because of {}", this, event, e.getMessage(), e);
- throw new UnsupportedOperationException("event cannot be encoded", e);
- }
- }
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("GsonProtocolCoderToolset [toString()=").append(super.toString()).append("]");
- return builder.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 f83f480e..572bc14f 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
@@ -7,9 +7,9 @@
* 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.
@@ -50,7 +50,7 @@ public class PdpdConfiguration {
/** Unique Transaction ID. This is an UUID. (Required) */
@JsonProperty("requestID")
@GsonJsonProperty("requestID")
- private String requestID;
+ private String requestId;
/* Set of entities on which configuration can be performed: controller (Required) */
@JsonProperty("entity")
@GsonJsonProperty("entity")
@@ -70,14 +70,14 @@ public class PdpdConfiguration {
/**
* Constructor.
- *
- * @param requestID request id
+ *
+ * @param requestId request id
* @param entity entity
* @param controllers controllers
*/
public PdpdConfiguration(
- String requestID, String entity, List<ControllerConfiguration> controllers) {
- this.requestID = requestID;
+ String requestId, String entity, List<ControllerConfiguration> controllers) {
+ this.requestId = requestId;
this.entity = entity;
this.controllers = controllers;
}
@@ -89,23 +89,23 @@ public class PdpdConfiguration {
*/
@JsonProperty("requestID")
@GsonJsonProperty("requestID")
- public String getRequestID() {
- return requestID;
+ public String getRequestId() {
+ return requestId;
}
/**
* Unique Transaction ID. This is an UUID. (Required)
*
- * @param requestID The requestID
+ * @param requestId The requestID
*/
@JsonProperty("requestID")
@GsonJsonProperty("requestID")
- public void setRequestID(String requestID) {
- this.requestID = requestID;
+ public void setRequestId(String requestId) {
+ this.requestId = requestId;
}
- public PdpdConfiguration withRequestID(String requestID) {
- this.requestID = requestID;
+ public PdpdConfiguration withRequestId(String requestId) {
+ this.requestId = requestId;
return this;
}
@@ -204,7 +204,7 @@ public class PdpdConfiguration {
protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) {
switch (name) {
case "requestID":
- return getRequestID();
+ return getRequestId();
case "entity":
return getEntity();
case "controllers":
@@ -216,7 +216,7 @@ public class PdpdConfiguration {
/**
* Get.
- *
+ *
* @param name name
* @return object
*/
@@ -232,7 +232,7 @@ public class PdpdConfiguration {
/**
* Set property.
- *
+ *
* @param name name
* @param value value
*/
@@ -255,7 +255,7 @@ public class PdpdConfiguration {
@Override
public int hashCode() {
return new HashCodeBuilder()
- .append(requestID)
+ .append(requestId)
.append(entity)
.append(controllers)
.append(additionalProperties)
@@ -272,7 +272,7 @@ public class PdpdConfiguration {
}
PdpdConfiguration rhs = (PdpdConfiguration) other;
return new EqualsBuilder()
- .append(requestID, rhs.requestID)
+ .append(requestId, rhs.requestId)
.append(entity, rhs.entity)
.append(controllers, rhs.controllers)
.append(additionalProperties, rhs.additionalProperties)
@@ -281,12 +281,12 @@ public class PdpdConfiguration {
/**
* Call set request id.
- *
+ *
* @param value value
*/
public void callSetRequestId(Object value) {
if (value instanceof String) {
- setRequestID((String) value);
+ setRequestId((String) value);
} else {
throw new IllegalArgumentException(
"property \"requestID\" is of type \"java.lang.String\", but got "
@@ -296,7 +296,7 @@ public class PdpdConfiguration {
/**
* Call set entity.
- *
+ *
* @param value value
*/
public void callSetEntity(Object value) {
@@ -311,7 +311,7 @@ public class PdpdConfiguration {
/**
* Call set controllers.
- *
+ *
* @param value value
*/
@SuppressWarnings("unchecked")
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 726e7217..a5fbfdd3 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
@@ -56,8 +56,8 @@ import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
import org.onap.policy.common.endpoints.event.comm.TopicSink;
import org.onap.policy.common.endpoints.event.comm.TopicSource;
import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
-import org.onap.policy.drools.features.PolicyEngineFeatureAPI;
+import org.onap.policy.drools.features.PolicyControllerFeatureApi;
+import org.onap.policy.drools.features.PolicyEngineFeatureApi;
import org.onap.policy.drools.properties.DroolsProperties;
import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters;
@@ -140,7 +140,7 @@ public class RestManager {
@Path("engine/features/inventory")
@ApiOperation(value = "Engine Detailed Feature Inventory",
notes = "Provides detailed list of loaded features using the PolicyEngineFeatureAPI",
- responseContainer = "List", response = PolicyEngineFeatureAPI.class)
+ responseContainer = "List", response = PolicyEngineFeatureApi.class)
public Response engineFeaturesInventory() {
return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatureProviders()).build();
}
@@ -153,7 +153,7 @@ public class RestManager {
@GET
@Path("engine/features/{featureName}")
@ApiOperation(value = "Engine Feature", notes = "Provides Details for a given feature Engine Provider",
- response = PolicyEngineFeatureAPI.class)
+ response = PolicyEngineFeatureApi.class)
@ApiResponses(value = {@ApiResponse(code = 404, message = "The feature cannot be found")})
public Response engineFeature(
@ApiParam(value = "Feature Name", required = true) @PathParam("featureName") String featureName) {
@@ -492,7 +492,7 @@ public class RestManager {
@Path("engine/controllers/features/inventory")
@ApiOperation(value = "Detailed Controllers Feature Inventory",
notes = "Provides detailed list of loaded features using the PolicyControllerFeatureAPI",
- responseContainer = "List", response = PolicyControllerFeatureAPI.class)
+ responseContainer = "List", response = PolicyControllerFeatureApi.class)
public Response controllerFeaturesInventory() {
return Response.status(Response.Status.OK).entity(PolicyController.factory.getFeatureProviders()).build();
}
@@ -506,7 +506,7 @@ public class RestManager {
@Path("engine/controllers/features/{featureName}")
@ApiOperation(value = "Controller Feature",
notes = "Provides Details for a given Policy Controller feature provider",
- response = PolicyControllerFeatureAPI.class)
+ response = PolicyControllerFeatureApi.class)
@ApiResponses(value = {@ApiResponse(code = 404, message = "The feature cannot be found")})
public Response controllerFeature(
@ApiParam(value = "Feature Name", required = true) @PathParam("featureName") String featureName) {
diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/IndexedPolicyControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/system/IndexedPolicyControllerFactory.java
new file mode 100644
index 00000000..38085101
--- /dev/null
+++ b/policy-management/src/main/java/org/onap/policy/drools/system/IndexedPolicyControllerFactory.java
@@ -0,0 +1,387 @@
+/*
+ * ============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.drools.system;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
+import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.features.PolicyControllerFeatureApi;
+import org.onap.policy.drools.protocol.configuration.DroolsConfiguration;
+import org.onap.policy.drools.system.internal.AggregatedPolicyController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Factory of Policy Controllers indexed by the name of the Policy Controller.
+ */
+class IndexedPolicyControllerFactory implements PolicyControllerFactory {
+ // get an instance of logger
+ private static final Logger logger = LoggerFactory.getLogger(PolicyControllerFactory.class);
+
+ /**
+ * Policy Controller Name Index.
+ */
+ private final HashMap<String,PolicyController> policyControllers =
+ new HashMap<>();
+
+ /**
+ * Group/Artifact Ids Index.
+ */
+ private final HashMap<String,PolicyController> coordinates2Controller =
+ new HashMap<>();
+
+ /**
+ * produces key for indexing controller names.
+ *
+ * @param groupId group id
+ * @param artifactId artifact id
+ * @return index key
+ */
+ private String toKey(String groupId, String artifactId) {
+ return groupId + ":" + artifactId;
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public synchronized PolicyController build(String name, Properties properties) {
+
+ if (this.policyControllers.containsKey(name)) {
+ return this.policyControllers.get(name);
+ }
+
+ /* A PolicyController does not exist */
+
+ PolicyController controller = newPolicyController(name, properties);
+
+ String coordinates = toKey(controller.getDrools().getGroupId(),
+ controller.getDrools().getArtifactId());
+
+ this.policyControllers.put(name, controller);
+
+
+ if (controller.getDrools().isBrained()) {
+ this.coordinates2Controller.put(coordinates, controller);
+ }
+
+ return controller;
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public synchronized PolicyController patch(String name, DroolsConfiguration droolsConfig) {
+
+ if (name == null || name.isEmpty() || !this.policyControllers.containsKey(name)) {
+ throw makeArgEx(name);
+ }
+
+ PolicyController controller = this.get(name);
+
+ if (controller == null) {
+ logger.warn("A POLICY CONTROLLER of name {} does not exist for patch operation: {}", name, droolsConfig);
+
+ throw new IllegalArgumentException("Not a valid controller of name " + name);
+ }
+
+ this.patch(controller, droolsConfig);
+
+ logger.info("UPDATED drools configuration: {} on {}", droolsConfig, this);
+
+ return controller;
+ }
+
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void patch(PolicyController controller, DroolsConfiguration droolsConfig) {
+
+ if (controller == null) {
+ throw new IllegalArgumentException("Not a valid controller: null");
+ }
+
+ if (droolsConfig == null) {
+ throw new IllegalArgumentException("Invalid Drools Configuration");
+ }
+
+ if (!controller.updateDrools(droolsConfig)) {
+ logger.warn("Cannot update drools configuration: {} on {}", droolsConfig, this);
+ throw new IllegalArgumentException("Cannot update drools configuration Drools Configuration");
+ }
+
+ logger.info("UPDATED drools configuration: {} on {}", droolsConfig, this);
+
+ String coordinates = toKey(controller.getDrools().getGroupId(),
+ controller.getDrools().getArtifactId());
+
+ if (controller.getDrools().isBrained()) {
+ this.coordinates2Controller.put(coordinates, controller);
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void shutdown(String controllerName) {
+
+ if (controllerName == null || controllerName.isEmpty()) {
+ throw makeArgEx(controllerName);
+ }
+
+ synchronized (this) {
+ if (!this.policyControllers.containsKey(controllerName)) {
+ return;
+ }
+
+ PolicyController controller = this.policyControllers.get(controllerName);
+ this.shutdown(controller);
+ }
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void shutdown(PolicyController controller) {
+ this.unmanage(controller);
+ controller.shutdown();
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void shutdown() {
+ List<PolicyController> controllers = this.inventory();
+ for (PolicyController controller: controllers) {
+ controller.shutdown();
+ }
+
+ synchronized (this) {
+ this.policyControllers.clear();
+ this.coordinates2Controller.clear();
+ }
+ }
+
+ /**
+ * unmanage the controller.
+ *
+ * @param controller controller
+ * @throws IllegalArgumentException exception
+ */
+ private void unmanage(PolicyController controller) {
+ PolicyController tempController = controller;
+ if (tempController == null) {
+ throw new IllegalArgumentException("Invalid Controller");
+ }
+
+ synchronized (this) {
+ if (!this.policyControllers.containsKey(tempController.getName())) {
+ return;
+ }
+ tempController = this.policyControllers.remove(tempController.getName());
+
+ String coordinates = toKey(tempController.getDrools().getGroupId(),
+ tempController.getDrools().getArtifactId());
+ this.coordinates2Controller.remove(coordinates);
+ }
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void destroy(String controllerName) {
+
+ if (controllerName == null || controllerName.isEmpty()) {
+ throw makeArgEx(controllerName);
+ }
+
+ synchronized (this) {
+ if (!this.policyControllers.containsKey(controllerName)) {
+ return;
+ }
+
+ PolicyController controller = this.policyControllers.get(controllerName);
+ this.destroy(controller);
+ }
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void destroy(PolicyController controller) {
+ this.unmanage(controller);
+ controller.halt();
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void destroy() {
+ List<PolicyController> controllers = this.inventory();
+ for (PolicyController controller: controllers) {
+ controller.halt();
+ }
+
+ synchronized (this) {
+ this.policyControllers.clear();
+ this.coordinates2Controller.clear();
+ }
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public PolicyController get(String name) {
+
+ if (name == null || name.isEmpty()) {
+ throw makeArgEx(name);
+ }
+
+ synchronized (this) {
+ if (this.policyControllers.containsKey(name)) {
+ return this.policyControllers.get(name);
+ } else {
+ throw makeArgEx(name);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public PolicyController get(String groupId, String artifactId) {
+
+ if (groupId == null || groupId.isEmpty()
+ || artifactId == null || artifactId.isEmpty()) {
+ throw new IllegalArgumentException("Invalid group/artifact ids");
+ }
+
+ synchronized (this) {
+ String key = toKey(groupId,artifactId);
+ if (this.coordinates2Controller.containsKey(key)) {
+ return this.coordinates2Controller.get(key);
+ } else {
+ throw makeArgEx(key);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public PolicyController get(DroolsController droolsController) {
+
+ if (droolsController == null) {
+ throw new IllegalArgumentException("No Drools Controller provided");
+ }
+
+ synchronized (this) {
+ String key = toKey(droolsController.getGroupId(), droolsController.getArtifactId());
+ if (this.coordinates2Controller.containsKey(key)) {
+ return this.coordinates2Controller.get(key);
+ } else {
+ logger.error("Drools Controller not associated with Policy Controller {}:{}", droolsController, this);
+ throw new IllegalStateException("Drools Controller not associated with Policy Controller "
+ + droolsController + ":" + this);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public List<PolicyController> inventory() {
+ return new ArrayList<>(this.policyControllers.values());
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public List<String> getFeatures() {
+ List<String> features = new ArrayList<>();
+ for (PolicyControllerFeatureApi feature : getProviders()) {
+ features.add(feature.getName());
+ }
+ return features;
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @JsonIgnore
+ @GsonJsonIgnore
+ @Override
+ public List<PolicyControllerFeatureApi> getFeatureProviders() {
+ return getProviders();
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public PolicyControllerFeatureApi getFeatureProvider(String featureName) {
+ if (featureName == null || featureName.isEmpty()) {
+ throw new IllegalArgumentException("A feature name must be provided");
+ }
+
+ for (PolicyControllerFeatureApi feature : getProviders()) {
+ if (feature.getName().equals(featureName)) {
+ return feature;
+ }
+ }
+
+ throw new IllegalArgumentException("Invalid Feature Name: " + featureName);
+ }
+
+ private IllegalArgumentException makeArgEx(String argName) {
+ return new IllegalArgumentException("Invalid " + argName);
+ }
+
+ // these methods can be overridden by junit tests
+
+ protected PolicyController newPolicyController(String name, Properties properties) {
+ return new AggregatedPolicyController(name, properties);
+ }
+
+ protected List<PolicyControllerFeatureApi> getProviders() {
+ return PolicyControllerFeatureApi.providers.getList();
+ }
+}
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 8baf667a..05f15ead 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
@@ -7,9 +7,9 @@
* 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.
@@ -20,19 +20,11 @@
package org.onap.policy.drools.system;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Properties;
-import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
+import org.onap.policy.drools.features.PolicyControllerFeatureApi;
import org.onap.policy.drools.protocol.configuration.DroolsConfiguration;
-import org.onap.policy.drools.system.internal.AggregatedPolicyController;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
@@ -149,21 +141,21 @@ public interface PolicyControllerFactory {
/**
* get features attached to the Policy Controllers.
- *
+ *
* @return list of features
*/
- List<PolicyControllerFeatureAPI> getFeatureProviders();
+ List<PolicyControllerFeatureApi> getFeatureProviders();
/**
* get named feature attached to the Policy Controllers.
- *
+ *
* @return the feature
*/
- PolicyControllerFeatureAPI getFeatureProvider(String featureName);
+ PolicyControllerFeatureApi getFeatureProvider(String featureName);
/**
* get features attached to the Policy Controllers.
- *
+ *
* @return list of features
*/
List<String> getFeatures();
@@ -175,355 +167,3 @@ public interface PolicyControllerFactory {
*/
List<PolicyController> inventory();
}
-
-/**
- * Factory of Policy Controllers indexed by the name of the Policy Controller.
- */
-class IndexedPolicyControllerFactory implements PolicyControllerFactory {
- // get an instance of logger
- private static final Logger logger = LoggerFactory.getLogger(PolicyControllerFactory.class);
-
- /**
- * Policy Controller Name Index.
- */
- private final HashMap<String,PolicyController> policyControllers =
- new HashMap<>();
-
- /**
- * Group/Artifact Ids Index.
- */
- private final HashMap<String,PolicyController> coordinates2Controller =
- new HashMap<>();
-
- /**
- * produces key for indexing controller names.
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @return index key
- */
- private String toKey(String groupId, String artifactId) {
- return groupId + ":" + artifactId;
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public synchronized PolicyController build(String name, Properties properties) {
-
- if (this.policyControllers.containsKey(name)) {
- return this.policyControllers.get(name);
- }
-
- /* A PolicyController does not exist */
-
- PolicyController controller = newPolicyController(name, properties);
-
- String coordinates = toKey(controller.getDrools().getGroupId(),
- controller.getDrools().getArtifactId());
-
- this.policyControllers.put(name, controller);
-
-
- if (controller.getDrools().isBrained()) {
- this.coordinates2Controller.put(coordinates, controller);
- }
-
- return controller;
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public synchronized PolicyController patch(String name, DroolsConfiguration droolsConfig) {
-
- if (name == null || name.isEmpty() || !this.policyControllers.containsKey(name)) {
- throw makeArgEx(name);
- }
-
- PolicyController controller = this.get(name);
-
- if (controller == null) {
- logger.warn("A POLICY CONTROLLER of name {} does not exist for patch operation: {}", name, droolsConfig);
-
- throw new IllegalArgumentException("Not a valid controller of name " + name);
- }
-
- this.patch(controller, droolsConfig);
-
- logger.info("UPDATED drools configuration: {} on {}", droolsConfig, this);
-
- return controller;
- }
-
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public void patch(PolicyController controller, DroolsConfiguration droolsConfig) {
-
- if (controller == null) {
- throw new IllegalArgumentException("Not a valid controller: null");
- }
-
- if (droolsConfig == null) {
- throw new IllegalArgumentException("Invalid Drools Configuration");
- }
-
- if (!controller.updateDrools(droolsConfig)) {
- logger.warn("Cannot update drools configuration: {} on {}", droolsConfig, this);
- throw new IllegalArgumentException("Cannot update drools configuration Drools Configuration");
- }
-
- logger.info("UPDATED drools configuration: {} on {}", droolsConfig, this);
-
- String coordinates = toKey(controller.getDrools().getGroupId(),
- controller.getDrools().getArtifactId());
-
- if (controller.getDrools().isBrained()) {
- this.coordinates2Controller.put(coordinates, controller);
- }
-
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public void shutdown(String controllerName) {
-
- if (controllerName == null || controllerName.isEmpty()) {
- throw makeArgEx(controllerName);
- }
-
- synchronized (this) {
- if (!this.policyControllers.containsKey(controllerName)) {
- return;
- }
-
- PolicyController controller = this.policyControllers.get(controllerName);
- this.shutdown(controller);
- }
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public void shutdown(PolicyController controller) {
- this.unmanage(controller);
- controller.shutdown();
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public void shutdown() {
- List<PolicyController> controllers = this.inventory();
- for (PolicyController controller: controllers) {
- controller.shutdown();
- }
-
- synchronized (this) {
- this.policyControllers.clear();
- this.coordinates2Controller.clear();
- }
- }
-
- /**
- * unmanage the controller.
- *
- * @param controller controller
- * @throws IllegalArgumentException exception
- */
- private void unmanage(PolicyController controller) {
- PolicyController tempController = controller;
- if (tempController == null) {
- throw new IllegalArgumentException("Invalid Controller");
- }
-
- synchronized (this) {
- if (!this.policyControllers.containsKey(tempController.getName())) {
- return;
- }
- tempController = this.policyControllers.remove(tempController.getName());
-
- String coordinates = toKey(tempController.getDrools().getGroupId(),
- tempController.getDrools().getArtifactId());
- this.coordinates2Controller.remove(coordinates);
- }
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public void destroy(String controllerName) {
-
- if (controllerName == null || controllerName.isEmpty()) {
- throw makeArgEx(controllerName);
- }
-
- synchronized (this) {
- if (!this.policyControllers.containsKey(controllerName)) {
- return;
- }
-
- PolicyController controller = this.policyControllers.get(controllerName);
- this.destroy(controller);
- }
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public void destroy(PolicyController controller) {
- this.unmanage(controller);
- controller.halt();
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public void destroy() {
- List<PolicyController> controllers = this.inventory();
- for (PolicyController controller: controllers) {
- controller.halt();
- }
-
- synchronized (this) {
- this.policyControllers.clear();
- this.coordinates2Controller.clear();
- }
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public PolicyController get(String name) {
-
- if (name == null || name.isEmpty()) {
- throw makeArgEx(name);
- }
-
- synchronized (this) {
- if (this.policyControllers.containsKey(name)) {
- return this.policyControllers.get(name);
- } else {
- throw makeArgEx(name);
- }
- }
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public PolicyController get(String groupId, String artifactId) {
-
- if (groupId == null || groupId.isEmpty()
- || artifactId == null || artifactId.isEmpty()) {
- throw new IllegalArgumentException("Invalid group/artifact ids");
- }
-
- synchronized (this) {
- String key = toKey(groupId,artifactId);
- if (this.coordinates2Controller.containsKey(key)) {
- return this.coordinates2Controller.get(key);
- } else {
- throw makeArgEx(key);
- }
- }
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public PolicyController get(DroolsController droolsController) {
-
- if (droolsController == null) {
- throw new IllegalArgumentException("No Drools Controller provided");
- }
-
- synchronized (this) {
- String key = toKey(droolsController.getGroupId(), droolsController.getArtifactId());
- if (this.coordinates2Controller.containsKey(key)) {
- return this.coordinates2Controller.get(key);
- } else {
- logger.error("Drools Controller not associated with Policy Controller {}:{}", droolsController, this);
- throw new IllegalStateException("Drools Controller not associated with Policy Controller "
- + droolsController + ":" + this);
- }
- }
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public List<PolicyController> inventory() {
- return new ArrayList<>(this.policyControllers.values());
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public List<String> getFeatures() {
- List<String> features = new ArrayList<>();
- for (PolicyControllerFeatureAPI feature : getProviders()) {
- features.add(feature.getName());
- }
- return features;
- }
-
- /**
- * {@inheritDoc}.
- */
- @JsonIgnore
- @GsonJsonIgnore
- @Override
- public List<PolicyControllerFeatureAPI> getFeatureProviders() {
- return getProviders();
- }
-
- /**
- * {@inheritDoc}.
- */
- @Override
- public PolicyControllerFeatureAPI getFeatureProvider(String featureName) {
- if (featureName == null || featureName.isEmpty()) {
- throw new IllegalArgumentException("A feature name must be provided");
- }
-
- for (PolicyControllerFeatureAPI feature : getProviders()) {
- if (feature.getName().equals(featureName)) {
- return feature;
- }
- }
-
- throw new IllegalArgumentException("Invalid Feature Name: " + featureName);
- }
-
- private IllegalArgumentException makeArgEx(String argName) {
- return new IllegalArgumentException("Invalid " + argName);
- }
-
- // these methods can be overridden by junit tests
-
- protected PolicyController newPolicyController(String name, Properties properties) {
- return new AggregatedPolicyController(name, properties);
- }
-
- protected List<PolicyControllerFeatureAPI> getProviders() {
- return PolicyControllerFeatureAPI.providers.getList();
- }
-}
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 811a9c80..eb2ed3df 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
@@ -20,47 +20,18 @@
package org.onap.policy.drools.system;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
-
import org.onap.policy.common.capabilities.Lockable;
import org.onap.policy.common.capabilities.Startable;
-import org.onap.policy.common.endpoints.event.comm.Topic;
import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
-import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
-import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
import org.onap.policy.common.endpoints.event.comm.TopicListener;
import org.onap.policy.common.endpoints.event.comm.TopicSink;
import org.onap.policy.common.endpoints.event.comm.TopicSource;
import org.onap.policy.common.endpoints.http.server.HttpServletServer;
-import org.onap.policy.common.endpoints.http.server.HttpServletServerFactory;
-import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
-import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
-import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
-import org.onap.policy.common.gson.annotation.GsonJsonProperty;
-import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.core.PolicyContainer;
-import org.onap.policy.drools.core.jmx.PdpJmxListener;
-import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
-import org.onap.policy.drools.features.PolicyEngineFeatureAPI;
-import org.onap.policy.drools.persistence.SystemPersistence;
-import org.onap.policy.drools.properties.DroolsProperties;
-import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
+import org.onap.policy.drools.features.PolicyEngineFeatureApi;
import org.onap.policy.drools.protocol.configuration.ControllerConfiguration;
import org.onap.policy.drools.protocol.configuration.PdpdConfiguration;
-import org.onap.policy.drools.server.restful.RestManager;
-import org.onap.policy.drools.server.restful.aaf.AafTelemetryAuthFilter;
-import org.onap.policy.drools.utils.PropertyUtil;
-import org.onap.policy.drools.utils.logging.LoggerUtil;
-import org.onap.policy.drools.utils.logging.MDCTransaction;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Policy Engine, the top abstraction for the Drools PDP Policy Engine. It abstracts away a Drools
@@ -249,14 +220,14 @@ public interface PolicyEngine extends Startable, Lockable, TopicListener {
*
* @return list of features
*/
- List<PolicyEngineFeatureAPI> getFeatureProviders();
+ List<PolicyEngineFeatureApi> getFeatureProviders();
/**
* get named feature attached to the Policy Engine.
*
* @return the feature
*/
- PolicyEngineFeatureAPI getFeatureProvider(String featureName);
+ PolicyEngineFeatureApi getFeatureProvider(String featureName);
/**
* get features attached to the Policy Engine.
@@ -336,1268 +307,3 @@ public interface PolicyEngine extends Startable, Lockable, TopicListener {
*/
Properties defaultTelemetryConfig();
}
-
-
-/**
- * Policy Engine Manager Implementation.
- */
-class PolicyEngineManager implements PolicyEngine {
-
- /**
- * String literals.
- */
- private static final String INVALID_TOPIC_MSG = "Invalid Topic";
- private static final String INVALID_EVENT_MSG = "Invalid Event";
-
- private static final String ENGINE_STOPPED_MSG = "Policy Engine is stopped";
- private static final String ENGINE_LOCKED_MSG = "Policy Engine is locked";
-
- /**
- * logger.
- */
- private static final Logger logger = LoggerFactory.getLogger(PolicyEngineManager.class);
-
- /**
- * Is the Policy Engine running.
- */
- private volatile boolean alive = false;
-
- /**
- * Is the engine locked.
- */
- private volatile boolean locked = false;
-
- /**
- * Properties used to initialize the engine.
- */
- private Properties properties;
-
- /**
- * Environment Properties.
- */
- private final Properties environment = new Properties();
-
- /**
- * Policy Engine Sources.
- */
- private List<? extends TopicSource> sources = new ArrayList<>();
-
- /**
- * Policy Engine Sinks.
- */
- private List<? extends TopicSink> sinks = new ArrayList<>();
-
- /**
- * Policy Engine HTTP Servers.
- */
- private List<HttpServletServer> httpServers = new ArrayList<>();
-
- /**
- * gson parser to decode configuration requests.
- */
- private final Gson decoder = new GsonBuilder().disableHtmlEscaping().create();
-
-
- @Override
- public synchronized void boot(String[] cliArgs) {
-
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.beforeBoot(this, cliArgs)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} before-boot failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- try {
- globalInitContainer(cliArgs);
- } catch (final Exception e) {
- logger.error("{}: cannot init policy-container because of {}", this, e.getMessage(), e);
- }
-
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.afterBoot(this)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} after-boot failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
- }
-
- @Override
- public synchronized void setEnvironment(Properties properties) {
- this.environment.putAll(PropertyUtil.getInterpolatedProperties(properties));
- }
-
- @JsonIgnore
- @GsonJsonIgnore
- @Override
- public synchronized Properties getEnvironment() {
- return this.environment;
- }
-
- @Override
- public synchronized String getEnvironmentProperty(String envKey) {
- String value = this.environment.getProperty(envKey);
- if (value == null) {
- value = System.getProperty(envKey);
- if (value == null) {
- value = System.getenv(envKey);
- }
- }
- return value;
- }
-
- @Override
- public synchronized String setEnvironmentProperty(String envKey, String envValue) {
- return (String) this.environment.setProperty(envKey, envValue);
- }
-
- @Override
- public final Properties defaultTelemetryConfig() {
- final Properties defaultConfig = new Properties();
-
- defaultConfig.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES, "TELEMETRY");
- defaultConfig.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
- + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, TELEMETRY_SERVER_DEFAULT_HOST);
- defaultConfig.put(
- PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
- + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX,
- "" + Integer.toString(TELEMETRY_SERVER_DEFAULT_PORT));
- defaultConfig.put(
- PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
- + PolicyEndPointProperties.PROPERTY_HTTP_REST_PACKAGES_SUFFIX,
- RestManager.class.getPackage().getName());
- defaultConfig.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
- + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, "" + Boolean.TRUE);
- defaultConfig.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
- + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "" + Boolean.FALSE);
-
- return defaultConfig;
- }
-
- @Override
- public synchronized void configure(Properties properties) {
-
- if (properties == null) {
- logger.warn("No properties provided");
- throw new IllegalArgumentException("No properties provided");
- }
-
- /* policy-engine dispatch pre configure hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.beforeConfigure(this, properties)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} before-configure failure because of {}", this,
- feature.getClass().getName(), e.getMessage(), e);
- }
- }
-
- this.properties = properties;
-
- try {
- this.sources = getTopicEndpointManager().addTopicSources(properties);
- for (final TopicSource source : this.sources) {
- source.register(this);
- }
- } catch (final Exception e) {
- logger.error("{}: add-sources failed", this, e);
- }
-
- try {
- this.sinks = getTopicEndpointManager().addTopicSinks(properties);
- } catch (final IllegalArgumentException e) {
- logger.error("{}: add-sinks failed", this, e);
- }
-
- try {
- this.httpServers = getServletFactory().build(properties);
- for (HttpServletServer server : this.httpServers) {
- if (server.isAaf()) {
- server.addFilterClass(null, AafTelemetryAuthFilter.class.getName());
- }
- }
- } catch (final IllegalArgumentException e) {
- logger.error("{}: add-http-servers failed", this, e);
- }
-
- /* policy-engine dispatch post configure hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.afterConfigure(this)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} after-configure failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
- }
-
- @Override
- public boolean configure(PdpdConfiguration config) {
-
- if (config == null) {
- throw new IllegalArgumentException("No configuration provided");
- }
-
- final String entity = config.getEntity();
-
- MDCTransaction mdcTrans = MDCTransaction.newTransaction(config.getRequestID(), "brmsgw");
- if (this.getSources().size() == 1) {
- Topic topic = this.getSources().get(0);
- mdcTrans.setServiceName(topic.getTopic()).setRemoteHost(topic.getServers().toString())
- .setTargetEntity(config.getEntity());
- }
-
- switch (entity) {
- case PdpdConfiguration.CONFIG_ENTITY_CONTROLLER:
- boolean success = controllerConfig(config);
- mdcTrans.resetSubTransaction().setStatusCode(success).transaction();
- return success;
- default:
- final String msg = "Configuration Entity is not supported: " + entity;
- mdcTrans.resetSubTransaction().setStatusCode(false).setResponseDescription(msg).flush();
- logger.warn(LoggerUtil.TRANSACTION_LOG_MARKER_NAME, msg);
- throw new IllegalArgumentException(msg);
- }
- }
-
- @Override
- public synchronized PolicyController createPolicyController(String name, Properties properties) {
-
- String tempName = name;
- // check if a PROPERTY_CONTROLLER_NAME property is present
- // if so, override the given name
-
- final String propertyControllerName = properties.getProperty(DroolsProperties.PROPERTY_CONTROLLER_NAME);
- if (propertyControllerName != null && !propertyControllerName.isEmpty()) {
- if (!propertyControllerName.equals(tempName)) {
- throw new IllegalStateException("Proposed name (" + tempName + ") and properties name ("
- + propertyControllerName + ") don't match");
- }
- tempName = propertyControllerName;
- }
-
- PolicyController controller;
- for (final PolicyControllerFeatureAPI controllerFeature : getControllerProviders()) {
- try {
- controller = controllerFeature.beforeCreate(tempName, properties);
- if (controller != null) {
- return controller;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} before-controller-create failure because of {}", this,
- controllerFeature.getClass().getName(), e.getMessage(), e);
- }
- }
-
- controller = getControllerFactory().build(tempName, properties);
- if (this.isLocked()) {
- controller.lock();
- }
-
- // feature hook
- for (final PolicyControllerFeatureAPI controllerFeature : getControllerProviders()) {
- try {
- if (controllerFeature.afterCreate(controller)) {
- return controller;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} after-controller-create failure because of {}", this,
- controllerFeature.getClass().getName(), e.getMessage(), e);
- }
- }
-
- return controller;
- }
-
-
- @Override
- public List<PolicyController> updatePolicyControllers(List<ControllerConfiguration> configControllers) {
-
- final List<PolicyController> policyControllers = new ArrayList<>();
- if (configControllers == null || configControllers.isEmpty()) {
- logger.info("No controller configuration provided: {}", configControllers);
- return policyControllers;
- }
-
- for (final ControllerConfiguration configController : configControllers) {
- MDCTransaction mdcTrans = MDCTransaction.newSubTransaction(null).setTargetEntity(configController.getName())
- .setTargetServiceName(configController.getOperation())
- .setTargetVirtualEntity("" + configController.getDrools());
- try {
- final PolicyController policyController = this.updatePolicyController(configController);
- policyControllers.add(policyController);
- mdcTrans.setStatusCode(true).transaction();
- } catch (final Exception e) {
- mdcTrans.setStatusCode(false).setResponseCode(e.getClass().getName())
- .setResponseDescription(e.getMessage()).flush();
- logger.error(LoggerUtil.TRANSACTION_LOG_MARKER_NAME,
- "{}: cannot update-policy-controllers because of {}", this, e.getMessage(), e);
- }
- }
-
- return policyControllers;
- }
-
- @Override
- public synchronized PolicyController updatePolicyController(ControllerConfiguration configController) {
-
- if (configController == null) {
- throw new IllegalArgumentException("No controller configuration has been provided");
- }
-
- final String controllerName = configController.getName();
- if (controllerName == null || controllerName.isEmpty()) {
- logger.warn("controller-name must be provided");
- throw new IllegalArgumentException("No controller configuration has been provided");
- }
-
- PolicyController policyController = null;
- try {
- final String operation = configController.getOperation();
- if (operation == null || operation.isEmpty()) {
- logger.warn("operation must be provided");
- throw new IllegalArgumentException("operation must be provided");
- }
-
- try {
- policyController = getControllerFactory().get(controllerName);
- } catch (final IllegalArgumentException e) {
- // not found
- logger.warn("Policy Controller " + controllerName + " not found", e);
- }
-
- if (policyController == null) {
-
- if (operation.equalsIgnoreCase(ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_LOCK)
- || operation.equalsIgnoreCase(ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UNLOCK)) {
- throw new IllegalArgumentException(controllerName + " is not available for operation " + operation);
- }
-
- /* Recovery case */
-
- logger.warn("controller {} does not exist. Attempting recovery from disk", controllerName);
-
- final Properties controllerProperties =
- getPersistenceManager().getControllerProperties(controllerName);
-
- /*
- * returned properties cannot be null (per implementation) assert (properties !=
- * null)
- */
-
- if (controllerProperties == null) {
- throw new IllegalArgumentException(controllerName + " is invalid");
- }
-
- logger.warn("controller being recovered. {} Reset controller's bad maven coordinates to brainless",
- controllerName);
-
- /*
- * try to bring up bad controller in brainless mode, after having it working, apply
- * the new create/update operation.
- */
- controllerProperties.setProperty(DroolsProperties.RULES_GROUPID, DroolsController.NO_GROUP_ID);
- controllerProperties.setProperty(DroolsProperties.RULES_ARTIFACTID, DroolsController.NO_ARTIFACT_ID);
- controllerProperties.setProperty(DroolsProperties.RULES_VERSION, DroolsController.NO_VERSION);
-
- policyController = getPolicyEngine().createPolicyController(controllerName, controllerProperties);
-
- /* fall through to do brain update operation */
- }
-
- switch (operation) {
- case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_CREATE:
- getControllerFactory().patch(policyController, configController.getDrools());
- break;
- case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UPDATE:
- policyController.unlock();
- getControllerFactory().patch(policyController, configController.getDrools());
- break;
- case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_LOCK:
- policyController.lock();
- break;
- case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UNLOCK:
- policyController.unlock();
- break;
- default:
- final String msg = "Controller Operation Configuration is not supported: " + operation + " for "
- + controllerName;
- logger.warn(msg);
- throw new IllegalArgumentException(msg);
- }
-
- return policyController;
- } catch (final Exception e) {
- logger.error("{}: cannot update-policy-controller because of {}", this, e.getMessage(), e);
- throw e;
- } catch (final LinkageError e) {
- logger.error("{}: cannot update-policy-controllers (rules) because of {}", this, e.getMessage(), e);
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public synchronized boolean start() {
-
- /* policy-engine dispatch pre start hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.beforeStart(this)) {
- return true;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} before-start failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- boolean success = true;
- if (this.locked) {
- throw new IllegalStateException(ENGINE_LOCKED_MSG);
- }
-
- this.alive = true;
-
- /* Start Policy Engine exclusively-owned (unmanaged) http servers */
-
- for (final HttpServletServer httpServer : this.httpServers) {
- try {
- if (!httpServer.waitedStart(10 * 1000L)) {
- success = false;
- }
- } catch (final Exception e) {
- logger.error("{}: cannot start http-server {} because of {}", this, httpServer, e.getMessage(), e);
- }
- }
-
- /* Start Policy Engine exclusively-owned (unmanaged) sources */
-
- for (final TopicSource source : this.sources) {
- try {
- if (!source.start()) {
- success = false;
- }
- } catch (final Exception e) {
- logger.error("{}: cannot start topic-source {} because of {}", this, source, e.getMessage(), e);
- }
- }
-
- /* Start Policy Engine owned (unmanaged) sinks */
-
- for (final TopicSink sink : this.sinks) {
- try {
- if (!sink.start()) {
- success = false;
- }
- } catch (final Exception e) {
- logger.error("{}: cannot start topic-sink {} because of {}", this, sink, e.getMessage(), e);
- }
- }
-
- /* Start Policy Controllers */
-
- final List<PolicyController> controllers = getControllerFactory().inventory();
- for (final PolicyController controller : controllers) {
- try {
- if (!controller.start()) {
- success = false;
- }
- } catch (final Exception e) {
- logger.error("{}: cannot start policy-controller {} because of {}", this, controller, e.getMessage(),
- e);
- success = false;
- }
- }
-
- /* Start managed Topic Endpoints */
-
- try {
- if (!getTopicEndpointManager().start()) {
- success = false;
- }
- } catch (final IllegalStateException e) {
- logger.warn("{}: Topic Endpoint Manager is in an invalid state because of {}", this, e.getMessage(), e);
- }
-
-
- // Start the JMX listener
-
- startPdpJmxListener();
-
- /* policy-engine dispatch after start hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.afterStart(this)) {
- return success;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} after-start failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- return success;
- }
-
- @Override
- public synchronized boolean stop() {
-
- /* policy-engine dispatch pre stop hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.beforeStop(this)) {
- return true;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} before-stop failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- /* stop regardless of the lock state */
-
- boolean success = true;
- if (!this.alive) {
- return true;
- }
-
- this.alive = false;
-
- final List<PolicyController> controllers = getControllerFactory().inventory();
- for (final PolicyController controller : controllers) {
- try {
- if (!controller.stop()) {
- success = false;
- }
- } catch (final Exception e) {
- logger.error("{}: cannot stop policy-controller {} because of {}", this, controller, e.getMessage(), e);
- success = false;
- }
- }
-
- /* Stop Policy Engine owned (unmanaged) sources */
- for (final TopicSource source : this.sources) {
- try {
- if (!source.stop()) {
- success = false;
- }
- } catch (final Exception e) {
- logger.error("{}: cannot start topic-source {} because of {}", this, source, e.getMessage(), e);
- }
- }
-
- /* Stop Policy Engine owned (unmanaged) sinks */
- for (final TopicSink sink : this.sinks) {
- try {
- if (!sink.stop()) {
- success = false;
- }
- } catch (final Exception e) {
- logger.error("{}: cannot start topic-sink {} because of {}", this, sink, e.getMessage(), e);
- }
- }
-
- /* stop all managed topics sources and sinks */
- if (!getTopicEndpointManager().stop()) {
- success = false;
- }
-
- /* stop all unmanaged http servers */
- for (final HttpServletServer httpServer : this.httpServers) {
- try {
- if (!httpServer.stop()) {
- success = false;
- }
- } catch (final Exception e) {
- logger.error("{}: cannot start http-server {} because of {}", this, httpServer, e.getMessage(), e);
- }
- }
-
- // stop JMX?
-
- /* policy-engine dispatch pre stop hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.afterStop(this)) {
- return success;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} after-stop failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- return success;
- }
-
- @Override
- public synchronized void shutdown() {
-
- /*
- * shutdown activity even when underlying subcomponents (features, controllers, topics, etc
- * ..) are stuck
- */
-
- Thread exitThread = makeShutdownThread();
- exitThread.start();
-
- /* policy-engine dispatch pre shutdown hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.beforeShutdown(this)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} before-shutdown failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- this.alive = false;
-
- /* Shutdown Policy Engine owned (unmanaged) sources */
- for (final TopicSource source : this.sources) {
- try {
- source.shutdown();
- } catch (final Exception e) {
- logger.error("{}: cannot shutdown topic-source {} because of {}", this, source, e.getMessage(), e);
- }
- }
-
- /* Shutdown Policy Engine owned (unmanaged) sinks */
- for (final TopicSink sink : this.sinks) {
- try {
- sink.shutdown();
- } catch (final Exception e) {
- logger.error("{}: cannot shutdown topic-sink {} because of {}", this, sink, e.getMessage(), e);
- }
- }
-
- /* Shutdown managed resources */
- getControllerFactory().shutdown();
- getTopicEndpointManager().shutdown();
- getServletFactory().destroy();
-
- // Stop the JMX listener
-
- stopPdpJmxListener();
-
- /* policy-engine dispatch post shutdown hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.afterShutdown(this)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} after-shutdown failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- exitThread.interrupt();
- logger.info("{}: normal termination", this);
- }
-
- /**
- * Thread that shuts down http servers.
- */
- protected class ShutdownThread extends Thread {
- private static final long SHUTDOWN_MAX_GRACE_TIME = 30000L;
-
- @Override
- public void run() {
- try {
- doSleep(SHUTDOWN_MAX_GRACE_TIME);
- logger.warn("{}: abnormal termination - shutdown graceful time period expiration",
- PolicyEngineManager.this);
- } catch (final InterruptedException e) {
- /* courtesy to shutdown() to allow it to return */
- synchronized (PolicyEngineManager.this) {
- }
- logger.info("{}: finishing a graceful shutdown ", PolicyEngineManager.this, e);
- } finally {
- /*
- * shut down the Policy Engine owned http servers as the very last thing
- */
- for (final HttpServletServer httpServer : PolicyEngineManager.this.getHttpServers()) {
- try {
- httpServer.shutdown();
- } catch (final Exception e) {
- logger.error("{}: cannot shutdown http-server {} because of {}", PolicyEngineManager.this,
- httpServer, e.getMessage(), e);
- }
- }
-
- logger.info("{}: exit", PolicyEngineManager.this);
- doExit(0);
- }
- }
-
- // these may be overridden by junit tests
-
- protected void doSleep(long sleepMs) throws InterruptedException {
- Thread.sleep(sleepMs);
- }
-
- protected void doExit(int code) {
- System.exit(code);
- }
- }
-
- @Override
- public boolean isAlive() {
- return this.alive;
- }
-
- @Override
- public synchronized boolean lock() {
-
- /* policy-engine dispatch pre lock hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.beforeLock(this)) {
- return true;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} before-lock failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- if (this.locked) {
- return true;
- }
-
- this.locked = true;
-
- boolean success = true;
- final List<PolicyController> controllers = getControllerFactory().inventory();
- for (final PolicyController controller : controllers) {
- try {
- success = controller.lock() && success;
- } catch (final Exception e) {
- logger.error("{}: cannot lock policy-controller {} because of {}", this, controller, e.getMessage(), e);
- success = false;
- }
- }
-
- success = getTopicEndpointManager().lock() && success;
-
- /* policy-engine dispatch post lock hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.afterLock(this)) {
- return success;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} after-lock failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- return success;
- }
-
- @Override
- public synchronized boolean unlock() {
-
- /* policy-engine dispatch pre unlock hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.beforeUnlock(this)) {
- return true;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} before-unlock failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- if (!this.locked) {
- return true;
- }
-
- this.locked = false;
-
- boolean success = true;
- final List<PolicyController> controllers = getControllerFactory().inventory();
- for (final PolicyController controller : controllers) {
- try {
- success = controller.unlock() && success;
- } catch (final Exception e) {
- logger.error("{}: cannot unlock policy-controller {} because of {}", this, controller, e.getMessage(),
- e);
- success = false;
- }
- }
-
- success = getTopicEndpointManager().unlock() && success;
-
- /* policy-engine dispatch after unlock hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.afterUnlock(this)) {
- return success;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} after-unlock failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- return success;
- }
-
- @Override
- public boolean isLocked() {
- return this.locked;
- }
-
- @Override
- public void removePolicyController(String name) {
- getControllerFactory().destroy(name);
- }
-
- @Override
- public void removePolicyController(PolicyController controller) {
- getControllerFactory().destroy(controller);
- }
-
- @JsonIgnore
- @GsonJsonIgnore
- @Override
- public List<PolicyController> getPolicyControllers() {
- return getControllerFactory().inventory();
- }
-
- @JsonProperty("controllers")
- @GsonJsonProperty("controllers")
- @Override
- public List<String> getPolicyControllerIds() {
- final List<String> controllerNames = new ArrayList<>();
- for (final PolicyController controller : getControllerFactory().inventory()) {
- controllerNames.add(controller.getName());
- }
- return controllerNames;
- }
-
- @Override
- @JsonIgnore
- @GsonJsonIgnore
- public Properties getProperties() {
- return this.properties;
- }
-
-
- @SuppressWarnings("unchecked")
- @Override
- public List<TopicSource> getSources() {
- return (List<TopicSource>) this.sources;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public List<TopicSink> getSinks() {
- return (List<TopicSink>) this.sinks;
- }
-
- @Override
- public List<HttpServletServer> getHttpServers() {
- return this.httpServers;
- }
-
- @Override
- public List<String> getFeatures() {
- final List<String> features = new ArrayList<>();
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- features.add(feature.getName());
- }
- return features;
- }
-
- @JsonIgnore
- @GsonJsonIgnore
- @Override
- public List<PolicyEngineFeatureAPI> getFeatureProviders() {
- return getEngineProviders();
- }
-
- @Override
- public PolicyEngineFeatureAPI getFeatureProvider(String featureName) {
- if (featureName == null || featureName.isEmpty()) {
- throw new IllegalArgumentException("A feature name must be provided");
- }
-
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- if (feature.getName().equals(featureName)) {
- return feature;
- }
- }
-
- throw new IllegalArgumentException("Invalid Feature Name: " + featureName);
- }
-
- @Override
- public void onTopicEvent(CommInfrastructure commType, String topic, String event) {
- /* policy-engine pre topic event hook */
- for (final PolicyEngineFeatureAPI feature : getFeatureProviders()) {
- try {
- if (feature.beforeOnTopicEvent(this, commType, topic, event)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} beforeOnTopicEvent failure on event {} because of {}", this,
- feature.getClass().getName(), event, e.getMessage(), e);
- }
- }
-
- /* configuration request */
- PdpdConfiguration configuration = null;
- try {
- configuration = this.decoder.fromJson(event, PdpdConfiguration.class);
- this.configure(configuration);
- } catch (final Exception e) {
- logger.error("{}: configuration-error due to {} because of {}", this, event, e.getMessage(), e);
- }
-
- /* policy-engine after topic event hook */
- for (final PolicyEngineFeatureAPI feature : getFeatureProviders()) {
- try {
- if (feature.afterOnTopicEvent(this, configuration, commType, topic, event)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} afterOnTopicEvent failure on event {} because of {}", this,
- feature.getClass().getName(), event, e.getMessage(), e);
- }
- }
- }
-
- @Override
- public boolean deliver(String topic, Object event) {
-
- /*
- * Note this entry point is usually from the DRL
- */
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException(INVALID_TOPIC_MSG);
- }
-
- if (event == null) {
- throw new IllegalArgumentException(INVALID_EVENT_MSG);
- }
-
- if (!this.isAlive()) {
- throw new IllegalStateException(ENGINE_STOPPED_MSG);
- }
-
- if (this.isLocked()) {
- throw new IllegalStateException(ENGINE_LOCKED_MSG);
- }
-
- final List<? extends TopicSink> topicSinks = getTopicEndpointManager().getTopicSinks(topic);
- if (topicSinks == null || topicSinks.size() != 1) {
- throw new IllegalStateException("Cannot ensure correct delivery on topic " + topic + ": " + topicSinks);
- }
-
- return this.deliver(topicSinks.get(0).getTopicCommInfrastructure(), topic, event);
- }
-
- @Override
- public boolean deliver(String busType, String topic, Object event) {
-
- /*
- * Note this entry point is usually from the DRL (one of the reasons busType is String.
- */
-
- if (busType == null || busType.isEmpty()) {
- throw new IllegalArgumentException("Invalid Communication Infrastructure");
- }
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException(INVALID_TOPIC_MSG);
- }
-
- if (event == null) {
- throw new IllegalArgumentException(INVALID_EVENT_MSG);
- }
-
- boolean valid = false;
- for (final Topic.CommInfrastructure comm : Topic.CommInfrastructure.values()) {
- if (comm.name().equals(busType)) {
- valid = true;
- }
- }
-
- if (!valid) {
- throw new IllegalArgumentException("Invalid Communication Infrastructure: " + busType);
- }
-
-
- if (!this.isAlive()) {
- throw new IllegalStateException(ENGINE_STOPPED_MSG);
- }
-
- if (this.isLocked()) {
- throw new IllegalStateException(ENGINE_LOCKED_MSG);
- }
-
-
- return this.deliver(Topic.CommInfrastructure.valueOf(busType), topic, event);
- }
-
- @Override
- public boolean deliver(Topic.CommInfrastructure busType, String topic, Object event) {
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException(INVALID_TOPIC_MSG);
- }
-
- if (event == null) {
- throw new IllegalArgumentException(INVALID_EVENT_MSG);
- }
-
- if (!this.isAlive()) {
- throw new IllegalStateException(ENGINE_STOPPED_MSG);
- }
-
- if (this.isLocked()) {
- throw new IllegalStateException(ENGINE_LOCKED_MSG);
- }
-
- /*
- * Try to send through the controller, this is the preferred way, since it may want to apply
- * additional processing
- */
- try {
- final DroolsController droolsController = getProtocolCoder().getDroolsController(topic, event);
- final PolicyController controller = getControllerFactory().get(droolsController);
- if (controller != null) {
- return controller.deliver(busType, topic, event);
- }
- } catch (final Exception e) {
- logger.warn("{}: cannot find policy-controller to deliver {} over {}:{} because of {}", this, event,
- busType, topic, e.getMessage(), e);
-
- /* continue (try without routing through the controller) */
- }
-
- /*
- * cannot route through the controller, send directly through the topic sink
- */
- try {
- final String json = getProtocolCoder().encode(topic, event);
- return this.deliver(busType, topic, json);
-
- } catch (final Exception e) {
- logger.warn("{}: cannot deliver {} over {}:{} because of {}", this, event, busType, topic, e.getMessage(),
- e);
- throw e;
- }
- }
-
- @Override
- public boolean deliver(Topic.CommInfrastructure busType, String topic, String event) {
-
- if (topic == null || topic.isEmpty()) {
- throw new IllegalArgumentException(INVALID_TOPIC_MSG);
- }
-
- if (event == null || event.isEmpty()) {
- throw new IllegalArgumentException(INVALID_EVENT_MSG);
- }
-
- if (!this.isAlive()) {
- throw new IllegalStateException(ENGINE_STOPPED_MSG);
- }
-
- if (this.isLocked()) {
- throw new IllegalStateException(ENGINE_LOCKED_MSG);
- }
-
- try {
- final TopicSink sink = getTopicEndpointManager().getTopicSink(busType, topic);
-
- if (sink == null) {
- throw new IllegalStateException("Inconsistent State: " + this);
- }
-
- return sink.send(event);
-
- } catch (final Exception e) {
- logger.warn("{}: cannot deliver {} over {}:{} because of {}", this, event, busType, topic, e.getMessage(),
- e);
- throw e;
- }
- }
-
- @Override
- public synchronized void activate() {
-
- /* policy-engine dispatch pre activate hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.beforeActivate(this)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} before-activate failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
-
- // activate 'policy-management'
- for (final PolicyController policyController : this.getPolicyControllers()) {
- try {
- policyController.unlock();
- policyController.start();
- } catch (final Exception e) {
- logger.error("{}: cannot activate of policy-controller {} because of {}", this, policyController,
- e.getMessage(), e);
- } catch (final LinkageError e) {
- logger.error("{}: cannot activate (rules compilation) of policy-controller {} because of {}", this,
- policyController, e.getMessage(), e);
- }
- }
-
- this.unlock();
-
- /* policy-engine dispatch post activate hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.afterActivate(this)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} after-activate failure because of {}", this, feature.getClass().getName(),
- e.getMessage(), e);
- }
- }
- }
-
- @Override
- public synchronized void deactivate() {
-
- /* policy-engine dispatch pre deactivate hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.beforeDeactivate(this)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} before-deactivate failure because of {}", this,
- feature.getClass().getName(), e.getMessage(), e);
- }
- }
-
- this.lock();
-
- for (final PolicyController policyController : this.getPolicyControllers()) {
- try {
- policyController.stop();
- } catch (final Exception | LinkageError e) {
- logger.error("{}: cannot deactivate (stop) policy-controller {} because of {}", this, policyController,
- e.getMessage(), e);
- }
- }
-
- /* policy-engine dispatch post deactivate hook */
- for (final PolicyEngineFeatureAPI feature : getEngineProviders()) {
- try {
- if (feature.afterDeactivate(this)) {
- return;
- }
- } catch (final Exception e) {
- logger.error("{}: feature {} after-deactivate failure because of {}", this,
- feature.getClass().getName(), e.getMessage(), e);
- }
- }
- }
-
- private boolean controllerConfig(PdpdConfiguration config) {
- /* only this one supported for now */
- final List<ControllerConfiguration> configControllers = config.getControllers();
- if (configControllers == null || configControllers.isEmpty()) {
- logger.info("No controller configuration provided: {}", config);
- return false;
- }
-
- final List<PolicyController> policyControllers = this.updatePolicyControllers(config.getControllers());
- boolean success = false;
- if (!(policyControllers == null || policyControllers.isEmpty())
- && (policyControllers.size() == configControllers.size())) {
- success = true;
- }
- return success;
- }
-
- @Override
- public String toString() {
- return "PolicyEngineManager [alive=" + this.alive + ", locked=" + this.locked + "]";
- }
-
- // these methods may be overridden by junit tests
-
- protected List<PolicyEngineFeatureAPI> getEngineProviders() {
- return PolicyEngineFeatureAPI.providers.getList();
- }
-
- protected List<PolicyControllerFeatureAPI> getControllerProviders() {
- return PolicyControllerFeatureAPI.providers.getList();
- }
-
- protected void globalInitContainer(String[] cliArgs) {
- PolicyContainer.globalInit(cliArgs);
- }
-
- protected TopicEndpoint getTopicEndpointManager() {
- return TopicEndpointManager.getManager();
- }
-
- protected HttpServletServerFactory getServletFactory() {
- return HttpServletServerFactoryInstance.getServerFactory();
- }
-
- protected PolicyControllerFactory getControllerFactory() {
- return PolicyController.factory;
- }
-
- protected void startPdpJmxListener() {
- PdpJmxListener.start();
- }
-
- protected void stopPdpJmxListener() {
- PdpJmxListener.stop();
- }
-
- protected Thread makeShutdownThread() {
- return new ShutdownThread();
- }
-
- protected EventProtocolCoder getProtocolCoder() {
- return EventProtocolCoder.manager;
- }
-
- protected SystemPersistence getPersistenceManager() {
- return SystemPersistence.manager;
- }
-
- protected PolicyEngine getPolicyEngine() {
- return PolicyEngine.manager;
- }
-}
-
-
diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngineManager.java b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngineManager.java
new file mode 100644
index 00000000..07202fb9
--- /dev/null
+++ b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngineManager.java
@@ -0,0 +1,1321 @@
+/*
+ * ============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.drools.system;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import org.onap.policy.common.endpoints.event.comm.Topic;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.event.comm.TopicSource;
+import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.common.endpoints.http.server.HttpServletServerFactory;
+import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
+import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
+import org.onap.policy.common.gson.annotation.GsonJsonProperty;
+import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.core.PolicyContainer;
+import org.onap.policy.drools.core.jmx.PdpJmxListener;
+import org.onap.policy.drools.features.PolicyControllerFeatureApi;
+import org.onap.policy.drools.features.PolicyEngineFeatureApi;
+import org.onap.policy.drools.persistence.SystemPersistence;
+import org.onap.policy.drools.properties.DroolsProperties;
+import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
+import org.onap.policy.drools.protocol.configuration.ControllerConfiguration;
+import org.onap.policy.drools.protocol.configuration.PdpdConfiguration;
+import org.onap.policy.drools.server.restful.RestManager;
+import org.onap.policy.drools.server.restful.aaf.AafTelemetryAuthFilter;
+import org.onap.policy.drools.utils.PropertyUtil;
+import org.onap.policy.drools.utils.logging.LoggerUtil;
+import org.onap.policy.drools.utils.logging.MDCTransaction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Policy Engine Manager Implementation.
+ */
+class PolicyEngineManager implements PolicyEngine {
+
+ /**
+ * String literals.
+ */
+ private static final String INVALID_TOPIC_MSG = "Invalid Topic";
+ private static final String INVALID_EVENT_MSG = "Invalid Event";
+
+ private static final String ENGINE_STOPPED_MSG = "Policy Engine is stopped";
+ private static final String ENGINE_LOCKED_MSG = "Policy Engine is locked";
+
+ /**
+ * logger.
+ */
+ private static final Logger logger = LoggerFactory.getLogger(PolicyEngineManager.class);
+
+ /**
+ * Is the Policy Engine running.
+ */
+ private volatile boolean alive = false;
+
+ /**
+ * Is the engine locked.
+ */
+ private volatile boolean locked = false;
+
+ /**
+ * Properties used to initialize the engine.
+ */
+ private Properties properties;
+
+ /**
+ * Environment Properties.
+ */
+ private final Properties environment = new Properties();
+
+ /**
+ * Policy Engine Sources.
+ */
+ private List<? extends TopicSource> sources = new ArrayList<>();
+
+ /**
+ * Policy Engine Sinks.
+ */
+ private List<? extends TopicSink> sinks = new ArrayList<>();
+
+ /**
+ * Policy Engine HTTP Servers.
+ */
+ private List<HttpServletServer> httpServers = new ArrayList<>();
+
+ /**
+ * gson parser to decode configuration requests.
+ */
+ private final Gson decoder = new GsonBuilder().disableHtmlEscaping().create();
+
+
+ @Override
+ public synchronized void boot(String[] cliArgs) {
+
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.beforeBoot(this, cliArgs)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} before-boot failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ try {
+ globalInitContainer(cliArgs);
+ } catch (final Exception e) {
+ logger.error("{}: cannot init policy-container because of {}", this, e.getMessage(), e);
+ }
+
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.afterBoot(this)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} after-boot failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+ }
+
+ @Override
+ public synchronized void setEnvironment(Properties properties) {
+ this.environment.putAll(PropertyUtil.getInterpolatedProperties(properties));
+ }
+
+ @JsonIgnore
+ @GsonJsonIgnore
+ @Override
+ public synchronized Properties getEnvironment() {
+ return this.environment;
+ }
+
+ @Override
+ public synchronized String getEnvironmentProperty(String envKey) {
+ String value = this.environment.getProperty(envKey);
+ if (value == null) {
+ value = System.getProperty(envKey);
+ if (value == null) {
+ value = System.getenv(envKey);
+ }
+ }
+ return value;
+ }
+
+ @Override
+ public synchronized String setEnvironmentProperty(String envKey, String envValue) {
+ return (String) this.environment.setProperty(envKey, envValue);
+ }
+
+ @Override
+ public final Properties defaultTelemetryConfig() {
+ final Properties defaultConfig = new Properties();
+
+ defaultConfig.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES, "TELEMETRY");
+ defaultConfig.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
+ + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, TELEMETRY_SERVER_DEFAULT_HOST);
+ defaultConfig.put(
+ PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
+ + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX,
+ "" + Integer.toString(TELEMETRY_SERVER_DEFAULT_PORT));
+ defaultConfig.put(
+ PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
+ + PolicyEndPointProperties.PROPERTY_HTTP_REST_PACKAGES_SUFFIX,
+ RestManager.class.getPackage().getName());
+ defaultConfig.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
+ + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, "" + Boolean.TRUE);
+ defaultConfig.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + TELEMETRY_SERVER_DEFAULT_NAME
+ + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "" + Boolean.FALSE);
+
+ return defaultConfig;
+ }
+
+ @Override
+ public synchronized void configure(Properties properties) {
+
+ if (properties == null) {
+ logger.warn("No properties provided");
+ throw new IllegalArgumentException("No properties provided");
+ }
+
+ /* policy-engine dispatch pre configure hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.beforeConfigure(this, properties)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} before-configure failure because of {}", this,
+ feature.getClass().getName(), e.getMessage(), e);
+ }
+ }
+
+ this.properties = properties;
+
+ try {
+ this.sources = getTopicEndpointManager().addTopicSources(properties);
+ for (final TopicSource source : this.sources) {
+ source.register(this);
+ }
+ } catch (final Exception e) {
+ logger.error("{}: add-sources failed", this, e);
+ }
+
+ try {
+ this.sinks = getTopicEndpointManager().addTopicSinks(properties);
+ } catch (final IllegalArgumentException e) {
+ logger.error("{}: add-sinks failed", this, e);
+ }
+
+ try {
+ this.httpServers = getServletFactory().build(properties);
+ for (HttpServletServer server : this.httpServers) {
+ if (server.isAaf()) {
+ server.addFilterClass(null, AafTelemetryAuthFilter.class.getName());
+ }
+ }
+ } catch (final IllegalArgumentException e) {
+ logger.error("{}: add-http-servers failed", this, e);
+ }
+
+ /* policy-engine dispatch post configure hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.afterConfigure(this)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} after-configure failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+ }
+
+ @Override
+ public boolean configure(PdpdConfiguration config) {
+
+ if (config == null) {
+ throw new IllegalArgumentException("No configuration provided");
+ }
+
+ final String entity = config.getEntity();
+
+ MDCTransaction mdcTrans = MDCTransaction.newTransaction(config.getRequestId(), "brmsgw");
+ if (this.getSources().size() == 1) {
+ Topic topic = this.getSources().get(0);
+ mdcTrans.setServiceName(topic.getTopic()).setRemoteHost(topic.getServers().toString())
+ .setTargetEntity(config.getEntity());
+ }
+
+ switch (entity) {
+ case PdpdConfiguration.CONFIG_ENTITY_CONTROLLER:
+ boolean success = controllerConfig(config);
+ mdcTrans.resetSubTransaction().setStatusCode(success).transaction();
+ return success;
+ default:
+ final String msg = "Configuration Entity is not supported: " + entity;
+ mdcTrans.resetSubTransaction().setStatusCode(false).setResponseDescription(msg).flush();
+ logger.warn(LoggerUtil.TRANSACTION_LOG_MARKER_NAME, msg);
+ throw new IllegalArgumentException(msg);
+ }
+ }
+
+ @Override
+ public synchronized PolicyController createPolicyController(String name, Properties properties) {
+
+ String tempName = name;
+ // check if a PROPERTY_CONTROLLER_NAME property is present
+ // if so, override the given name
+
+ final String propertyControllerName = properties.getProperty(DroolsProperties.PROPERTY_CONTROLLER_NAME);
+ if (propertyControllerName != null && !propertyControllerName.isEmpty()) {
+ if (!propertyControllerName.equals(tempName)) {
+ throw new IllegalStateException("Proposed name (" + tempName + ") and properties name ("
+ + propertyControllerName + ") don't match");
+ }
+ tempName = propertyControllerName;
+ }
+
+ PolicyController controller;
+ for (final PolicyControllerFeatureApi controllerFeature : getControllerProviders()) {
+ try {
+ controller = controllerFeature.beforeCreate(tempName, properties);
+ if (controller != null) {
+ return controller;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} before-controller-create failure because of {}", this,
+ controllerFeature.getClass().getName(), e.getMessage(), e);
+ }
+ }
+
+ controller = getControllerFactory().build(tempName, properties);
+ if (this.isLocked()) {
+ controller.lock();
+ }
+
+ // feature hook
+ for (final PolicyControllerFeatureApi controllerFeature : getControllerProviders()) {
+ try {
+ if (controllerFeature.afterCreate(controller)) {
+ return controller;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} after-controller-create failure because of {}", this,
+ controllerFeature.getClass().getName(), e.getMessage(), e);
+ }
+ }
+
+ return controller;
+ }
+
+
+ @Override
+ public List<PolicyController> updatePolicyControllers(List<ControllerConfiguration> configControllers) {
+
+ final List<PolicyController> policyControllers = new ArrayList<>();
+ if (configControllers == null || configControllers.isEmpty()) {
+ logger.info("No controller configuration provided: {}", configControllers);
+ return policyControllers;
+ }
+
+ for (final ControllerConfiguration configController : configControllers) {
+ MDCTransaction mdcTrans = MDCTransaction.newSubTransaction(null).setTargetEntity(configController.getName())
+ .setTargetServiceName(configController.getOperation())
+ .setTargetVirtualEntity("" + configController.getDrools());
+ try {
+ final PolicyController policyController = this.updatePolicyController(configController);
+ policyControllers.add(policyController);
+ mdcTrans.setStatusCode(true).transaction();
+ } catch (final Exception e) {
+ mdcTrans.setStatusCode(false).setResponseCode(e.getClass().getName())
+ .setResponseDescription(e.getMessage()).flush();
+ logger.error(LoggerUtil.TRANSACTION_LOG_MARKER_NAME,
+ "{}: cannot update-policy-controllers because of {}", this, e.getMessage(), e);
+ }
+ }
+
+ return policyControllers;
+ }
+
+ @Override
+ public synchronized PolicyController updatePolicyController(ControllerConfiguration configController) {
+
+ if (configController == null) {
+ throw new IllegalArgumentException("No controller configuration has been provided");
+ }
+
+ final String controllerName = configController.getName();
+ if (controllerName == null || controllerName.isEmpty()) {
+ logger.warn("controller-name must be provided");
+ throw new IllegalArgumentException("No controller configuration has been provided");
+ }
+
+ PolicyController policyController = null;
+ try {
+ final String operation = configController.getOperation();
+ if (operation == null || operation.isEmpty()) {
+ logger.warn("operation must be provided");
+ throw new IllegalArgumentException("operation must be provided");
+ }
+
+ try {
+ policyController = getControllerFactory().get(controllerName);
+ } catch (final IllegalArgumentException e) {
+ // not found
+ logger.warn("Policy Controller " + controllerName + " not found", e);
+ }
+
+ if (policyController == null) {
+
+ if (operation.equalsIgnoreCase(ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_LOCK)
+ || operation.equalsIgnoreCase(ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UNLOCK)) {
+ throw new IllegalArgumentException(controllerName + " is not available for operation " + operation);
+ }
+
+ /* Recovery case */
+
+ logger.warn("controller {} does not exist. Attempting recovery from disk", controllerName);
+
+ final Properties controllerProperties =
+ getPersistenceManager().getControllerProperties(controllerName);
+
+ /*
+ * returned properties cannot be null (per implementation) assert (properties !=
+ * null)
+ */
+
+ if (controllerProperties == null) {
+ throw new IllegalArgumentException(controllerName + " is invalid");
+ }
+
+ logger.warn("controller being recovered. {} Reset controller's bad maven coordinates to brainless",
+ controllerName);
+
+ /*
+ * try to bring up bad controller in brainless mode, after having it working, apply
+ * the new create/update operation.
+ */
+ controllerProperties.setProperty(DroolsProperties.RULES_GROUPID, DroolsController.NO_GROUP_ID);
+ controllerProperties.setProperty(DroolsProperties.RULES_ARTIFACTID, DroolsController.NO_ARTIFACT_ID);
+ controllerProperties.setProperty(DroolsProperties.RULES_VERSION, DroolsController.NO_VERSION);
+
+ policyController = getPolicyEngine().createPolicyController(controllerName, controllerProperties);
+
+ /* fall through to do brain update operation */
+ }
+
+ switch (operation) {
+ case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_CREATE:
+ getControllerFactory().patch(policyController, configController.getDrools());
+ break;
+ case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UPDATE:
+ policyController.unlock();
+ getControllerFactory().patch(policyController, configController.getDrools());
+ break;
+ case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_LOCK:
+ policyController.lock();
+ break;
+ case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UNLOCK:
+ policyController.unlock();
+ break;
+ default:
+ final String msg = "Controller Operation Configuration is not supported: " + operation + " for "
+ + controllerName;
+ logger.warn(msg);
+ throw new IllegalArgumentException(msg);
+ }
+
+ return policyController;
+ } catch (final Exception e) {
+ logger.error("{}: cannot update-policy-controller because of {}", this, e.getMessage(), e);
+ throw e;
+ } catch (final LinkageError e) {
+ logger.error("{}: cannot update-policy-controllers (rules) because of {}", this, e.getMessage(), e);
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public synchronized boolean start() {
+
+ /* policy-engine dispatch pre start hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.beforeStart(this)) {
+ return true;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} before-start failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ boolean success = true;
+ if (this.locked) {
+ throw new IllegalStateException(ENGINE_LOCKED_MSG);
+ }
+
+ this.alive = true;
+
+ /* Start Policy Engine exclusively-owned (unmanaged) http servers */
+
+ for (final HttpServletServer httpServer : this.httpServers) {
+ try {
+ if (!httpServer.waitedStart(10 * 1000L)) {
+ success = false;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: cannot start http-server {} because of {}", this, httpServer, e.getMessage(), e);
+ }
+ }
+
+ /* Start Policy Engine exclusively-owned (unmanaged) sources */
+
+ for (final TopicSource source : this.sources) {
+ try {
+ if (!source.start()) {
+ success = false;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: cannot start topic-source {} because of {}", this, source, e.getMessage(), e);
+ }
+ }
+
+ /* Start Policy Engine owned (unmanaged) sinks */
+
+ for (final TopicSink sink : this.sinks) {
+ try {
+ if (!sink.start()) {
+ success = false;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: cannot start topic-sink {} because of {}", this, sink, e.getMessage(), e);
+ }
+ }
+
+ /* Start Policy Controllers */
+
+ final List<PolicyController> controllers = getControllerFactory().inventory();
+ for (final PolicyController controller : controllers) {
+ try {
+ if (!controller.start()) {
+ success = false;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: cannot start policy-controller {} because of {}", this, controller, e.getMessage(),
+ e);
+ success = false;
+ }
+ }
+
+ /* Start managed Topic Endpoints */
+
+ try {
+ if (!getTopicEndpointManager().start()) {
+ success = false;
+ }
+ } catch (final IllegalStateException e) {
+ logger.warn("{}: Topic Endpoint Manager is in an invalid state because of {}", this, e.getMessage(), e);
+ }
+
+
+ // Start the JMX listener
+
+ startPdpJmxListener();
+
+ /* policy-engine dispatch after start hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.afterStart(this)) {
+ return success;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} after-start failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ return success;
+ }
+
+ @Override
+ public synchronized boolean stop() {
+
+ /* policy-engine dispatch pre stop hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.beforeStop(this)) {
+ return true;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} before-stop failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ /* stop regardless of the lock state */
+
+ boolean success = true;
+ if (!this.alive) {
+ return true;
+ }
+
+ this.alive = false;
+
+ final List<PolicyController> controllers = getControllerFactory().inventory();
+ for (final PolicyController controller : controllers) {
+ try {
+ if (!controller.stop()) {
+ success = false;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: cannot stop policy-controller {} because of {}", this, controller, e.getMessage(), e);
+ success = false;
+ }
+ }
+
+ /* Stop Policy Engine owned (unmanaged) sources */
+ for (final TopicSource source : this.sources) {
+ try {
+ if (!source.stop()) {
+ success = false;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: cannot start topic-source {} because of {}", this, source, e.getMessage(), e);
+ }
+ }
+
+ /* Stop Policy Engine owned (unmanaged) sinks */
+ for (final TopicSink sink : this.sinks) {
+ try {
+ if (!sink.stop()) {
+ success = false;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: cannot start topic-sink {} because of {}", this, sink, e.getMessage(), e);
+ }
+ }
+
+ /* stop all managed topics sources and sinks */
+ if (!getTopicEndpointManager().stop()) {
+ success = false;
+ }
+
+ /* stop all unmanaged http servers */
+ for (final HttpServletServer httpServer : this.httpServers) {
+ try {
+ if (!httpServer.stop()) {
+ success = false;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: cannot start http-server {} because of {}", this, httpServer, e.getMessage(), e);
+ }
+ }
+
+ // stop JMX?
+
+ /* policy-engine dispatch pre stop hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.afterStop(this)) {
+ return success;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} after-stop failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ return success;
+ }
+
+ @Override
+ public synchronized void shutdown() {
+
+ /*
+ * shutdown activity even when underlying subcomponents (features, controllers, topics, etc
+ * ..) are stuck
+ */
+
+ Thread exitThread = makeShutdownThread();
+ exitThread.start();
+
+ /* policy-engine dispatch pre shutdown hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.beforeShutdown(this)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} before-shutdown failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ this.alive = false;
+
+ /* Shutdown Policy Engine owned (unmanaged) sources */
+ for (final TopicSource source : this.sources) {
+ try {
+ source.shutdown();
+ } catch (final Exception e) {
+ logger.error("{}: cannot shutdown topic-source {} because of {}", this, source, e.getMessage(), e);
+ }
+ }
+
+ /* Shutdown Policy Engine owned (unmanaged) sinks */
+ for (final TopicSink sink : this.sinks) {
+ try {
+ sink.shutdown();
+ } catch (final Exception e) {
+ logger.error("{}: cannot shutdown topic-sink {} because of {}", this, sink, e.getMessage(), e);
+ }
+ }
+
+ /* Shutdown managed resources */
+ getControllerFactory().shutdown();
+ getTopicEndpointManager().shutdown();
+ getServletFactory().destroy();
+
+ // Stop the JMX listener
+
+ stopPdpJmxListener();
+
+ /* policy-engine dispatch post shutdown hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.afterShutdown(this)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} after-shutdown failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ exitThread.interrupt();
+ logger.info("{}: normal termination", this);
+ }
+
+ /**
+ * Thread that shuts down http servers.
+ */
+ protected class ShutdownThread extends Thread {
+ private static final long SHUTDOWN_MAX_GRACE_TIME = 30000L;
+
+ @Override
+ public void run() {
+ try {
+ doSleep(SHUTDOWN_MAX_GRACE_TIME);
+ logger.warn("{}: abnormal termination - shutdown graceful time period expiration",
+ PolicyEngineManager.this);
+ } catch (final InterruptedException e) {
+ /* courtesy to shutdown() to allow it to return */
+ synchronized (PolicyEngineManager.this) {
+ }
+ logger.info("{}: finishing a graceful shutdown ", PolicyEngineManager.this, e);
+ } finally {
+ /*
+ * shut down the Policy Engine owned http servers as the very last thing
+ */
+ for (final HttpServletServer httpServer : PolicyEngineManager.this.getHttpServers()) {
+ try {
+ httpServer.shutdown();
+ } catch (final Exception e) {
+ logger.error("{}: cannot shutdown http-server {} because of {}", PolicyEngineManager.this,
+ httpServer, e.getMessage(), e);
+ }
+ }
+
+ logger.info("{}: exit", PolicyEngineManager.this);
+ doExit(0);
+ }
+ }
+
+ // these may be overridden by junit tests
+
+ protected void doSleep(long sleepMs) throws InterruptedException {
+ Thread.sleep(sleepMs);
+ }
+
+ protected void doExit(int code) {
+ System.exit(code);
+ }
+ }
+
+ @Override
+ public boolean isAlive() {
+ return this.alive;
+ }
+
+ @Override
+ public synchronized boolean lock() {
+
+ /* policy-engine dispatch pre lock hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.beforeLock(this)) {
+ return true;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} before-lock failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ if (this.locked) {
+ return true;
+ }
+
+ this.locked = true;
+
+ boolean success = true;
+ final List<PolicyController> controllers = getControllerFactory().inventory();
+ for (final PolicyController controller : controllers) {
+ try {
+ success = controller.lock() && success;
+ } catch (final Exception e) {
+ logger.error("{}: cannot lock policy-controller {} because of {}", this, controller, e.getMessage(), e);
+ success = false;
+ }
+ }
+
+ success = getTopicEndpointManager().lock() && success;
+
+ /* policy-engine dispatch post lock hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.afterLock(this)) {
+ return success;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} after-lock failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ return success;
+ }
+
+ @Override
+ public synchronized boolean unlock() {
+
+ /* policy-engine dispatch pre unlock hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.beforeUnlock(this)) {
+ return true;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} before-unlock failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ if (!this.locked) {
+ return true;
+ }
+
+ this.locked = false;
+
+ boolean success = true;
+ final List<PolicyController> controllers = getControllerFactory().inventory();
+ for (final PolicyController controller : controllers) {
+ try {
+ success = controller.unlock() && success;
+ } catch (final Exception e) {
+ logger.error("{}: cannot unlock policy-controller {} because of {}", this, controller, e.getMessage(),
+ e);
+ success = false;
+ }
+ }
+
+ success = getTopicEndpointManager().unlock() && success;
+
+ /* policy-engine dispatch after unlock hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.afterUnlock(this)) {
+ return success;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} after-unlock failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ return success;
+ }
+
+ @Override
+ public boolean isLocked() {
+ return this.locked;
+ }
+
+ @Override
+ public void removePolicyController(String name) {
+ getControllerFactory().destroy(name);
+ }
+
+ @Override
+ public void removePolicyController(PolicyController controller) {
+ getControllerFactory().destroy(controller);
+ }
+
+ @JsonIgnore
+ @GsonJsonIgnore
+ @Override
+ public List<PolicyController> getPolicyControllers() {
+ return getControllerFactory().inventory();
+ }
+
+ @JsonProperty("controllers")
+ @GsonJsonProperty("controllers")
+ @Override
+ public List<String> getPolicyControllerIds() {
+ final List<String> controllerNames = new ArrayList<>();
+ for (final PolicyController controller : getControllerFactory().inventory()) {
+ controllerNames.add(controller.getName());
+ }
+ return controllerNames;
+ }
+
+ @Override
+ @JsonIgnore
+ @GsonJsonIgnore
+ public Properties getProperties() {
+ return this.properties;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<TopicSource> getSources() {
+ return (List<TopicSource>) this.sources;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<TopicSink> getSinks() {
+ return (List<TopicSink>) this.sinks;
+ }
+
+ @Override
+ public List<HttpServletServer> getHttpServers() {
+ return this.httpServers;
+ }
+
+ @Override
+ public List<String> getFeatures() {
+ final List<String> features = new ArrayList<>();
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ features.add(feature.getName());
+ }
+ return features;
+ }
+
+ @JsonIgnore
+ @GsonJsonIgnore
+ @Override
+ public List<PolicyEngineFeatureApi> getFeatureProviders() {
+ return getEngineProviders();
+ }
+
+ @Override
+ public PolicyEngineFeatureApi getFeatureProvider(String featureName) {
+ if (featureName == null || featureName.isEmpty()) {
+ throw new IllegalArgumentException("A feature name must be provided");
+ }
+
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ if (feature.getName().equals(featureName)) {
+ return feature;
+ }
+ }
+
+ throw new IllegalArgumentException("Invalid Feature Name: " + featureName);
+ }
+
+ @Override
+ public void onTopicEvent(CommInfrastructure commType, String topic, String event) {
+ /* policy-engine pre topic event hook */
+ for (final PolicyEngineFeatureApi feature : getFeatureProviders()) {
+ try {
+ if (feature.beforeOnTopicEvent(this, commType, topic, event)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} beforeOnTopicEvent failure on event {} because of {}", this,
+ feature.getClass().getName(), event, e.getMessage(), e);
+ }
+ }
+
+ /* configuration request */
+ PdpdConfiguration configuration = null;
+ try {
+ configuration = this.decoder.fromJson(event, PdpdConfiguration.class);
+ this.configure(configuration);
+ } catch (final Exception e) {
+ logger.error("{}: configuration-error due to {} because of {}", this, event, e.getMessage(), e);
+ }
+
+ /* policy-engine after topic event hook */
+ for (final PolicyEngineFeatureApi feature : getFeatureProviders()) {
+ try {
+ if (feature.afterOnTopicEvent(this, configuration, commType, topic, event)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} afterOnTopicEvent failure on event {} because of {}", this,
+ feature.getClass().getName(), event, e.getMessage(), e);
+ }
+ }
+ }
+
+ @Override
+ public boolean deliver(String topic, Object event) {
+
+ /*
+ * Note this entry point is usually from the DRL
+ */
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_TOPIC_MSG);
+ }
+
+ if (event == null) {
+ throw new IllegalArgumentException(INVALID_EVENT_MSG);
+ }
+
+ if (!this.isAlive()) {
+ throw new IllegalStateException(ENGINE_STOPPED_MSG);
+ }
+
+ if (this.isLocked()) {
+ throw new IllegalStateException(ENGINE_LOCKED_MSG);
+ }
+
+ final List<? extends TopicSink> topicSinks = getTopicEndpointManager().getTopicSinks(topic);
+ if (topicSinks == null || topicSinks.size() != 1) {
+ throw new IllegalStateException("Cannot ensure correct delivery on topic " + topic + ": " + topicSinks);
+ }
+
+ return this.deliver(topicSinks.get(0).getTopicCommInfrastructure(), topic, event);
+ }
+
+ @Override
+ public boolean deliver(String busType, String topic, Object event) {
+
+ /*
+ * Note this entry point is usually from the DRL (one of the reasons busType is String.
+ */
+
+ if (busType == null || busType.isEmpty()) {
+ throw new IllegalArgumentException("Invalid Communication Infrastructure");
+ }
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_TOPIC_MSG);
+ }
+
+ if (event == null) {
+ throw new IllegalArgumentException(INVALID_EVENT_MSG);
+ }
+
+ boolean valid = false;
+ for (final Topic.CommInfrastructure comm : Topic.CommInfrastructure.values()) {
+ if (comm.name().equals(busType)) {
+ valid = true;
+ }
+ }
+
+ if (!valid) {
+ throw new IllegalArgumentException("Invalid Communication Infrastructure: " + busType);
+ }
+
+
+ if (!this.isAlive()) {
+ throw new IllegalStateException(ENGINE_STOPPED_MSG);
+ }
+
+ if (this.isLocked()) {
+ throw new IllegalStateException(ENGINE_LOCKED_MSG);
+ }
+
+
+ return this.deliver(Topic.CommInfrastructure.valueOf(busType), topic, event);
+ }
+
+ @Override
+ public boolean deliver(Topic.CommInfrastructure busType, String topic, Object event) {
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_TOPIC_MSG);
+ }
+
+ if (event == null) {
+ throw new IllegalArgumentException(INVALID_EVENT_MSG);
+ }
+
+ if (!this.isAlive()) {
+ throw new IllegalStateException(ENGINE_STOPPED_MSG);
+ }
+
+ if (this.isLocked()) {
+ throw new IllegalStateException(ENGINE_LOCKED_MSG);
+ }
+
+ /*
+ * Try to send through the controller, this is the preferred way, since it may want to apply
+ * additional processing
+ */
+ try {
+ final DroolsController droolsController = getProtocolCoder().getDroolsController(topic, event);
+ final PolicyController controller = getControllerFactory().get(droolsController);
+ if (controller != null) {
+ return controller.deliver(busType, topic, event);
+ }
+ } catch (final Exception e) {
+ logger.warn("{}: cannot find policy-controller to deliver {} over {}:{} because of {}", this, event,
+ busType, topic, e.getMessage(), e);
+
+ /* continue (try without routing through the controller) */
+ }
+
+ /*
+ * cannot route through the controller, send directly through the topic sink
+ */
+ try {
+ final String json = getProtocolCoder().encode(topic, event);
+ return this.deliver(busType, topic, json);
+
+ } catch (final Exception e) {
+ logger.warn("{}: cannot deliver {} over {}:{} because of {}", this, event, busType, topic, e.getMessage(),
+ e);
+ throw e;
+ }
+ }
+
+ @Override
+ public boolean deliver(Topic.CommInfrastructure busType, String topic, String event) {
+
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_TOPIC_MSG);
+ }
+
+ if (event == null || event.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_EVENT_MSG);
+ }
+
+ if (!this.isAlive()) {
+ throw new IllegalStateException(ENGINE_STOPPED_MSG);
+ }
+
+ if (this.isLocked()) {
+ throw new IllegalStateException(ENGINE_LOCKED_MSG);
+ }
+
+ try {
+ final TopicSink sink = getTopicEndpointManager().getTopicSink(busType, topic);
+
+ if (sink == null) {
+ throw new IllegalStateException("Inconsistent State: " + this);
+ }
+
+ return sink.send(event);
+
+ } catch (final Exception e) {
+ logger.warn("{}: cannot deliver {} over {}:{} because of {}", this, event, busType, topic, e.getMessage(),
+ e);
+ throw e;
+ }
+ }
+
+ @Override
+ public synchronized void activate() {
+
+ /* policy-engine dispatch pre activate hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.beforeActivate(this)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} before-activate failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+
+ // activate 'policy-management'
+ for (final PolicyController policyController : this.getPolicyControllers()) {
+ try {
+ policyController.unlock();
+ policyController.start();
+ } catch (final Exception e) {
+ logger.error("{}: cannot activate of policy-controller {} because of {}", this, policyController,
+ e.getMessage(), e);
+ } catch (final LinkageError e) {
+ logger.error("{}: cannot activate (rules compilation) of policy-controller {} because of {}", this,
+ policyController, e.getMessage(), e);
+ }
+ }
+
+ this.unlock();
+
+ /* policy-engine dispatch post activate hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.afterActivate(this)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} after-activate failure because of {}", this, feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+ }
+
+ @Override
+ public synchronized void deactivate() {
+
+ /* policy-engine dispatch pre deactivate hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.beforeDeactivate(this)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} before-deactivate failure because of {}", this,
+ feature.getClass().getName(), e.getMessage(), e);
+ }
+ }
+
+ this.lock();
+
+ for (final PolicyController policyController : this.getPolicyControllers()) {
+ try {
+ policyController.stop();
+ } catch (final Exception | LinkageError e) {
+ logger.error("{}: cannot deactivate (stop) policy-controller {} because of {}", this, policyController,
+ e.getMessage(), e);
+ }
+ }
+
+ /* policy-engine dispatch post deactivate hook */
+ for (final PolicyEngineFeatureApi feature : getEngineProviders()) {
+ try {
+ if (feature.afterDeactivate(this)) {
+ return;
+ }
+ } catch (final Exception e) {
+ logger.error("{}: feature {} after-deactivate failure because of {}", this,
+ feature.getClass().getName(), e.getMessage(), e);
+ }
+ }
+ }
+
+ private boolean controllerConfig(PdpdConfiguration config) {
+ /* only this one supported for now */
+ final List<ControllerConfiguration> configControllers = config.getControllers();
+ if (configControllers == null || configControllers.isEmpty()) {
+ logger.info("No controller configuration provided: {}", config);
+ return false;
+ }
+
+ final List<PolicyController> policyControllers = this.updatePolicyControllers(config.getControllers());
+ boolean success = false;
+ if (!(policyControllers == null || policyControllers.isEmpty())
+ && (policyControllers.size() == configControllers.size())) {
+ success = true;
+ }
+ return success;
+ }
+
+ @Override
+ public String toString() {
+ return "PolicyEngineManager [alive=" + this.alive + ", locked=" + this.locked + "]";
+ }
+
+ // these methods may be overridden by junit tests
+
+ protected List<PolicyEngineFeatureApi> getEngineProviders() {
+ return PolicyEngineFeatureApi.providers.getList();
+ }
+
+ protected List<PolicyControllerFeatureApi> getControllerProviders() {
+ return PolicyControllerFeatureApi.providers.getList();
+ }
+
+ protected void globalInitContainer(String[] cliArgs) {
+ PolicyContainer.globalInit(cliArgs);
+ }
+
+ protected TopicEndpoint getTopicEndpointManager() {
+ return TopicEndpointManager.getManager();
+ }
+
+ protected HttpServletServerFactory getServletFactory() {
+ return HttpServletServerFactoryInstance.getServerFactory();
+ }
+
+ protected PolicyControllerFactory getControllerFactory() {
+ return PolicyController.factory;
+ }
+
+ protected void startPdpJmxListener() {
+ PdpJmxListener.start();
+ }
+
+ protected void stopPdpJmxListener() {
+ PdpJmxListener.stop();
+ }
+
+ protected Thread makeShutdownThread() {
+ return new ShutdownThread();
+ }
+
+ protected EventProtocolCoder getProtocolCoder() {
+ return EventProtocolCoder.manager;
+ }
+
+ protected SystemPersistence getPersistenceManager() {
+ return SystemPersistence.manager;
+ }
+
+ protected PolicyEngine getPolicyEngine() {
+ return PolicyEngine.manager;
+ }
+}
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 bdcb19ad..51280eb3 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
@@ -36,7 +36,7 @@ import org.onap.policy.common.endpoints.event.comm.TopicSource;
import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
import org.onap.policy.drools.controller.DroolsController;
import org.onap.policy.drools.controller.DroolsControllerFactory;
-import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
+import org.onap.policy.drools.features.PolicyControllerFeatureApi;
import org.onap.policy.drools.persistence.SystemPersistence;
import org.onap.policy.drools.properties.DroolsProperties;
import org.onap.policy.drools.protocol.configuration.DroolsConfiguration;
@@ -268,7 +268,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
public boolean start() {
logger.info("{}: start", this);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.beforeStart(this)) {
return true;
@@ -307,7 +307,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
}
}
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.afterStart(this)) {
return true;
@@ -328,7 +328,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
public boolean stop() {
logger.info("{}: stop", this);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.beforeStop(this)) {
return true;
@@ -357,7 +357,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
boolean success = this.droolsController.stop();
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.afterStop(this)) {
return true;
@@ -378,7 +378,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
public void shutdown() {
logger.info("{}: shutdown", this);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.beforeShutdown(this)) {
return;
@@ -393,7 +393,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
getDroolsFactory().shutdown(this.droolsController);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.afterShutdown(this)) {
return;
@@ -412,7 +412,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
public void halt() {
logger.info("{}: halt", this);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.beforeHalt(this)) {
return;
@@ -427,7 +427,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
getDroolsFactory().destroy(this.droolsController);
getPersistenceManager().deleteController(this.name);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.afterHalt(this)) {
return;
@@ -450,7 +450,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
return;
}
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.beforeOffer(this, commType, topic, event)) {
return;
@@ -463,7 +463,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
boolean success = this.droolsController.offer(topic, event);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.afterOffer(this, commType, topic, event, success)) {
return;
@@ -483,7 +483,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
return true;
}
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.beforeOffer(this, event)) {
return true;
@@ -496,7 +496,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
boolean success = this.droolsController.offer(event);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.afterOffer(this, event, success)) {
return success;
@@ -522,7 +522,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
logger.debug("{}: deliver event to {}:{}: {}", this, commType, topic, event);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.beforeDeliver(this, commType, topic, event)) {
return true;
@@ -557,7 +557,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
boolean success = this.droolsController.deliver(this.topic2Sinks.get(topic), event);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.afterDeliver(this, commType, topic, event, success)) {
return success;
@@ -586,7 +586,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
public boolean lock() {
logger.info("{}: lock", this);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.beforeLock(this)) {
return true;
@@ -610,7 +610,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
boolean success = this.droolsController.lock();
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.afterLock(this)) {
return true;
@@ -632,7 +632,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
logger.info("{}: unlock", this);
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.beforeUnlock(this)) {
return true;
@@ -653,7 +653,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
boolean success = this.droolsController.unlock();
- for (PolicyControllerFeatureAPI feature : getProviders()) {
+ for (PolicyControllerFeatureApi feature : getProviders()) {
try {
if (feature.afterUnlock(this)) {
return true;
@@ -730,8 +730,8 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
return DroolsController.factory;
}
- protected List<PolicyControllerFeatureAPI> getProviders() {
- return PolicyControllerFeatureAPI.providers.getList();
+ protected List<PolicyControllerFeatureApi> getProviders() {
+ return PolicyControllerFeatureApi.providers.getList();
}
}