aboutsummaryrefslogtreecommitdiffstats
path: root/policy-management/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'policy-management/src/main')
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java58
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java182
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java1653
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java292
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureAPI.java48
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureAPI.java416
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/features/PolicyEngineFeatureAPI.java372
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java485
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/persistence/SystemPersistence.java179
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java2626
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java685
11 files changed, 3610 insertions, 3386 deletions
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java
index 7f68930e..c582a1c0 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java
@@ -30,67 +30,67 @@ import org.onap.policy.drools.core.PolicyContainer;
import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
/**
- * Drools Controller is the abstractions that wraps the drools layer (policy-core)
+ * Drools Controller is the abstractions that wraps the drools layer (policy-core).
*/
public interface DroolsController extends Startable, Lockable {
/**
- * No Group ID identifier
+ * No Group ID identifier.
*/
public static final String NO_GROUP_ID = "NO-GROUP-ID";
/**
- * No Artifact ID identifier
+ * No Artifact ID identifier.
*/
public static final String NO_ARTIFACT_ID = "NO-ARTIFACT-ID";
/**
- * No version identifier
+ * No version identifier.
*/
public static final String NO_VERSION = "NO-VERSION";
/**
- * Factory to track and manage drools controllers
+ * Factory to track and manage drools controllers.
*/
public static final DroolsControllerFactory factory = new IndexedDroolsControllerFactory();
/**
- * get group id
+ * get group id.
*
* @return group id
*/
public String getGroupId();
/**
- * get artifact id
+ * get artifact id.
*
* @return artifact id
*/
public String getArtifactId();
/**
- * get version
+ * get version.
*
* @return version
*/
public String getVersion();
/**
- * return the policy session names
+ * return the policy session names.
*
* @return policy session
*/
public List<String> getSessionNames();
/**
- * return the policy full session names
+ * return the policy full session names.
*
* @return policy session
*/
public List<String> getCanonicalSessionNames();
/**
- * offers an event to this controller for processing
+ * offers an event to this controller for processing.
*
* @param topic topic associated with the event
* @param event the event
@@ -100,10 +100,10 @@ public interface DroolsController extends Startable, Lockable {
public boolean offer(String topic, String event);
/**
- * delivers "event" to "sink"
+ * delivers "event" to "sink".
*
* @param sink destination
- * @param event
+ * @param event event
* @return true if successful, false if a failure has occurred.
* @throws IllegalArgumentException when invalid or insufficient properties are provided
* @throws IllegalStateException when the engine is in a state where this operation is not
@@ -114,32 +114,37 @@ public interface DroolsController extends Startable, Lockable {
public boolean deliver(TopicSink sink, Object event);
/**
+ * Get recent source events.
*
- * @return the most recent received events
+ * @return the most recent received events.
*/
public Object[] getRecentSourceEvents();
/**
+ * Get recent sink events.
*
* @return the most recent delivered events
*/
public String[] getRecentSinkEvents();
/**
+ * Get container.
+ *
* @return the underlying policy container
*/
public PolicyContainer getContainer();
/**
- * Supports this encoder?
+ * Does it owns the coder.
*
- * @param encodedObject
- * @return
+ * @param coderClass the encoder object
+ * @param modelHash the hash for the model
+ * @return true it owns it
*/
public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash);
/**
- * fetches a class from the model
+ * fetches a class from the model.
*
* @param className the class to fetch
* @return the actual class object, or null if not found
@@ -147,12 +152,12 @@ public interface DroolsController extends Startable, Lockable {
public Class<?> fetchModelClass(String className);
/**
- * is this controller Smart?
+ * is this controller Smart.
*/
public boolean isBrained();
/**
- * update the new version of the maven jar rules file
+ * update the new version of the maven jar rules file.
*
* @param newGroupId - new group id
* @param newArtifactId - new artifact id
@@ -162,14 +167,13 @@ public interface DroolsController extends Startable, Lockable {
*
* @throws Exception from within drools libraries
* @throws LinkageError from within drools libraries
- * @throws ArgumentException bad parameter passed in
*/
public void updateToVersion(String newGroupId, String newArtifactId, String newVersion,
List<TopicCoderFilterConfiguration> decoderConfigurations,
List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError;
/**
- * gets the classnames of facts as well as the current count
+ * gets the classnames of facts as well as the current count.
*
* @param sessionName the session name
* @return map of class to count
@@ -177,16 +181,15 @@ public interface DroolsController extends Startable, Lockable {
public Map<String, Integer> factClassNames(String sessionName);
/**
- * gets the count of facts for a given session
+ * gets the count of facts for a given session.
*
* @param sessionName the session name
* @return the fact count
- * @throws IllegalArgumentException
*/
public long factCount(String sessionName);
/**
- * gets all the facts of a given class for a given session
+ * gets all the facts of a given class for a given session.
*
* @param sessionName the session identifier
* @param className the class type
@@ -196,7 +199,7 @@ public interface DroolsController extends Startable, Lockable {
public List<Object> facts(String sessionName, String className, boolean delete);
/**
- * gets the facts associated with a query for a give session for a given queried entity
+ * gets the facts associated with a query for a give session for a given queried entity.
*
* @param sessionName the session
* @param queryName the query identifier
@@ -209,9 +212,8 @@ public interface DroolsController extends Startable, Lockable {
Object... queryParams);
/**
- * halts and permanently releases all resources
+ * halts and permanently releases all resources.
*
- * @throws IllegalStateException
*/
public void halt();
}
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 b3aaaa7f..6dcae635 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
@@ -26,13 +26,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Properties;
-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.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;
@@ -45,12 +45,12 @@ import org.slf4j.LoggerFactory;
/**
* Drools Controller Factory to manage controller creation, destruction, and retrieval for
- * management interfaces
+ * management interfaces.
*/
public interface DroolsControllerFactory {
/**
- * Constructs a Drools Controller based on properties
+ * Constructs a Drools Controller based on properties.
*
* @param properties properties containing initialization parameters
* @param eventSources list of event sources
@@ -64,7 +64,7 @@ public interface DroolsControllerFactory {
List<? extends TopicSink> eventSinks) throws LinkageError;
/**
- * Explicit construction of a Drools Controller
+ * Explicit construction of a Drools Controller.
*
* @param groupId maven group id of drools artifact
* @param artifactId maven artifact id of drools artifact
@@ -81,31 +81,31 @@ public interface DroolsControllerFactory {
List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError;
/**
- * Releases the Drools Controller from operation
+ * Releases the Drools Controller from operation.
*
* @param controller the Drools Controller to shut down
*/
public void shutdown(DroolsController controller);
/**
- * Disables all Drools Controllers from operation
+ * Disables all Drools Controllers from operation.
*/
public void shutdown();
/**
- * Destroys and releases resources for a Drools Controller
+ * Destroys and releases resources for a Drools Controller.
*
* @param controller the Drools Controller to destroy
*/
public void destroy(DroolsController controller);
/**
- * Destroys all Drools Controllers
+ * Destroys all Drools Controllers.
*/
public void destroy();
/**
- * Gets the Drools Controller associated with the maven group and artifact id
+ * Gets the Drools Controller associated with the maven group and artifact id.
*
* @param groupId maven group id of drools artifact
* @param artifactId maven artifact id of drools artifact
@@ -117,7 +117,7 @@ public interface DroolsControllerFactory {
public DroolsController get(String groupId, String artifactId, String version);
/**
- * returns the current inventory of Drools Controllers
+ * returns the current inventory of Drools Controllers.
*
* @return a list of Drools Controllers
*/
@@ -128,22 +128,22 @@ public interface DroolsControllerFactory {
/* ---------------- implementation ----------------- */
/**
- * Factory of Drools Controllers indexed by the Maven coordinates
+ * Factory of Drools Controllers indexed by the Maven coordinates.
*/
class IndexedDroolsControllerFactory implements DroolsControllerFactory {
/**
- * logger
+ * logger.
*/
private static Logger logger = LoggerFactory.getLogger(MavenDroolsController.class);
/**
- * Policy Controller Name Index
+ * Policy Controller Name Index.
*/
protected HashMap<String, DroolsController> droolsControllers = new HashMap<>();
/**
- * Null Drools Controller
+ * Null Drools Controller.
*/
protected NullDroolsController nullDroolsController = new NullDroolsController();
@@ -186,8 +186,66 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
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
+ * find out decoder classes and filters.
*
* @param properties properties with information about decoders
* @param topicEntities topic sources
@@ -235,12 +293,12 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
// 1. first the topic
- String aTopic = topic.getTopic();
+ 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 + aTopic
+ String customGson = properties.getProperty(propertyTopicEntityPrefix + firstTopic
+ PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_GSON_SUFFIX);
CustomGsonCoder customGsonCoder = null;
@@ -253,7 +311,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
}
}
- String customJackson = properties.getProperty(propertyTopicEntityPrefix + aTopic
+ String customJackson = properties.getProperty(propertyTopicEntityPrefix + firstTopic
+ PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_JACKSON_SUFFIX);
CustomJacksonCoder customJacksonCoder = null;
@@ -269,25 +327,27 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
// 3. second the list of classes associated with each topic
String eventClasses = properties
- .getProperty(propertyTopicEntityPrefix + aTopic + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX);
+ .getProperty(propertyTopicEntityPrefix + firstTopic
+ + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX);
if (eventClasses == null || eventClasses.isEmpty()) {
- // TODO warn
+ logger.warn("There are no event classes for topic {}", firstTopic);
continue;
}
List<PotentialCoderFilter> classes2Filters = new ArrayList<>();
- List<String> aTopicClasses = new ArrayList<>(Arrays.asList(eventClasses.split("\\s*,\\s*")));
+ List<String> topicClasses = new ArrayList<>(Arrays.asList(eventClasses.split("\\s*,\\s*")));
- for (String aClass : aTopicClasses) {
+ for (String theClass : topicClasses) {
// 4. third, for each coder class, get the list of field filters
String filter = properties
- .getProperty(propertyTopicEntityPrefix + aTopic + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX
- + "." + aClass + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX);
+ .getProperty(propertyTopicEntityPrefix + firstTopic
+ + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX
+ + "." + theClass + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX);
List<Pair<String, String>> filters = new ArrayList<>();
@@ -295,7 +355,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
// 4. topic -> class -> with no filters
JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters);
- PotentialCoderFilter class2Filters = new PotentialCoderFilter(aClass, protocolFilter);
+ PotentialCoderFilter class2Filters = new PotentialCoderFilter(theClass, protocolFilter);
classes2Filters.add(class2Filters);
continue;
}
@@ -330,12 +390,12 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
}
JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters);
- PotentialCoderFilter class2Filters = new PotentialCoderFilter(aClass, protocolFilter);
+ PotentialCoderFilter class2Filters = new PotentialCoderFilter(theClass, protocolFilter);
classes2Filters.add(class2Filters);
}
TopicCoderFilterConfiguration topic2Classes2Filters =
- new TopicCoderFilterConfiguration(aTopic, classes2Filters, customGsonCoder, customJacksonCoder);
+ new TopicCoderFilterConfiguration(firstTopic, classes2Filters, customGsonCoder, customJacksonCoder);
topics2DecodedClasses2Filters.add(topic2Classes2Filters);
}
@@ -343,64 +403,6 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
}
@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;
- }
-
- @Override
public void destroy(DroolsController controller) {
unmanage(controller);
controller.halt();
@@ -419,11 +421,9 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
}
/**
- * unmanage the drools controller
+ * unmanage the drools controller.
*
- * @param controller
- * @return
- * @throws IllegalArgumentException
+ * @param controller the controller
*/
protected void unmanage(DroolsController controller) {
if (controller == null) {
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 7b44817a..707a8e77 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
@@ -35,11 +35,11 @@ import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
import org.kie.api.runtime.rule.QueryResults;
import org.kie.api.runtime.rule.QueryResultsRow;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
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.common.endpoints.event.comm.TopicSink;
import org.onap.policy.drools.features.DroolsControllerFeatureAPI;
import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
@@ -57,806 +57,857 @@ import org.slf4j.LoggerFactory;
* Drools containers instantiated using Maven.
*/
public class MavenDroolsController implements DroolsController {
-
- /**
- * logger
- */
- private static Logger logger = LoggerFactory.getLogger(MavenDroolsController.class);
-
- /**
- * Policy Container, the access object to the policy-core layer
- */
- @JsonIgnore
- protected final PolicyContainer policyContainer;
-
- /**
- * alive status of this drools controller,
- * reflects invocation of start()/stop() only
- */
- protected volatile boolean alive = false;
-
- /**
- * locked status of this drools controller,
- * reflects if i/o drools related operations are permitted,
- * more specifically: offer() and deliver().
- * It does not affect the ability to start and stop
- * underlying drools infrastructure
- */
- protected volatile boolean locked = false;
-
- /**
- * list of topics, each with associated decoder classes, each
- * with a list of associated filters.
- */
- protected List<TopicCoderFilterConfiguration> decoderConfigurations;
-
- /**
- * list of topics, each with associated encoder classes, each
- * with a list of associated filters.
- */
- protected List<TopicCoderFilterConfiguration> encoderConfigurations;
-
- /**
- * recent source events processed
- */
- protected final CircularFifoQueue<Object> recentSourceEvents = new CircularFifoQueue<>(10);
-
- /**
- * recent sink events processed
- */
- protected final CircularFifoQueue<String> recentSinkEvents = new CircularFifoQueue<>(10);
-
- /**
- * original Drools Model/Rules classloader hash
- */
- protected int modelClassLoaderHash;
-
- /**
- * Expanded version of the constructor
- *
- * @param groupId maven group id
- * @param artifactId maven artifact id
- * @param version maven version
- * @param decoderConfigurations list of topic -> decoders -> filters mapping
- * @param encoderConfigurations list of topic -> encoders -> filters mapping
- *
- * @throws IllegalArgumentException invalid arguments passed in
- */
- public MavenDroolsController(String groupId,
- String artifactId,
- String version,
- List<TopicCoderFilterConfiguration> decoderConfigurations,
- List<TopicCoderFilterConfiguration> encoderConfigurations) {
-
- logger.info("drools-controller instantiation [{}:{}:{}]", groupId, artifactId, version);
-
- if (groupId == null || groupId.isEmpty())
- throw new IllegalArgumentException("Missing maven group-id coordinate");
-
- if (artifactId == null || artifactId.isEmpty())
- throw new IllegalArgumentException("Missing maven artifact-id coordinate");
-
- if (version == null || version.isEmpty())
- throw new IllegalArgumentException("Missing maven version coordinate");
-
- this.policyContainer= new PolicyContainer(groupId, artifactId, version);
- this.init(decoderConfigurations, encoderConfigurations);
-
- logger.debug("{}: instantiation completed ", this);
- }
-
- /**
- * init encoding/decoding configuration
- * @param decoderConfigurations list of topic -> decoders -> filters mapping
- * @param encoderConfigurations list of topic -> encoders -> filters mapping
- */
- protected void init(List<TopicCoderFilterConfiguration> decoderConfigurations,
- List<TopicCoderFilterConfiguration> encoderConfigurations) {
-
- this.decoderConfigurations = decoderConfigurations;
- this.encoderConfigurations = encoderConfigurations;
-
- this.initCoders(decoderConfigurations, true);
- this.initCoders(encoderConfigurations, false);
-
- this.modelClassLoaderHash = this.policyContainer.getClassLoader().hashCode();
- }
-
- @Override
- public void updateToVersion(String newGroupId, String newArtifactId, String newVersion,
- List<TopicCoderFilterConfiguration> decoderConfigurations,
- List<TopicCoderFilterConfiguration> encoderConfigurations)
- throws LinkageError {
-
- logger.info("{}: updating version -> [{}:{}:{}]", newGroupId, newArtifactId, newVersion);
-
- 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");
-
- if (newGroupId.equalsIgnoreCase(DroolsController.NO_GROUP_ID) ||
- newArtifactId.equalsIgnoreCase(DroolsController.NO_ARTIFACT_ID) ||
- newVersion.equalsIgnoreCase(DroolsController.NO_VERSION)) {
- throw new IllegalArgumentException("BRAINLESS maven coordinates provided: " +
- newGroupId + ":" + newArtifactId + ":" +
- newVersion);
- }
-
- if (newGroupId.equalsIgnoreCase(this.getGroupId()) &&
- newArtifactId.equalsIgnoreCase(this.getArtifactId()) &&
- newVersion.equalsIgnoreCase(this.getVersion())) {
- logger.warn("Al in the right version: " + newGroupId + ":" +
- newArtifactId + ":" + newVersion + " vs. " + this);
- return;
- }
-
- if (!newGroupId.equalsIgnoreCase(this.getGroupId()) ||
- !newArtifactId.equalsIgnoreCase(this.getArtifactId())) {
- throw new IllegalArgumentException("Group ID and Artifact ID maven coordinates must be identical for the upgrade: " +
- newGroupId + ":" + newArtifactId + ":" +
- newVersion + " vs. " + this);
- }
-
- /* upgrade */
- String messages = this.policyContainer.updateToVersion(newVersion);
- if (logger.isWarnEnabled())
- logger.warn(this + "UPGRADE results: " + messages);
-
- /*
- * If all sucessful (can load new container), now we can remove all coders from previous sessions
- */
- this.removeCoders();
-
- /*
- * add the new coders
- */
- this.init(decoderConfigurations, encoderConfigurations);
-
- if (logger.isInfoEnabled())
- logger.info("UPDATE-TO-VERSION: completed " + this);
- }
-
- /**
- * initialize decoders for all the topics supported by this controller
- * Note this is critical to be done after the Policy Container is
- * instantiated to be able to fetch the corresponding classes.
- *
- * @param coderConfigurations list of topic -> decoders -> filters mapping
- */
- protected void initCoders(List<TopicCoderFilterConfiguration> coderConfigurations,
- boolean decoder) {
-
- if (logger.isInfoEnabled())
- logger.info("INIT-CODERS: " + this);
-
- if (coderConfigurations == null) {
- return;
- }
-
-
- for (TopicCoderFilterConfiguration coderConfig: coderConfigurations) {
- String topic = coderConfig.getTopic();
-
- CustomGsonCoder customGsonCoder = coderConfig.getCustomGsonCoder();
- if (coderConfig.getCustomGsonCoder() != null &&
- coderConfig.getCustomGsonCoder().getClassContainer() != null &&
- !coderConfig.getCustomGsonCoder().getClassContainer().isEmpty()) {
-
- String customGsonCoderClass = coderConfig.getCustomGsonCoder().getClassContainer();
- if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
- customGsonCoderClass)) {
- throw makeRetrieveEx(customGsonCoderClass);
- } else {
- if (logger.isInfoEnabled())
- logClassFetched(customGsonCoderClass);
- }
- }
-
- CustomJacksonCoder customJacksonCoder = coderConfig.getCustomJacksonCoder();
- if (coderConfig.getCustomJacksonCoder() != null &&
- coderConfig.getCustomJacksonCoder().getClassContainer() != null &&
- !coderConfig.getCustomJacksonCoder().getClassContainer().isEmpty()) {
-
- String customJacksonCoderClass = coderConfig.getCustomJacksonCoder().getClassContainer();
- if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
- customJacksonCoderClass)) {
- throw makeRetrieveEx(customJacksonCoderClass);
- } else {
- if (logger.isInfoEnabled())
- logClassFetched(customJacksonCoderClass);
- }
- }
-
- List<PotentialCoderFilter> coderFilters = coderConfig.getCoderFilters();
- if (coderFilters == null || coderFilters.isEmpty()) {
- continue;
- }
-
- for (PotentialCoderFilter coderFilter : coderFilters) {
- String potentialCodedClass = coderFilter.getCodedClass();
- JsonProtocolFilter protocolFilter = coderFilter.getFilter();
-
- if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
- potentialCodedClass)) {
- throw makeRetrieveEx(potentialCodedClass);
- } else {
- if (logger.isInfoEnabled())
- logClassFetched(potentialCodedClass);
- }
-
- if (decoder)
- EventProtocolCoder.manager.addDecoder(this.getGroupId(), this.getArtifactId(),
- topic, potentialCodedClass, protocolFilter,
- customGsonCoder,
- customJacksonCoder,
- this.policyContainer.getClassLoader().hashCode());
- else
- EventProtocolCoder.manager.addEncoder(this.getGroupId(), this.getArtifactId(),
- topic, potentialCodedClass, protocolFilter,
- customGsonCoder,
- customJacksonCoder,
- this.policyContainer.getClassLoader().hashCode());
- }
- }
- }
-
- /**
- * Logs an error and makes an exception for an item that cannot be retrieved.
- * @param itemName
- * @return a new exception
- */
- private IllegalArgumentException makeRetrieveEx(String itemName) {
- logger.error(itemName + " cannot be retrieved");
- return new IllegalArgumentException(itemName + " cannot be retrieved");
- }
-
- /**
- * Logs the name of the class that was fetched.
- * @param className
- */
- private void logClassFetched(String className) {
- logger.info("CLASS FETCHED " + className);
- }
-
-
- /**
- * remove decoders.
- */
- protected void removeDecoders(){
- if (logger.isInfoEnabled())
- logger.info("REMOVE-DECODERS: " + this);
-
- if (this.decoderConfigurations == null) {
- return;
- }
-
-
- for (TopicCoderFilterConfiguration coderConfig: decoderConfigurations) {
- String topic = coderConfig.getTopic();
- EventProtocolCoder.manager.removeDecoders
- (this.getGroupId(), this.getArtifactId(), topic);
- }
- }
-
- /**
- * remove decoders.
- */
- protected void removeEncoders() {
-
- if (logger.isInfoEnabled())
- logger.info("REMOVE-ENCODERS: " + this);
-
- if (this.encoderConfigurations == null)
- return;
-
-
- for (TopicCoderFilterConfiguration coderConfig: encoderConfigurations) {
- String topic = coderConfig.getTopic();
- EventProtocolCoder.manager.removeEncoders
- (this.getGroupId(), this.getArtifactId(), topic);
- }
- }
-
-
- @Override
- public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) {
- if (!ReflectionUtil.isClass
- (this.policyContainer.getClassLoader(), coderClass.getCanonicalName())) {
- logger.error(this + coderClass.getCanonicalName() + " cannot be retrieved. ");
- return false;
- }
-
- if (modelHash == this.modelClassLoaderHash) {
- if (logger.isInfoEnabled())
- logger.info(coderClass.getCanonicalName() +
- this + " class loader matches original drools controller rules classloader " +
- coderClass.getClassLoader());
- return true;
- } else {
- if (logger.isWarnEnabled())
- logger.warn(this + coderClass.getCanonicalName() + " class loaders don't match " +
- coderClass.getClassLoader() + " vs " +
- this.policyContainer.getClassLoader());
- return false;
- }
- }
-
- @Override
- public boolean start() {
-
- if (logger.isInfoEnabled())
- logger.info("START: " + this);
-
- synchronized (this) {
- if (this.alive)
- return true;
-
- this.alive = true;
- }
-
- return this.policyContainer.start();
- }
-
- @Override
- public boolean stop() {
-
- logger.info("STOP: " + this);
-
- synchronized (this) {
- if (!this.alive)
- return true;
-
- this.alive = false;
- }
-
- return this.policyContainer.stop();
- }
-
- @Override
- public void shutdown() {
- logger.info("{}: SHUTDOWN", this);
-
- try {
- this.stop();
- this.removeCoders();
- } catch (Exception e) {
- logger.error("{} SHUTDOWN FAILED because of {}", this, e.getMessage(), e);
- } finally {
- this.policyContainer.shutdown();
- }
-
- }
-
- @Override
- public void halt() {
- logger.info("{}: HALT", this);
-
- try {
- this.stop();
- this.removeCoders();
- } catch (Exception e) {
- logger.error("{} HALT FAILED because of {}", this, e.getMessage(), e);
- } finally {
- this.policyContainer.destroy();
- }
- }
-
- /**
- * removes this drools controllers and encoders and decoders from operation
- */
- protected void removeCoders() {
- logger.info("{}: REMOVE-CODERS", this);
-
- try {
- this.removeDecoders();
- } catch (IllegalArgumentException e) {
- logger.error("{} REMOVE-DECODERS FAILED because of {}", this, e.getMessage(), e);
- }
-
- try {
- this.removeEncoders();
- } catch (IllegalArgumentException e) {
- logger.error("{} REMOVE-ENCODERS FAILED because of {}", this, e.getMessage(), e);
- }
- }
-
- @Override
- public boolean isAlive() {
- return this.alive;
- }
-
- @Override
- public boolean offer(String topic, String event) {
- logger.debug("{}: OFFER: {} <- {}", this, topic, event);
-
- if (this.locked)
- return true;
-
- if (!this.alive)
- return true;
-
- // 0. Check if the policy container has any sessions
-
- if (this.policyContainer.getPolicySessions().isEmpty()) {
- // no sessions
- return true;
- }
-
- // 1. Now, check if this topic has a decoder:
-
- if (!EventProtocolCoder.manager.isDecodingSupported(this.getGroupId(),
- this.getArtifactId(),
- topic)) {
-
- logger.warn("{}: DECODING-UNSUPPORTED {}:{}:{}", this,
- topic, this.getGroupId(), this.getArtifactId());
- return true;
- }
-
- // 2. Decode
-
- Object anEvent;
- try {
- anEvent = EventProtocolCoder.manager.decode(this.getGroupId(),
- this.getArtifactId(),
- topic,
- event);
- } catch (UnsupportedOperationException uoe) {
- logger.debug("{}: DECODE FAILED: {} <- {} because of {}", this, topic,
- event, uoe.getMessage(), uoe);
- return true;
- } catch (Exception e) {
- logger.warn("{}: DECODE FAILED: {} <- {} because of {}", this, topic,
- event, e.getMessage(), e);
- return true;
- }
-
- synchronized(this.recentSourceEvents) {
- this.recentSourceEvents.add(anEvent);
- }
-
- // increment event count for Nagios monitoring
- PdpJmx.getInstance().updateOccured();
-
- // Broadcast
-
- if (logger.isInfoEnabled())
- logger.info(this + "BROADCAST-INJECT of " + event + " FROM " + topic + " INTO " + this.policyContainer.getName());
-
- for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
- try {
- if (feature.beforeInsert(this, anEvent))
- return true;
- } catch (Exception e) {
- logger.error("{}: feature {} before-insert failure because of {}",
- this, feature.getClass().getName(), e.getMessage(), e);
- }
- }
-
- boolean successInject = this.policyContainer.insertAll(anEvent);
- if (!successInject)
- logger.warn(this + "Failed to inject into PolicyContainer " + this.getSessionNames());
-
- for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
- try {
- if (feature.afterInsert(this, anEvent, successInject))
- return true;
- } catch (Exception e) {
- logger.error("{}: feature {} after-insert failure because of {}",
- this, feature.getClass().getName(), e.getMessage(), e);
- }
- }
-
- return true;
- }
-
- @Override
- public boolean deliver(TopicSink sink, Object event) {
-
- if (logger.isInfoEnabled())
- logger.info(this + "DELIVER: " + event + " FROM " + this + " TO " + sink);
-
- if (sink == null)
- throw new IllegalArgumentException
- (this + " invalid sink");
-
- if (event == null)
- throw new IllegalArgumentException
- (this + " invalid event");
-
- if (this.locked)
- throw new IllegalStateException
- (this + " is locked");
-
- if (!this.alive)
- throw new IllegalStateException
- (this + " is stopped");
-
- String json =
- EventProtocolCoder.manager.encode(sink.getTopic(), event, this);
-
- synchronized(this.recentSinkEvents) {
- this.recentSinkEvents.add(json);
- }
-
- return sink.send(json);
-
- }
-
- @Override
- public String getVersion() {
- return this.policyContainer.getVersion();
- }
-
- @Override
- public String getArtifactId() {
- return this.policyContainer.getArtifactId();
- }
-
- @Override
- public String getGroupId() {
- return this.policyContainer.getGroupId();
- }
-
- /**
- * @return the modelClassLoaderHash
- */
- public int getModelClassLoaderHash() {
- return modelClassLoaderHash;
- }
-
- @Override
- public synchronized boolean lock() {
- logger.info("LOCK: " + this);
-
- this.locked = true;
- return true;
- }
-
- @Override
- public synchronized boolean unlock() {
- logger.info("UNLOCK: " + this);
-
- this.locked = false;
- return true;
- }
-
- @Override
- public boolean isLocked() {
- return this.locked;
- }
-
- @JsonIgnore
- @Override
- public PolicyContainer getContainer() {
- return this.policyContainer;
- }
-
- @JsonProperty("sessions")
- @Override
- public List<String> getSessionNames() {
- return getSessionNames(true);
- }
-
- @JsonProperty("sessionCoordinates")
- @Override
- public List<String> getCanonicalSessionNames() {
- return getSessionNames(false);
- }
-
- /**
- * get session names
- * @param abbreviated true for the short form, otherwise the long form
- * @return session names
- */
- protected List<String> getSessionNames(boolean abbreviated) {
- List<String> sessionNames = new ArrayList<>();
- try {
- for (PolicySession session: this.policyContainer.getPolicySessions()) {
- if (abbreviated)
- sessionNames.add(session.getName());
- else
- sessionNames.add(session.getFullName());
- }
- } catch (Exception e) {
- logger.warn("Can't retrieve CORE sessions: " + e.getMessage(), e);
- sessionNames.add(e.getMessage());
- }
- return sessionNames;
- }
-
- /**
- * provides the underlying core layer container sessions
- *
- * @return the attached Policy Container
- */
- protected List<PolicySession> getSessions() {
- List<PolicySession> sessions = new ArrayList<>();
- sessions.addAll(this.policyContainer.getPolicySessions());
- return sessions;
- }
-
- /**
- * provides the underlying core layer container session with name sessionName
- *
- * @param sessionName session name
- * @return the attached Policy Container
- * @throws IllegalArgumentException when an invalid session name is provided
- * @throws IllegalStateException when the drools controller is in an invalid state
- */
- protected PolicySession getSession(String sessionName) {
- if (sessionName == null || sessionName.isEmpty())
- throw new IllegalArgumentException("A Session Name must be provided");
-
- List<PolicySession> sessions = this.getSessions();
- for (PolicySession session : sessions) {
- if (sessionName.equals(session.getName()) || sessionName.equals(session.getFullName()))
- return session;
- }
-
- throw invalidSessNameEx(sessionName);
- }
-
- private IllegalArgumentException invalidSessNameEx(String sessionName) {
- return new IllegalArgumentException("Invalid Session Name: " + sessionName);
- }
-
- @Override
- public Map<String,Integer> factClassNames(String sessionName) {
- if (sessionName == null || sessionName.isEmpty())
- throw invalidSessNameEx(sessionName);
-
- Map<String,Integer> classNames = new HashMap<>();
-
- PolicySession session = getSession(sessionName);
- KieSession kieSession = session.getKieSession();
-
- Collection<FactHandle> facts = session.getKieSession().getFactHandles();
- for (FactHandle fact : facts) {
- try {
- String className = kieSession.getObject(fact).getClass().getName();
- if (classNames.containsKey(className))
- classNames.put(className, classNames.get(className) + 1);
- else
- classNames.put(className, 1);
- } catch (Exception e) {
- logger.warn("Object cannot be retrieved from fact {}", fact, e);
- }
- }
-
- return classNames;
- }
-
- @Override
- public long factCount(String sessionName) {
- if (sessionName == null || sessionName.isEmpty())
- throw invalidSessNameEx(sessionName);
-
- PolicySession session = getSession(sessionName);
- return session.getKieSession().getFactCount();
- }
-
- @Override
- public List<Object> facts(String sessionName, String className, boolean delete) {
- if (sessionName == null || sessionName.isEmpty())
- throw invalidSessNameEx(sessionName);
-
- if (className == null || className.isEmpty())
- throw new IllegalArgumentException("Invalid Class Name: " + className);
-
- Class<?> factClass =
- ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className);
- if (factClass == null)
- throw new IllegalArgumentException("Class cannot be fetched in model's classloader: " + className);
-
- PolicySession session = getSession(sessionName);
- KieSession kieSession = session.getKieSession();
-
- List<Object> factObjects = new ArrayList<>();
-
- Collection<FactHandle> factHandles = kieSession.getFactHandles(new ClassObjectFilter(factClass));
- for (FactHandle factHandle : factHandles) {
- try {
- factObjects.add(kieSession.getObject(factHandle));
- if (delete)
- kieSession.delete(factHandle);
- } catch (Exception e) {
- logger.warn("Object cannot be retrieved from fact {}", factHandle, e);
- }
- }
-
- return factObjects;
- }
-
- @Override
- public List<Object> factQuery(String sessionName, String queryName, String queriedEntity, boolean delete, Object... queryParams) {
- if (sessionName == null || sessionName.isEmpty())
- throw invalidSessNameEx(sessionName);
-
- if (queryName == null || queryName.isEmpty())
- throw new IllegalArgumentException("Invalid Query Name: " + queryName);
-
- if (queriedEntity == null || queriedEntity.isEmpty())
- throw new IllegalArgumentException("Invalid Queried Entity: " + queriedEntity);
-
- PolicySession session = getSession(sessionName);
- KieSession kieSession = session.getKieSession();
-
- boolean found = false;
- for (KiePackage kiePackage : kieSession.getKieBase().getKiePackages()) {
- for (Query q : kiePackage.getQueries()) {
- if (q.getName() != null && q.getName().equals(queryName)) {
- found = true;
- break;
- }
- }
- }
- if (!found)
- throw new IllegalArgumentException("Invalid Query Name: " + queryName);
+
+ /**
+ * logger.
+ */
+ private static Logger logger = LoggerFactory.getLogger(MavenDroolsController.class);
+
+ /**
+ * Policy Container, the access object to the policy-core layer.
+ */
+ @JsonIgnore
+ protected final PolicyContainer policyContainer;
+
+ /**
+ * alive status of this drools controller,
+ * reflects invocation of start()/stop() only.
+ */
+ protected volatile boolean alive = false;
+
+ /**
+ * locked status of this drools controller,
+ * reflects if i/o drools related operations are permitted,
+ * more specifically: offer() and deliver().
+ * It does not affect the ability to start and stop
+ * underlying drools infrastructure
+ */
+ protected volatile boolean locked = false;
+
+ /**
+ * list of topics, each with associated decoder classes, each
+ * with a list of associated filters.
+ */
+ protected List<TopicCoderFilterConfiguration> decoderConfigurations;
+
+ /**
+ * list of topics, each with associated encoder classes, each
+ * with a list of associated filters.
+ */
+ protected List<TopicCoderFilterConfiguration> encoderConfigurations;
+
+ /**
+ * recent source events processed.
+ */
+ protected final CircularFifoQueue<Object> recentSourceEvents = new CircularFifoQueue<>(10);
+
+ /**
+ * recent sink events processed.
+ */
+ protected final CircularFifoQueue<String> recentSinkEvents = new CircularFifoQueue<>(10);
+
+ /**
+ * original Drools Model/Rules classloader hash.
+ */
+ protected int modelClassLoaderHash;
+
+ /**
+ * Expanded version of the constructor.
+ *
+ * @param groupId maven group id
+ * @param artifactId maven artifact id
+ * @param version maven version
+ * @param decoderConfigurations list of topic -> decoders -> filters mapping
+ * @param encoderConfigurations list of topic -> encoders -> filters mapping
+ *
+ * @throws IllegalArgumentException invalid arguments passed in
+ */
+ public MavenDroolsController(String groupId,
+ String artifactId,
+ String version,
+ List<TopicCoderFilterConfiguration> decoderConfigurations,
+ List<TopicCoderFilterConfiguration> encoderConfigurations) {
+
+ logger.info("drools-controller instantiation [{}:{}:{}]", groupId, artifactId, version);
+
+ if (groupId == null || groupId.isEmpty()) {
+ throw new IllegalArgumentException("Missing maven group-id coordinate");
+ }
+
+ if (artifactId == null || artifactId.isEmpty()) {
+ throw new IllegalArgumentException("Missing maven artifact-id coordinate");
+ }
+
+ if (version == null || version.isEmpty()) {
+ throw new IllegalArgumentException("Missing maven version coordinate");
+ }
+
+ this.policyContainer = new PolicyContainer(groupId, artifactId, version);
+ this.init(decoderConfigurations, encoderConfigurations);
+
+ logger.debug("{}: instantiation completed ", this);
+ }
+
+ /**
+ * init encoding/decoding configuration.
+ *
+ * @param decoderConfigurations list of topic -> decoders -> filters mapping
+ * @param encoderConfigurations list of topic -> encoders -> filters mapping
+ */
+ protected void init(List<TopicCoderFilterConfiguration> decoderConfigurations,
+ List<TopicCoderFilterConfiguration> encoderConfigurations) {
+
+ this.decoderConfigurations = decoderConfigurations;
+ this.encoderConfigurations = encoderConfigurations;
+
+ this.initCoders(decoderConfigurations, true);
+ this.initCoders(encoderConfigurations, false);
+
+ this.modelClassLoaderHash = this.policyContainer.getClassLoader().hashCode();
+ }
+
+ @Override
+ public void updateToVersion(String newGroupId, String newArtifactId, String newVersion,
+ List<TopicCoderFilterConfiguration> decoderConfigurations,
+ List<TopicCoderFilterConfiguration> encoderConfigurations)
+ throws LinkageError {
+
+ logger.info("updating version -> [{}:{}:{}]", newGroupId, newArtifactId, newVersion);
+
+ 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");
+ }
+
+ if (newGroupId.equalsIgnoreCase(DroolsController.NO_GROUP_ID)
+ || newArtifactId.equalsIgnoreCase(DroolsController.NO_ARTIFACT_ID)
+ || newVersion.equalsIgnoreCase(DroolsController.NO_VERSION)) {
+ throw new IllegalArgumentException("BRAINLESS maven coordinates provided: "
+ + newGroupId + ":" + newArtifactId + ":"
+ + newVersion);
+ }
+
+ if (newGroupId.equalsIgnoreCase(this.getGroupId())
+ && newArtifactId.equalsIgnoreCase(this.getArtifactId())
+ && newVersion.equalsIgnoreCase(this.getVersion())) {
+ logger.warn("Al in the right version: " + newGroupId + ":"
+ + newArtifactId + ":" + newVersion + " vs. " + this);
+ return;
+ }
+
+ if (!newGroupId.equalsIgnoreCase(this.getGroupId())
+ || !newArtifactId.equalsIgnoreCase(this.getArtifactId())) {
+ throw new IllegalArgumentException(
+ "Group ID and Artifact ID maven coordinates must be identical for the upgrade: "
+ + newGroupId + ":" + newArtifactId + ":"
+ + newVersion + " vs. " + this);
+ }
+
+ /* upgrade */
+ String messages = this.policyContainer.updateToVersion(newVersion);
+ if (logger.isWarnEnabled()) {
+ logger.warn("{} UPGRADE results: {}", this, messages);
+ }
+
+ /*
+ * If all sucessful (can load new container), now we can remove all coders from previous sessions
+ */
+ this.removeCoders();
+
+ /*
+ * add the new coders
+ */
+ this.init(decoderConfigurations, encoderConfigurations);
+
+ if (logger.isInfoEnabled()) {
+ logger.info("UPDATE-TO-VERSION: completed " + this);
+ }
+ }
+
+ /**
+ * initialize decoders for all the topics supported by this controller
+ * Note this is critical to be done after the Policy Container is
+ * instantiated to be able to fetch the corresponding classes.
+ *
+ * @param coderConfigurations list of topic -> decoders -> filters mapping
+ */
+ protected void initCoders(List<TopicCoderFilterConfiguration> coderConfigurations,
+ boolean decoder) {
+
+ if (logger.isInfoEnabled()) {
+ logger.info("INIT-CODERS: " + this);
+ }
+
+ if (coderConfigurations == null) {
+ return;
+ }
+
+
+ for (TopicCoderFilterConfiguration coderConfig: coderConfigurations) {
+ String topic = coderConfig.getTopic();
+
+ CustomGsonCoder customGsonCoder = coderConfig.getCustomGsonCoder();
+ if (coderConfig.getCustomGsonCoder() != null
+ && coderConfig.getCustomGsonCoder().getClassContainer() != null
+ && !coderConfig.getCustomGsonCoder().getClassContainer().isEmpty()) {
+
+ String customGsonCoderClass = coderConfig.getCustomGsonCoder().getClassContainer();
+ if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
+ customGsonCoderClass)) {
+ throw makeRetrieveEx(customGsonCoderClass);
+ } else {
+ if (logger.isInfoEnabled()) {
+ logClassFetched(customGsonCoderClass);
+ }
+ }
+ }
+
+ CustomJacksonCoder customJacksonCoder = coderConfig.getCustomJacksonCoder();
+ if (coderConfig.getCustomJacksonCoder() != null
+ && coderConfig.getCustomJacksonCoder().getClassContainer() != null
+ && !coderConfig.getCustomJacksonCoder().getClassContainer().isEmpty()) {
+
+ String customJacksonCoderClass = coderConfig.getCustomJacksonCoder().getClassContainer();
+ if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
+ customJacksonCoderClass)) {
+ throw makeRetrieveEx(customJacksonCoderClass);
+ } else {
+ if (logger.isInfoEnabled()) {
+ logClassFetched(customJacksonCoderClass);
+ }
+ }
+ }
+
+ List<PotentialCoderFilter> coderFilters = coderConfig.getCoderFilters();
+ if (coderFilters == null || coderFilters.isEmpty()) {
+ continue;
+ }
+
+ for (PotentialCoderFilter coderFilter : coderFilters) {
+ String potentialCodedClass = coderFilter.getCodedClass();
+ JsonProtocolFilter protocolFilter = coderFilter.getFilter();
+
+ if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
+ potentialCodedClass)) {
+ throw makeRetrieveEx(potentialCodedClass);
+ } else {
+ if (logger.isInfoEnabled()) {
+ logClassFetched(potentialCodedClass);
+ }
+ }
+
+ if (decoder) {
+ EventProtocolCoder.manager.addDecoder(this.getGroupId(), this.getArtifactId(),
+ topic, potentialCodedClass, protocolFilter,
+ customGsonCoder,
+ customJacksonCoder,
+ this.policyContainer.getClassLoader().hashCode());
+ } else {
+ EventProtocolCoder.manager.addEncoder(this.getGroupId(), this.getArtifactId(),
+ topic, potentialCodedClass, protocolFilter,
+ customGsonCoder,
+ customJacksonCoder,
+ this.policyContainer.getClassLoader().hashCode());
+ }
+ }
+ }
+ }
+
+ /**
+ * Logs an error and makes an exception for an item that cannot be retrieved.
+ * @param itemName the item to retrieve
+ * @return a new exception
+ */
+ private IllegalArgumentException makeRetrieveEx(String itemName) {
+ logger.error("{} cannot be retrieved", itemName);
+ return new IllegalArgumentException(itemName + " cannot be retrieved");
+ }
+
+ /**
+ * Logs the name of the class that was fetched.
+ * @param className class name fetched
+ */
+ private void logClassFetched(String className) {
+ logger.info("CLASS FETCHED {}", className);
+ }
+
+
+ /**
+ * remove decoders.
+ */
+ protected void removeDecoders() {
+ if (logger.isInfoEnabled()) {
+ logger.info("REMOVE-DECODERS: {}", this);
+ }
+
+ if (this.decoderConfigurations == null) {
+ return;
+ }
+
+
+ for (TopicCoderFilterConfiguration coderConfig: decoderConfigurations) {
+ String topic = coderConfig.getTopic();
+ EventProtocolCoder.manager.removeDecoders(this.getGroupId(), this.getArtifactId(), topic);
+ }
+ }
+
+ /**
+ * remove decoders.
+ */
+ protected void removeEncoders() {
+
+ if (logger.isInfoEnabled()) {
+ logger.info("REMOVE-ENCODERS: {}", this);
+ }
+
+ if (this.encoderConfigurations == null) {
+ return;
+ }
+
+ for (TopicCoderFilterConfiguration coderConfig: encoderConfigurations) {
+ String topic = coderConfig.getTopic();
+ EventProtocolCoder.manager.removeEncoders(this.getGroupId(), this.getArtifactId(), topic);
+ }
+ }
+
+
+ @Override
+ public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) {
+ if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(), coderClass.getCanonicalName())) {
+ logger.error("{}{} cannot be retrieved. ", this, coderClass.getCanonicalName());
+ return false;
+ }
+
+ if (modelHash == this.modelClassLoaderHash) {
+ if (logger.isInfoEnabled()) {
+ logger.info(coderClass.getCanonicalName()
+ + this + " class loader matches original drools controller rules classloader "
+ + coderClass.getClassLoader());
+ }
+ return true;
+ } else {
+ if (logger.isWarnEnabled()) {
+ logger.warn(this + coderClass.getCanonicalName() + " class loaders don't match "
+ + coderClass.getClassLoader() + " vs "
+ + this.policyContainer.getClassLoader());
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public boolean start() {
+
+ if (logger.isInfoEnabled()) {
+ logger.info("START: {}", this);
+ }
+
+ synchronized (this) {
+ if (this.alive) {
+ return true;
+ }
+ this.alive = true;
+ }
+
+ return this.policyContainer.start();
+ }
+
+ @Override
+ public boolean stop() {
+
+ logger.info("STOP: {}", this);
+
+ synchronized (this) {
+ if (!this.alive) {
+ return true;
+ }
+ this.alive = false;
+ }
+
+ return this.policyContainer.stop();
+ }
+
+ @Override
+ public void shutdown() {
+ logger.info("{}: SHUTDOWN", this);
+
+ try {
+ this.stop();
+ this.removeCoders();
+ } catch (Exception e) {
+ logger.error("{} SHUTDOWN FAILED because of {}", this, e.getMessage(), e);
+ } finally {
+ this.policyContainer.shutdown();
+ }
+
+ }
+
+ @Override
+ public void halt() {
+ logger.info("{}: HALT", this);
+
+ try {
+ this.stop();
+ this.removeCoders();
+ } catch (Exception e) {
+ logger.error("{} HALT FAILED because of {}", this, e.getMessage(), e);
+ } finally {
+ this.policyContainer.destroy();
+ }
+ }
+
+ /**
+ * removes this drools controllers and encoders and decoders from operation.
+ */
+ protected void removeCoders() {
+ logger.info("{}: REMOVE-CODERS", this);
+
+ try {
+ this.removeDecoders();
+ } catch (IllegalArgumentException e) {
+ logger.error("{} REMOVE-DECODERS FAILED because of {}", this, e.getMessage(), e);
+ }
+
+ try {
+ this.removeEncoders();
+ } catch (IllegalArgumentException e) {
+ logger.error("{} REMOVE-ENCODERS FAILED because of {}", this, e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean isAlive() {
+ return this.alive;
+ }
+
+ @Override
+ public boolean offer(String topic, String event) {
+ logger.debug("{}: OFFER: {} <- {}", this, topic, event);
+
+ if (this.locked) {
+ return true;
+ }
+ if (!this.alive) {
+ return true;
+ }
+
+ // 0. Check if the policy container has any sessions
+
+ if (this.policyContainer.getPolicySessions().isEmpty()) {
+ // no sessions
+ return true;
+ }
+
+ // 1. Now, check if this topic has a decoder:
+
+ if (!EventProtocolCoder.manager.isDecodingSupported(this.getGroupId(),
+ this.getArtifactId(),
+ topic)) {
+
+ logger.warn("{}: DECODING-UNSUPPORTED {}:{}:{}", this,
+ topic, this.getGroupId(), this.getArtifactId());
+ return true;
+ }
+
+ // 2. Decode
+
+ Object anEvent;
+ try {
+ anEvent = EventProtocolCoder.manager.decode(this.getGroupId(),
+ this.getArtifactId(),
+ topic,
+ event);
+ } catch (UnsupportedOperationException uoe) {
+ logger.debug("{}: DECODE FAILED: {} <- {} because of {}", this, topic,
+ event, uoe.getMessage(), uoe);
+ return true;
+ } catch (Exception e) {
+ logger.warn("{}: DECODE FAILED: {} <- {} because of {}", this, topic,
+ event, e.getMessage(), e);
+ return true;
+ }
+
+ synchronized (this.recentSourceEvents) {
+ this.recentSourceEvents.add(anEvent);
+ }
+
+ // increment event count for Nagios monitoring
+ PdpJmx.getInstance().updateOccured();
+
+ // Broadcast
+
+ if (logger.isInfoEnabled()) {
+ logger.info("{} BROADCAST-INJECT of {} FROM {} INTO {}",
+ this, event, topic, this.policyContainer.getName());
+ }
+
+ for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
+ try {
+ if (feature.beforeInsert(this, anEvent)) {
+ return true;
+ }
+ } catch (Exception e) {
+ logger.error("{}: feature {} before-insert failure because of {}",
+ this, feature.getClass().getName(), e.getMessage(), e);
+ }
+ }
+
+ boolean successInject = this.policyContainer.insertAll(anEvent);
+ if (!successInject) {
+ logger.warn(this + "Failed to inject into PolicyContainer {}", this.getSessionNames());
+ }
+
+ for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
+ try {
+ if (feature.afterInsert(this, anEvent, successInject)) {
+ return true;
+ }
+ } catch (Exception e) {
+ logger.error("{}: feature {} after-insert failure because of {}",
+ this, feature.getClass().getName(), e.getMessage(), e);
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean deliver(TopicSink sink, Object event) {
+
+ if (logger.isInfoEnabled()) {
+ logger.info("{}DELIVER: {} FROM {} TO {}", this, event, this, sink);
+ }
+
+ if (sink == null) {
+ throw new IllegalArgumentException(this + " invalid sink");
+ }
+
+ if (event == null) {
+ throw new IllegalArgumentException(this + " invalid event");
+ }
- List<Object> factObjects = new ArrayList<>();
-
- QueryResults queryResults = kieSession.getQueryResults(queryName, queryParams);
- for (QueryResultsRow row : queryResults) {
- try {
- factObjects.add(row.get(queriedEntity));
- if (delete)
- kieSession.delete(row.getFactHandle(queriedEntity));
- } catch (Exception e) {
- logger.warn("Object cannot be retrieved from row: {}", row, e);
- }
- }
-
- return factObjects;
- }
-
- @Override
- public Class<?> fetchModelClass(String className) {
- return ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className);
- }
-
- /**
- * @return the recentSourceEvents
- */
- @Override
- public Object[] getRecentSourceEvents() {
- synchronized(this.recentSourceEvents) {
- Object[] events = new Object[recentSourceEvents.size()];
- return recentSourceEvents.toArray(events);
- }
- }
-
- /**
- * @return the recentSinkEvents
- */
- @Override
- public String[] getRecentSinkEvents() {
- synchronized(this.recentSinkEvents) {
- String[] events = new String[recentSinkEvents.size()];
- return recentSinkEvents.toArray(events);
- }
- }
-
- @Override
- public boolean isBrained() {
- return true;
- }
-
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("MavenDroolsController [policyContainer=")
- .append((policyContainer != null) ? policyContainer.getName() : "NULL").append(":")
- .append(", alive=")
- .append(alive).append(", locked=")
- .append(", modelClassLoaderHash=").append(modelClassLoaderHash).append("]");
- return builder.toString();
- }
+ if (this.locked) {
+ throw new IllegalStateException(this + " is locked");
+ }
+
+ if (!this.alive) {
+ throw new IllegalStateException(this + " is stopped");
+ }
+
+ String json =
+ EventProtocolCoder.manager.encode(sink.getTopic(), event, this);
+
+ synchronized (this.recentSinkEvents) {
+ this.recentSinkEvents.add(json);
+ }
+
+ return sink.send(json);
+
+ }
+
+ @Override
+ public String getVersion() {
+ return this.policyContainer.getVersion();
+ }
+
+ @Override
+ public String getArtifactId() {
+ return this.policyContainer.getArtifactId();
+ }
+
+ @Override
+ public String getGroupId() {
+ return this.policyContainer.getGroupId();
+ }
+
+ /**
+ * Get model class loader hash.
+ *
+ * @return the modelClassLoaderHash
+ */
+ public int getModelClassLoaderHash() {
+ return modelClassLoaderHash;
+ }
+
+ @Override
+ public synchronized boolean lock() {
+ logger.info("LOCK: {}", this);
+
+ this.locked = true;
+ return true;
+ }
+
+ @Override
+ public synchronized boolean unlock() {
+ logger.info("UNLOCK: {}", this);
+
+ this.locked = false;
+ return true;
+ }
+
+ @Override
+ public boolean isLocked() {
+ return this.locked;
+ }
+
+ @JsonIgnore
+ @Override
+ public PolicyContainer getContainer() {
+ return this.policyContainer;
+ }
+
+ @JsonProperty("sessions")
+ @Override
+ public List<String> getSessionNames() {
+ return getSessionNames(true);
+ }
+
+ /**
+ * get session names.
+ *
+ * @param abbreviated true for the short form, otherwise the long form
+ * @return session names
+ */
+ protected List<String> getSessionNames(boolean abbreviated) {
+ List<String> sessionNames = new ArrayList<>();
+ try {
+ for (PolicySession session: this.policyContainer.getPolicySessions()) {
+ if (abbreviated) {
+ sessionNames.add(session.getName());
+ } else {
+ sessionNames.add(session.getFullName());
+ }
+ }
+ } catch (Exception e) {
+ logger.warn("Can't retrieve CORE sessions: " + e.getMessage(), e);
+ sessionNames.add(e.getMessage());
+ }
+ return sessionNames;
+ }
+
+ @JsonProperty("sessionCoordinates")
+ @Override
+ public List<String> getCanonicalSessionNames() {
+ return getSessionNames(false);
+ }
+
+ /**
+ * provides the underlying core layer container sessions.
+ *
+ * @return the attached Policy Container
+ */
+ protected List<PolicySession> getSessions() {
+ List<PolicySession> sessions = new ArrayList<>();
+ sessions.addAll(this.policyContainer.getPolicySessions());
+ return sessions;
+ }
+
+ /**
+ * provides the underlying core layer container session with name sessionName.
+ *
+ * @param sessionName session name
+ * @return the attached Policy Container
+ * @throws IllegalArgumentException when an invalid session name is provided
+ * @throws IllegalStateException when the drools controller is in an invalid state
+ */
+ protected PolicySession getSession(String sessionName) {
+ if (sessionName == null || sessionName.isEmpty()) {
+ throw new IllegalArgumentException("A Session Name must be provided");
+ }
+
+ List<PolicySession> sessions = this.getSessions();
+ for (PolicySession session : sessions) {
+ if (sessionName.equals(session.getName()) || sessionName.equals(session.getFullName())) {
+ return session;
+ }
+ }
+
+ throw invalidSessNameEx(sessionName);
+ }
+
+ private IllegalArgumentException invalidSessNameEx(String sessionName) {
+ return new IllegalArgumentException("Invalid Session Name: " + sessionName);
+ }
+
+ @Override
+ public Map<String,Integer> factClassNames(String sessionName) {
+ if (sessionName == null || sessionName.isEmpty()) {
+ throw invalidSessNameEx(sessionName);
+ }
+
+ Map<String,Integer> classNames = new HashMap<>();
+
+ PolicySession session = getSession(sessionName);
+ KieSession kieSession = session.getKieSession();
+
+ Collection<FactHandle> facts = session.getKieSession().getFactHandles();
+ for (FactHandle fact : facts) {
+ try {
+ String className = kieSession.getObject(fact).getClass().getName();
+ if (classNames.containsKey(className)) {
+ classNames.put(className, classNames.get(className) + 1);
+ } else {
+ classNames.put(className, 1);
+ }
+ } catch (Exception e) {
+ logger.warn("Object cannot be retrieved from fact {}", fact, e);
+ }
+ }
+
+ return classNames;
+ }
+
+ @Override
+ public long factCount(String sessionName) {
+ if (sessionName == null || sessionName.isEmpty()) {
+ throw invalidSessNameEx(sessionName);
+ }
+
+ PolicySession session = getSession(sessionName);
+ return session.getKieSession().getFactCount();
+ }
+
+ @Override
+ public List<Object> facts(String sessionName, String className, boolean delete) {
+ if (sessionName == null || sessionName.isEmpty()) {
+ throw invalidSessNameEx(sessionName);
+ }
+
+ if (className == null || className.isEmpty()) {
+ throw new IllegalArgumentException("Invalid Class Name: " + className);
+ }
+
+ Class<?> factClass =
+ ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className);
+ if (factClass == null) {
+ throw new IllegalArgumentException("Class cannot be fetched in model's classloader: " + className);
+ }
+
+ PolicySession session = getSession(sessionName);
+ KieSession kieSession = session.getKieSession();
+
+ List<Object> factObjects = new ArrayList<>();
+
+ Collection<FactHandle> factHandles = kieSession.getFactHandles(new ClassObjectFilter(factClass));
+ for (FactHandle factHandle : factHandles) {
+ try {
+ factObjects.add(kieSession.getObject(factHandle));
+ if (delete) {
+ kieSession.delete(factHandle);
+ }
+ } catch (Exception e) {
+ logger.warn("Object cannot be retrieved from fact {}", factHandle, e);
+ }
+ }
+
+ return factObjects;
+ }
+
+ @Override
+ public List<Object> factQuery(String sessionName, String queryName, String queriedEntity,
+ boolean delete, Object... queryParams) {
+ if (sessionName == null || sessionName.isEmpty()) {
+ throw invalidSessNameEx(sessionName);
+ }
+
+ if (queryName == null || queryName.isEmpty()) {
+ throw new IllegalArgumentException("Invalid Query Name: " + queryName);
+ }
+
+ if (queriedEntity == null || queriedEntity.isEmpty()) {
+ throw new IllegalArgumentException("Invalid Queried Entity: " + queriedEntity);
+ }
+
+ PolicySession session = getSession(sessionName);
+ KieSession kieSession = session.getKieSession();
+
+ boolean found = false;
+ for (KiePackage kiePackage : kieSession.getKieBase().getKiePackages()) {
+ for (Query q : kiePackage.getQueries()) {
+ if (q.getName() != null && q.getName().equals(queryName)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ throw new IllegalArgumentException("Invalid Query Name: " + queryName);
+ }
+
+ List<Object> factObjects = new ArrayList<>();
+
+ QueryResults queryResults = kieSession.getQueryResults(queryName, queryParams);
+ for (QueryResultsRow row : queryResults) {
+ try {
+ factObjects.add(row.get(queriedEntity));
+ if (delete) {
+ kieSession.delete(row.getFactHandle(queriedEntity));
+ }
+ } catch (Exception e) {
+ logger.warn("Object cannot be retrieved from row: {}", row, e);
+ }
+ }
+
+ return factObjects;
+ }
+
+ @Override
+ public Class<?> fetchModelClass(String className) {
+ return ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className);
+ }
+
+ /**
+ * Get recent source events.
+ *
+ * @return the recentSourceEvents
+ */
+ @Override
+ public Object[] getRecentSourceEvents() {
+ synchronized (this.recentSourceEvents) {
+ Object[] events = new Object[recentSourceEvents.size()];
+ return recentSourceEvents.toArray(events);
+ }
+ }
+
+ /**
+ * Get recent sink events.
+ *
+ * @return the recentSinkEvents
+ */
+ @Override
+ public String[] getRecentSinkEvents() {
+ synchronized (this.recentSinkEvents) {
+ String[] events = new String[recentSinkEvents.size()];
+ return recentSinkEvents.toArray(events);
+ }
+ }
+
+ @Override
+ public boolean isBrained() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("MavenDroolsController [policyContainer=")
+ .append((policyContainer != null) ? policyContainer.getName() : "NULL")
+ .append(":")
+ .append(", alive=")
+ .append(alive)
+ .append(", locked=")
+ .append(", modelClassLoaderHash=")
+ .append(modelClassLoaderHash)
+ .append("]");
+ return builder.toString();
+ }
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java
index 31ac1008..93cbc65e 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java
@@ -31,153 +31,153 @@ import org.onap.policy.common.endpoints.event.comm.TopicSink;
import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
/**
- * no-op Drools Controller
+ * no-op Drools Controller.
*/
public class NullDroolsController implements DroolsController {
- @Override
- public boolean start() {
- return false;
- }
-
- @Override
- public boolean stop() {
- return false;
- }
-
- @Override
- public void shutdown() {
- return;
- }
-
- @Override
- public void halt() {
- return;
- }
-
- @Override
- public boolean isAlive() {
- return false;
- }
-
- @Override
- public boolean lock() {
- return false;
- }
-
- @Override
- public boolean unlock() {
- return false;
- }
-
- @Override
- public boolean isLocked() {
- return false;
- }
-
- @Override
- public String getGroupId() {
- return NO_GROUP_ID;
- }
-
- @Override
- public String getArtifactId() {
- return NO_ARTIFACT_ID;
- }
-
- @Override
- public String getVersion() {
- return NO_VERSION;
- }
-
- @Override
- public List<String> getSessionNames() {
- return new ArrayList<>();
- }
-
- @Override
- public List<String> getCanonicalSessionNames() {
- return new ArrayList<>();
- }
-
- @Override
- public boolean offer(String topic, String event) {
- return false;
- }
-
- @Override
- public boolean deliver(TopicSink sink, Object event) {
- throw new IllegalStateException(makeInvokeMsg());
- }
-
- @Override
- public Object[] getRecentSourceEvents() {
- return new String[0];
- }
-
- @Override
- public PolicyContainer getContainer() {
- return null;
- }
-
- @Override
- public String[] getRecentSinkEvents() {
- return new String[0];
- }
-
- @Override
- public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) {
- throw new IllegalStateException(makeInvokeMsg());
- }
-
- @Override
- public Class<?> fetchModelClass(String className) {
- throw new IllegalArgumentException(makeInvokeMsg());
- }
-
- @Override
- public boolean isBrained() {
- return false;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("NullDroolsController []");
- return builder.toString();
- }
-
- @Override
- public void updateToVersion(String newGroupId, String newArtifactId, String newVersion,
- List<TopicCoderFilterConfiguration> decoderConfigurations,
- List<TopicCoderFilterConfiguration> encoderConfigurations)
- throws LinkageError {
- throw new IllegalArgumentException(makeInvokeMsg());
- }
-
- @Override
- public Map<String, Integer> factClassNames(String sessionName) {
- return new HashMap<>();
- }
-
- @Override
- public long factCount(String sessionName) {
- return 0;
- }
-
- @Override
- public List<Object> facts(String sessionName, String className, boolean delete) {
- return new ArrayList<>();
- }
-
- @Override
- public List<Object> factQuery(String sessionName, String queryName,
- String queriedEntity,
- boolean delete, Object... queryParams) {
- return new ArrayList<>();
- }
-
- private String makeInvokeMsg() {
- return this.getClass().getCanonicalName() + " invoked";
- }
+ @Override
+ public boolean start() {
+ return false;
+ }
+
+ @Override
+ public boolean stop() {
+ return false;
+ }
+
+ @Override
+ public void shutdown() {
+ return;
+ }
+
+ @Override
+ public void halt() {
+ return;
+ }
+
+ @Override
+ public boolean isAlive() {
+ return false;
+ }
+
+ @Override
+ public boolean lock() {
+ return false;
+ }
+
+ @Override
+ public boolean unlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isLocked() {
+ return false;
+ }
+
+ @Override
+ public String getGroupId() {
+ return NO_GROUP_ID;
+ }
+
+ @Override
+ public String getArtifactId() {
+ return NO_ARTIFACT_ID;
+ }
+
+ @Override
+ public String getVersion() {
+ return NO_VERSION;
+ }
+
+ @Override
+ public List<String> getSessionNames() {
+ return new ArrayList<>();
+ }
+
+ @Override
+ public List<String> getCanonicalSessionNames() {
+ return new ArrayList<>();
+ }
+
+ @Override
+ public boolean offer(String topic, String event) {
+ return false;
+ }
+
+ @Override
+ public boolean deliver(TopicSink sink, Object event) {
+ throw new IllegalStateException(makeInvokeMsg());
+ }
+
+ @Override
+ public Object[] getRecentSourceEvents() {
+ return new String[0];
+ }
+
+ @Override
+ public PolicyContainer getContainer() {
+ return null;
+ }
+
+ @Override
+ public String[] getRecentSinkEvents() {
+ return new String[0];
+ }
+
+ @Override
+ public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) {
+ throw new IllegalStateException(makeInvokeMsg());
+ }
+
+ @Override
+ public Class<?> fetchModelClass(String className) {
+ throw new IllegalArgumentException(makeInvokeMsg());
+ }
+
+ @Override
+ public boolean isBrained() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("NullDroolsController []");
+ return builder.toString();
+ }
+
+ @Override
+ public void updateToVersion(String newGroupId, String newArtifactId, String newVersion,
+ List<TopicCoderFilterConfiguration> decoderConfigurations,
+ List<TopicCoderFilterConfiguration> encoderConfigurations)
+ throws LinkageError {
+ throw new IllegalArgumentException(makeInvokeMsg());
+ }
+
+ @Override
+ public Map<String, Integer> factClassNames(String sessionName) {
+ return new HashMap<>();
+ }
+
+ @Override
+ public long factCount(String sessionName) {
+ return 0;
+ }
+
+ @Override
+ public List<Object> facts(String sessionName, String className, boolean delete) {
+ return new ArrayList<>();
+ }
+
+ @Override
+ public List<Object> factQuery(String sessionName, String queryName,
+ String queriedEntity,
+ boolean delete, Object... queryParams) {
+ return new ArrayList<>();
+ }
+
+ private String makeInvokeMsg() {
+ return this.getClass().getCanonicalName() + " invoked";
+ }
}
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 f4158804..135e1c58 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
@@ -29,28 +29,32 @@ import org.onap.policy.drools.utils.OrderedServiceImpl;
*/
public interface DroolsControllerFeatureAPI extends OrderedService {
- /**
- * intercepts before the Drools Controller gives the Policy Container a fact to
- * insert into its Policy Sessions
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- default boolean beforeInsert(DroolsController controller, Object fact) {return false;}
+ /**
+ * intercepts before the Drools Controller gives the Policy Container a fact to
+ * insert into its Policy Sessions.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ default boolean beforeInsert(DroolsController controller, Object fact) {
+ return false;
+ }
- /**
- * called after a fact is injected into the Policy Container
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- default boolean afterInsert(DroolsController controller, Object fact, boolean successInsert) {return false;}
+ /**
+ * called after a fact is injected into the Policy Container.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ default boolean afterInsert(DroolsController controller, Object fact, boolean successInsert) {
+ return false;
+ }
- /**
- * Feature providers implementing this interface
- */
- public static final OrderedServiceImpl<DroolsControllerFeatureAPI> providers =
- new OrderedServiceImpl<>(DroolsControllerFeatureAPI.class);
+ /**
+ * Feature providers implementing this interface.
+ */
+ 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 94d1b15e..286948ed 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
@@ -28,194 +28,230 @@ import org.onap.policy.drools.utils.OrderedService;
import org.onap.policy.drools.utils.OrderedServiceImpl;
public interface PolicyControllerFeatureAPI extends OrderedService {
-
- /**
- * Feature providers implementing this interface
- */
- public static final OrderedServiceImpl<PolicyControllerFeatureAPI> providers =
- new OrderedServiceImpl<PolicyControllerFeatureAPI>(PolicyControllerFeatureAPI.class);
-
- /**
- * called before creating a controller with name 'name' and
- * properties 'properties'
- *
- * @param name name of the the controller
- * @param properties configuration properties
- *
- * @return a policy controller. A take over of the creation operation
- * is performed by returning a non-null policy controller.
- * 'null' indicates that no take over has taken place, and processing should
- * continue to the next feature provider.
- */
- public default PolicyController beforeCreate(String name, Properties properties) {return null;}
-
- /**
- * called after creating a controller with name 'name'
- *
- * @param controller controller
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterCreate(PolicyController controller) {return false;}
-
- /**
- * intercept before the Policy Controller is started.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeStart(PolicyController controller) {return false;}
-
- /**
- * intercept after the Policy Controller is started.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterStart(PolicyController controller) {return false;}
-
- /**
- * intercept before the Policy Controller is stopped.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise..
- */
- public default boolean beforeStop(PolicyController controller) {return false;}
-
- /**
- * intercept after the Policy Controller is stopped
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.d.
- */
- public default boolean afterStop(PolicyController controller) {return false;}
-
- /**
- * intercept before the Policy Controller is locked
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeLock(PolicyController controller) {return false;}
-
- /**
- * intercept after the Policy Controller is locked
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise..
- */
- public default boolean afterLock(PolicyController controller) {return false;}
-
- /**
- * intercept before the Policy Controller is locked
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeUnlock(PolicyController controller) {return false;}
-
- /**
- * intercept after the Policy Controller is locked
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterUnlock(PolicyController controller) {return false;}
-
- /**
- * intercept before the Policy Controller is shut down
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise..
- */
- public default boolean beforeShutdown(PolicyController controller) {return false;}
-
- /**
- * called after the Policy Controller is shut down
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterShutdown(PolicyController controller) {return false;}
-
- /**
- * intercept before the Policy Controller is halted
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise..
- */
- public default boolean beforeHalt(PolicyController controller) {return false;}
-
- /**
- * called after the Policy Controller is halted
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterHalt(PolicyController controller) {return false;}
-
-
- /**
- * intercept before the Policy Controller is offered an event
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeOffer(PolicyController controller,
- CommInfrastructure protocol,
- String topic,
- String event) {return false;}
-
- /**
- * called after the Policy Controller processes an event offer
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterOffer(PolicyController controller,
- CommInfrastructure protocol,
- String topic,
- String event,
- boolean success) {return false;}
-
- /**
- * intercept before the Policy Controller delivers (posts) an event
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeDeliver(PolicyController controller,
- CommInfrastructure protocol,
- String topic,
- Object event) {return false;}
-
- /**
- * called after the Policy Controller delivers (posts) an event
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterDeliver(PolicyController controller,
- CommInfrastructure protocol,
- String topic,
- Object event,
- boolean success) {return false;}
+
+ /**
+ * Feature providers implementing this interface.
+ */
+ public static final OrderedServiceImpl<PolicyControllerFeatureAPI> providers =
+ new OrderedServiceImpl<>(PolicyControllerFeatureAPI.class);
+
+ /**
+ * called before creating a controller with name 'name' and
+ * properties 'properties'.
+ *
+ * @param name name of the the controller
+ * @param properties configuration properties
+ *
+ * @return a policy controller. A take over of the creation operation
+ * is performed by returning a non-null policy controller.
+ * 'null' indicates that no take over has taken place, and processing should
+ * continue to the next feature provider.
+ */
+ public default PolicyController beforeCreate(String name, Properties properties) {
+ return null;
+ }
+
+ /**
+ * called after creating a controller with name 'name'.
+ *
+ * @param controller controller
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterCreate(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Controller is started.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeStart(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Controller is started.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterStart(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Controller is stopped.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise..
+ */
+ public default boolean beforeStop(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Controller is stopped.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.d.
+ */
+ public default boolean afterStop(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Controller is locked.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeLock(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Controller is locked.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise..
+ */
+ public default boolean afterLock(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Controller is locked.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeUnlock(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Controller is locked.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterUnlock(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Controller is shut down.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise..
+ */
+ public default boolean beforeShutdown(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * called after the Policy Controller is shut down.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterShutdown(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Controller is halted.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise..
+ */
+ public default boolean beforeHalt(PolicyController controller) {
+ return false;
+ }
+
+ /**
+ * called after the Policy Controller is halted.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterHalt(PolicyController controller) {
+ return false;
+ }
+
+
+ /**
+ * intercept before the Policy Controller is offered an event.
+ *
+ * @return true if this feature intercepts and takes ownership.
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeOffer(PolicyController controller,
+ CommInfrastructure protocol,
+ String topic,
+ String event) {
+ return false;
+ }
+
+ /**
+ * called after the Policy Controller processes an event offer.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterOffer(PolicyController controller,
+ CommInfrastructure protocol,
+ String topic,
+ String event,
+ boolean success) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Controller delivers (posts) an event.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeDeliver(PolicyController controller,
+ CommInfrastructure protocol,
+ String topic,
+ Object event) {
+ return false;
+ }
+
+ /**
+ * called after the Policy Controller delivers (posts) an event.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterDeliver(PolicyController controller,
+ CommInfrastructure protocol,
+ String topic,
+ Object event,
+ boolean success) {
+ return false;
+ }
}
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 956401ad..66b206b6 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
@@ -30,172 +30,208 @@ import org.onap.policy.drools.utils.OrderedServiceImpl;
* Policy Engine Feature API.
* Provides Interception Points during the Policy Engine lifecycle.
*/
-public interface PolicyEngineFeatureAPI extends OrderedService {
- /**
- * Feature providers implementing this interface
- */
- public static final OrderedServiceImpl<PolicyEngineFeatureAPI> providers =
- new OrderedServiceImpl<>(PolicyEngineFeatureAPI.class);
-
- /**
- * intercept before the Policy Engine is commanded to boot.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeBoot(PolicyEngine engine, String[] cliArgs) {return false;};
-
- /**
- * intercept after the Policy Engine is booted.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterBoot(PolicyEngine engine) {return false;};
-
- /**
- * intercept before the Policy Engine is configured.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeConfigure(PolicyEngine engine, Properties properties) {return false;};
-
- /**
- * intercept after the Policy Engine is configured.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterConfigure(PolicyEngine engine) {return false;};
-
- /**
- * intercept before the Policy Engine goes active.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeActivate(PolicyEngine engine) {return false;};
-
- /**
- * intercept after the Policy Engine goes active.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterActivate(PolicyEngine engine) {return false;};
-
- /**
- * intercept before the Policy Engine goes standby.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeDeactivate(PolicyEngine engine) {return false;};
-
- /**
- * intercept after the Policy Engine goes standby.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterDeactivate(PolicyEngine engine) {return false;};
-
- /**
- * intercept before the Policy Engine is started.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeStart(PolicyEngine engine) {return false;};
-
- /**
- * intercept after the Policy Engine is started.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterStart(PolicyEngine engine) {return false;};
-
- /**
- * intercept before the Policy Engine is stopped.
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise..
- */
- public default boolean beforeStop(PolicyEngine engine) {return false;};
-
- /**
- * intercept after the Policy Engine is stopped
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.d.
- */
- public default boolean afterStop(PolicyEngine engine) {return false;};
-
- /**
- * intercept before the Policy Engine is locked
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeLock(PolicyEngine engine) {return false;};
-
- /**
- * intercept after the Policy Engine is locked
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise..
- */
- public default boolean afterLock(PolicyEngine engine) {return false;};
-
- /**
- * intercept before the Policy Engine is locked
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean beforeUnlock(PolicyEngine engine) {return false;};
-
- /**
- * intercept after the Policy Engine is locked
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterUnlock(PolicyEngine engine) {return false;};
-
- /**
- * intercept the Policy Engine is shut down
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise..
- */
- public default boolean beforeShutdown(PolicyEngine engine){return false;};
-
- /**
- * called after the Policy Engine is shut down
- *
- * @return true if this feature intercepts and takes ownership
- * of the operation preventing the invocation of
- * lower priority features. False, otherwise.
- */
- public default boolean afterShutdown(PolicyEngine engine) {return false;};
+public interface PolicyEngineFeatureAPI extends OrderedService {
+ /**
+ * Feature providers implementing this interface.
+ */
+ public static final OrderedServiceImpl<PolicyEngineFeatureAPI> providers =
+ new OrderedServiceImpl<>(PolicyEngineFeatureAPI.class);
+
+ /**
+ * intercept before the Policy Engine is commanded to boot.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeBoot(PolicyEngine engine, String[] cliArgs) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Engine is booted.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterBoot(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Engine is configured.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeConfigure(PolicyEngine engine, Properties properties) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Engine is configured.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterConfigure(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Engine goes active.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeActivate(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Engine goes active.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterActivate(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Engine goes standby.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeDeactivate(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Engine goes standby.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterDeactivate(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Engine is started.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeStart(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Engine is started.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterStart(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Engine is stopped.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise..
+ */
+ public default boolean beforeStop(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Engine is stopped.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.d.
+ */
+ public default boolean afterStop(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Engine is locked.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeLock(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Engine is locked.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise..
+ */
+ public default boolean afterLock(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept before the Policy Engine is locked.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean beforeUnlock(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept after the Policy Engine is locked.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterUnlock(PolicyEngine engine) {
+ return false;
+ }
+
+ /**
+ * intercept the Policy Engine is shut down.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise..
+ */
+ public default boolean beforeShutdown(PolicyEngine engine){
+ return false;
+ }
+
+ /**
+ * called after the Policy Engine is shut down.
+ *
+ * @return true if this feature intercepts and takes ownership
+ * of the operation preventing the invocation of
+ * lower priority features. False, otherwise.
+ */
+ public default boolean afterShutdown(PolicyEngine engine) {
+ return false;
+ }
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java b/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java
index b1e49ec2..6864a346 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java
@@ -17,6 +17,7 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
+
package org.onap.policy.drools.persistence;
import java.io.File;
@@ -37,276 +38,282 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Properties based Persistence
+ * Properties based Persistence.
*/
public class FileSystemPersistence implements SystemPersistence {
- /**
- * policy controllers suffix
- */
- public static final String CONTROLLER_SUFFIX_IDENTIFIER = "-controller";
-
- /**
- * policy controller properties file suffix
- */
- public static final String PROPERTIES_FILE_CONTROLLER_SUFFIX =
- CONTROLLER_SUFFIX_IDENTIFIER + ".properties";
-
- /**
- * policy controller properties file suffix
- */
- public static final String PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX =
- CONTROLLER_SUFFIX_IDENTIFIER + ".properties.bak";
-
- /**
- * policy engine properties file name
- */
- public static final String PROPERTIES_FILE_ENGINE = "policy-engine.properties";
-
- /**
- * Installation environment suffix for files
- */
- public static final String ENV_SUFFIX = ".environment";
-
- /**
- * configuration directory
- */
- protected Path configurationDirectory = Paths.get(DEFAULT_CONFIGURATION_DIR);
-
- /**
- * logger
- */
- private static final Logger logger = LoggerFactory.getLogger(FileSystemPersistence.class);
-
-
- @Override
- public void setConfigurationDir(String configDir) {
- String tempConfigDir = configDir;
- if (tempConfigDir == null) {
- tempConfigDir = DEFAULT_CONFIGURATION_DIR;
- this.configurationDirectory = Paths.get(DEFAULT_CONFIGURATION_DIR);
+ /**
+ * policy controllers suffix.
+ */
+ public static final String CONTROLLER_SUFFIX_IDENTIFIER = "-controller";
+
+ /**
+ * policy controller properties file suffix.
+ */
+ public static final String PROPERTIES_FILE_CONTROLLER_SUFFIX =
+ CONTROLLER_SUFFIX_IDENTIFIER + ".properties";
+
+ /**
+ * policy controller properties file suffix.
+ */
+ public static final String PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX =
+ CONTROLLER_SUFFIX_IDENTIFIER + ".properties.bak";
+
+ /**
+ * policy engine properties file name.
+ */
+ public static final String PROPERTIES_FILE_ENGINE = "policy-engine.properties";
+
+ /**
+ * Installation environment suffix for files.
+ */
+ public static final String ENV_SUFFIX = ".environment";
+
+ /**
+ * configuration directory.
+ */
+ protected Path configurationDirectory = Paths.get(DEFAULT_CONFIGURATION_DIR);
+
+ /**
+ * logger.
+ */
+ private static final Logger logger = LoggerFactory.getLogger(FileSystemPersistence.class);
+
+
+ @Override
+ public void setConfigurationDir(String configDir) {
+ String tempConfigDir = configDir;
+
+ if (tempConfigDir == null) {
+ tempConfigDir = DEFAULT_CONFIGURATION_DIR;
+ this.configurationDirectory = Paths.get(DEFAULT_CONFIGURATION_DIR);
+ }
+
+ if (!tempConfigDir.equals(DEFAULT_CONFIGURATION_DIR)) {
+ this.configurationDirectory = Paths.get(tempConfigDir);
+ }
+
+ if (Files.notExists(this.configurationDirectory)) {
+ try {
+ Files.createDirectories(this.configurationDirectory);
+ } catch (final IOException e) {
+ throw new IllegalStateException("cannot create " + this.configurationDirectory, e);
+ }
+ }
+
+ if (!Files.isDirectory(this.configurationDirectory)) {
+ throw new IllegalStateException(
+ "config directory: " + this.configurationDirectory + " is not a directory");
+ }
+ }
+
+ @Override
+ public Path getConfigurationPath() {
+ return this.configurationDirectory;
}
- if (!tempConfigDir.equals(DEFAULT_CONFIGURATION_DIR))
- this.configurationDirectory = Paths.get(tempConfigDir);
+ @Override
+ public Properties getEngineProperties() {
+ final Path policyEnginePath =
+ Paths.get(this.configurationDirectory.toString(), PROPERTIES_FILE_ENGINE);
+ try {
+ if (Files.exists(policyEnginePath)) {
+ return PropertyUtil.getProperties(policyEnginePath.toFile());
+ }
+ } catch (final Exception e) {
+ logger.warn("{}: could not find {}", this, policyEnginePath, e);
+ }
- if (Files.notExists(this.configurationDirectory)) {
- try {
- Files.createDirectories(this.configurationDirectory);
- } catch (final IOException e) {
- throw new IllegalStateException("cannot create " + this.configurationDirectory, e);
- }
+ return null;
}
- if (!Files.isDirectory(this.configurationDirectory))
- throw new IllegalStateException(
- "config directory: " + this.configurationDirectory + " is not a directory");
- }
-
- @Override
- public Path getConfigurationPath() {
- return this.configurationDirectory;
- }
-
- @Override
- public Properties getEngineProperties() {
- final Path policyEnginePath =
- Paths.get(this.configurationDirectory.toString(), PROPERTIES_FILE_ENGINE);
- try {
- if (Files.exists(policyEnginePath))
- return PropertyUtil.getProperties(policyEnginePath.toFile());
- } catch (final Exception e) {
- logger.warn("{}: could not find {}", this, policyEnginePath, e);
+ @Override
+ public boolean backupController(String controllerName) {
+ final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
+ controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
+
+ if (Files.exists(controllerPropertiesPath)) {
+ try {
+ logger.info("{}: there is an existing configuration file @ {} ", this,
+ controllerPropertiesPath);
+ final Path controllerPropertiesBakPath = Paths.get(this.configurationDirectory.toString(),
+ controllerName + PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX);
+ Files.copy(controllerPropertiesPath, controllerPropertiesBakPath,
+ StandardCopyOption.REPLACE_EXISTING);
+ } catch (final Exception e) {
+ logger.warn("{}: {} cannot be backed up", this, controllerName, e);
+ return false;
+ }
+ }
+
+ return true;
}
- return null;
- }
-
- @Override
- public boolean backupController(String controllerName) {
- final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
- controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
-
- if (Files.exists(controllerPropertiesPath)) {
- try {
- logger.info("{}: there is an existing configuration file @ {} ", this,
- controllerPropertiesPath);
- final Path controllerPropertiesBakPath = Paths.get(this.configurationDirectory.toString(),
- controllerName + PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX);
- Files.copy(controllerPropertiesPath, controllerPropertiesBakPath,
- StandardCopyOption.REPLACE_EXISTING);
- } catch (final Exception e) {
- logger.warn("{}: {} cannot be backed up", this, controllerName, e);
- return false;
- }
+ @Override
+ public boolean storeController(String controllerName, Object configuration) {
+ if (!(configuration instanceof Properties)) {
+ throw new IllegalArgumentException(
+ "configuration must be of type properties to be handled by this manager");
+ }
+
+ final Properties properties = (Properties) configuration;
+
+ final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
+ controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
+ if (Files.exists(controllerPropertiesPath)) {
+ try {
+ final Properties oldProperties =
+ PropertyUtil.getProperties(controllerPropertiesPath.toFile());
+ if (oldProperties.equals(properties)) {
+ logger.info(
+ "{}: noop: a properties file with the same contents exists for controller {}.", this,
+ controllerName);
+ return true;
+ } else {
+ this.backupController(controllerName);
+ }
+ } catch (final Exception e) {
+ logger.info("{}: no existing {} properties {}", this, controllerName, e);
+ // continue
+ }
+ }
+
+ final File controllerPropertiesFile = controllerPropertiesPath.toFile();
+ try (FileWriter writer = new FileWriter(controllerPropertiesFile)) {
+ properties.store(writer, "Machine created Policy Controller Configuration");
+ } catch (final Exception e) {
+ logger.warn("{}: {} cannot be saved", this, controllerName, e);
+ return false;
+ }
+
+ return true;
}
- return true;
- }
-
- @Override
- public boolean storeController(String controllerName, Object configuration) {
- if (!(configuration instanceof Properties))
- throw new IllegalArgumentException(
- "configuration must be of type properties to be handled by this manager");
-
- final Properties properties = (Properties) configuration;
-
- final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
- controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
- if (Files.exists(controllerPropertiesPath)) {
- try {
- final Properties oldProperties =
- PropertyUtil.getProperties(controllerPropertiesPath.toFile());
- if (oldProperties.equals(properties)) {
- logger.info(
- "{}: noop: a properties file with the same contents exists for controller {}.", this,
- controllerName);
- return true;
- } else {
- this.backupController(controllerName);
+ @Override
+ public boolean deleteController(String controllerName) {
+ final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
+ controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
+
+ if (Files.exists(controllerPropertiesPath)) {
+ try {
+ final Path controllerPropertiesBakPath = Paths.get(this.configurationDirectory.toString(),
+ controllerName + PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX);
+ Files.move(controllerPropertiesPath, controllerPropertiesBakPath,
+ StandardCopyOption.REPLACE_EXISTING);
+ } catch (final Exception e) {
+ logger.warn("{}: {} cannot be deleted", this, controllerName, e);
+ return false;
+ }
}
- } catch (final Exception e) {
- logger.info("{}: no existing {} properties {}", this, controllerName, e);
- // continue
- }
+
+ return true;
}
- final File controllerPropertiesFile = controllerPropertiesPath.toFile();
- try (FileWriter writer = new FileWriter(controllerPropertiesFile)) {
- properties.store(writer, "Machine created Policy Controller Configuration");
- } catch (final Exception e) {
- logger.warn("{}: {} cannot be saved", this, controllerName, e);
- return false;
+ @Override
+ public Properties getControllerProperties(String controllerName) {
+ return this.getProperties(controllerName + CONTROLLER_SUFFIX_IDENTIFIER);
}
- return true;
- }
-
- @Override
- public boolean deleteController(String controllerName) {
- final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
- controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
-
- if (Files.exists(controllerPropertiesPath)) {
- try {
- final Path controllerPropertiesBakPath = Paths.get(this.configurationDirectory.toString(),
- controllerName + PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX);
- Files.move(controllerPropertiesPath, controllerPropertiesBakPath,
- StandardCopyOption.REPLACE_EXISTING);
- } catch (final Exception e) {
- logger.warn("{}: {} cannot be deleted", this, controllerName, e);
- return false;
- }
+ @Override
+ public List<Properties> getControllerProperties() {
+ final List<Properties> controllers = new ArrayList<>();
+ final File[] controllerFiles = this.sortedListFiles();
+ for (final File controllerFile : controllerFiles) {
+ if (controllerFile.getName().endsWith(PROPERTIES_FILE_CONTROLLER_SUFFIX)) {
+ final int idxSuffix = controllerFile.getName().indexOf(PROPERTIES_FILE_CONTROLLER_SUFFIX);
+ final int lastIdxSuffix =
+ controllerFile.getName().lastIndexOf(PROPERTIES_FILE_CONTROLLER_SUFFIX);
+ if (idxSuffix != lastIdxSuffix) {
+ throw new IllegalArgumentException(
+ "Improper naming of controller properties file: " + "Expected <controller-name>"
+ + FileSystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX);
+ }
+
+ final String name = controllerFile.getName().substring(0, lastIdxSuffix);
+ try {
+ final Properties controllerProperties = this.getControllerProperties(name);
+ final String controllerName =
+ controllerProperties.getProperty(DroolsProperties.PROPERTY_CONTROLLER_NAME);
+ if (controllerName == null) {
+ controllerProperties.setProperty(DroolsProperties.PROPERTY_CONTROLLER_NAME, name);
+ } else if (!controllerName.equals(name)) {
+ logger.error("{}: mismatch controller named {} with file name {}", this, controllerName,
+ controllerFile.getName());
+ continue;
+ }
+ controllers.add(this.getControllerProperties(name));
+ } catch (final Exception e) {
+ logger.error("{}: cannot obtain properties for controller {} because of {}", name,
+ e.getMessage(), e);
+ }
+ }
+ }
+ return controllers;
}
- return true;
- }
-
- @Override
- public Properties getControllerProperties(String controllerName) {
- return this.getProperties(controllerName + CONTROLLER_SUFFIX_IDENTIFIER);
- }
-
- @Override
- public List<Properties> getControllerProperties() {
- final List<Properties> controllers = new ArrayList<>();
- final File[] controllerFiles = this.sortedListFiles();
- for (final File controllerFile : controllerFiles) {
- if (controllerFile.getName().endsWith(PROPERTIES_FILE_CONTROLLER_SUFFIX)) {
- final int idxSuffix = controllerFile.getName().indexOf(PROPERTIES_FILE_CONTROLLER_SUFFIX);
- final int lastIdxSuffix =
- controllerFile.getName().lastIndexOf(PROPERTIES_FILE_CONTROLLER_SUFFIX);
- if (idxSuffix != lastIdxSuffix)
- throw new IllegalArgumentException(
- "Improper naming of controller properties file: " + "Expected <controller-name>"
- + FileSystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX);
-
- final String name = controllerFile.getName().substring(0, lastIdxSuffix);
+ @Override
+ public Properties getProperties(String name) {
+ final Path propertiesPath =
+ Paths.get(this.configurationDirectory.toString(), name + ".properties");
+
+ if (!Files.exists(propertiesPath)) {
+ throw new IllegalArgumentException("properties for " + name + " are not persisted.");
+ }
+
try {
- final Properties controllerProperties = this.getControllerProperties(name);
- final String controllerName =
- controllerProperties.getProperty(DroolsProperties.PROPERTY_CONTROLLER_NAME);
- if (controllerName == null) {
- controllerProperties.setProperty(DroolsProperties.PROPERTY_CONTROLLER_NAME, name);
- } else if (!controllerName.equals(name)) {
- logger.error("{}: mismatch controller named {} with file name {}", this, controllerName,
- controllerFile.getName());
- continue;
- }
- controllers.add(this.getControllerProperties(name));
+ return PropertyUtil.getProperties(propertiesPath.toFile());
} catch (final Exception e) {
- logger.error("{}: cannot obtain properties for controller {} because of {}", name,
- e.getMessage(), e);
+ logger.warn("{}: can't read properties @ {}", name, propertiesPath);
+ throw new IllegalArgumentException(
+ "can't read properties for " + name + " @ " + propertiesPath, e);
}
- }
}
- return controllers;
- }
- @Override
- public Properties getProperties(String name) {
- final Path propertiesPath =
- Paths.get(this.configurationDirectory.toString(), name + ".properties");
-
- if (!Files.exists(propertiesPath)) {
- throw new IllegalArgumentException("properties for " + name + " are not persisted.");
+ @Override
+ public List<Properties> getEnvironmentProperties() {
+ final List<Properties> envs = new ArrayList<>();
+ final File[] envFiles = this.sortedListFiles();
+ for (final File envFile : envFiles) {
+ if (envFile.getName().endsWith(ENV_SUFFIX)) {
+ final String name = envFile.getName().substring(0, envFile.getName().indexOf(ENV_SUFFIX));
+ try {
+ envs.add(this.getEnvironmentProperties(name));
+ } catch (final Exception e) {
+ logger.error("{}: cannot get environment {} because of {}", name, e.getMessage(), e);
+ }
+ }
+ }
+ return envs;
}
- try {
- return PropertyUtil.getProperties(propertiesPath.toFile());
- } catch (final Exception e) {
- logger.warn("{}: can't read properties @ {}", name, propertiesPath);
- throw new IllegalArgumentException(
- "can't read properties for " + name + " @ " + propertiesPath, e);
- }
- }
-
- @Override
- public List<Properties> getEnvironmentProperties() {
- final List<Properties> envs = new ArrayList<>();
- final File[] envFiles = this.sortedListFiles();
- for (final File envFile : envFiles) {
- if (envFile.getName().endsWith(ENV_SUFFIX)) {
- final String name = envFile.getName().substring(0, envFile.getName().indexOf(ENV_SUFFIX));
+ @Override
+ public Properties getEnvironmentProperties(String name) {
+ final Path envPath = Paths.get(this.configurationDirectory.toString(), name + ENV_SUFFIX);
+ if (!Files.exists(envPath)) {
+ throw new IllegalArgumentException("{} environment" + name + " cannot be retrieved");
+ }
+
try {
- envs.add(this.getEnvironmentProperties(name));
+ return PropertyUtil.getProperties(envPath.toFile());
} catch (final Exception e) {
- logger.error("{}: cannot get environment {} because of {}", name, e.getMessage(), e);
+ throw new IllegalArgumentException("cannot read environment " + name, e);
}
- }
- }
- return envs;
- }
-
- @Override
- public Properties getEnvironmentProperties(String name) {
- final Path envPath = Paths.get(this.configurationDirectory.toString(), name + ENV_SUFFIX);
- if (!Files.exists(envPath)) {
- throw new IllegalArgumentException("{} environment" + name + " cannot be retrieved");
}
- try {
- return PropertyUtil.getProperties(envPath.toFile());
- } catch (final Exception e) {
- throw new IllegalArgumentException("cannot read environment " + name, e);
+ /**
+ * provides a list of files sorted by name in ascending order in the configuration directory.
+ */
+ protected File[] sortedListFiles() {
+ final File[] dirFiles = this.configurationDirectory.toFile().listFiles();
+ Arrays.sort(dirFiles, (a, b) -> a.getName().compareTo(b.getName()));
+ return dirFiles;
}
- }
-
- /**
- * provides a list of files sorted by name in ascending order in the configuration directory
- */
- protected File[] sortedListFiles() {
- final File[] dirFiles = this.configurationDirectory.toFile().listFiles();
- Arrays.sort(dirFiles, (a, b) -> a.getName().compareTo(b.getName()));
- return dirFiles;
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("FileSystemPersistence [configurationDirectory=")
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("FileSystemPersistence [configurationDirectory=")
.append(this.configurationDirectory).append("]");
- return builder.toString();
- }
+ return builder.toString();
+ }
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/persistence/SystemPersistence.java b/policy-management/src/main/java/org/onap/policy/drools/persistence/SystemPersistence.java
index 0d0a33ce..34b27c23 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/persistence/SystemPersistence.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/persistence/SystemPersistence.java
@@ -25,108 +25,107 @@ import java.util.List;
import java.util.Properties;
/**
- * System Configuration
+ * System Configuration.
*/
public interface SystemPersistence {
- /**
- * configuration directory
- */
- public static final String DEFAULT_CONFIGURATION_DIR = "config";
+ /**
+ * configuration directory.
+ */
+ public static final String DEFAULT_CONFIGURATION_DIR = "config";
- /**
- * Persistence Manager. For now it is a file-based properties management, In the future, it will
- * probably be DB based, so manager implementation will change.
- */
- public static final SystemPersistence manager = new FileSystemPersistence();
+ /**
+ * Persistence Manager. For now it is a file-based properties management, In the future, it will
+ * probably be DB based, so manager implementation will change.
+ */
+ public static final SystemPersistence manager = new FileSystemPersistence();
- /**
- * sets a configuration directory and ensures it exists
- *
- * @param configDir configuration directory or null to use the default one
- */
- public void setConfigurationDir(String configDir);
+ /**
+ * sets a configuration directory and ensures it exists.
+ *
+ * @param configDir configuration directory or null to use the default one
+ */
+ public void setConfigurationDir(String configDir);
- /**
- * get configuration directory path
- *
- * @return configuration directory path
- */
- public Path getConfigurationPath();
+ /**
+ * get configuration directory path.
+ *
+ * @return configuration directory path
+ */
+ public Path getConfigurationPath();
- /**
- * backs up a controller configuration.
- *
- * @param controllerName the controller name
- * @return true if the configuration is backed up
- */
- public boolean backupController(String controllerName);
+ /**
+ * backs up a controller configuration.
+ *
+ * @param controllerName the controller name
+ * @return true if the configuration is backed up
+ */
+ public boolean backupController(String controllerName);
- /**
- * persists controller configuration
- *
- * @param controllerName the controller name
- * @param configuration object containing the configuration
- *
- * @return true if storage is succesful, false otherwise
- * @throws IllegalArgumentException if the configuration cannot be handled by the persistence
- * manager
- */
- public boolean storeController(String controllerName, Object configuration);
+ /**
+ * persists controller configuration.
+ *
+ * @param controllerName the controller name
+ * @param configuration object containing the configuration
+ *
+ * @return true if storage is succesful, false otherwise
+ * @throws IllegalArgumentException if the configuration cannot be handled by the persistence
+ * manager
+ */
+ public boolean storeController(String controllerName, Object configuration);
- /**
- * delete controller configuration
- *
- * @param controllerName the controller name
- * @return true if storage is succesful, false otherwise
- */
- public boolean deleteController(String controllerName);
+ /**
+ * delete controller configuration.
+ *
+ * @param controllerName the controller name
+ * @return true if storage is succesful, false otherwise
+ */
+ public boolean deleteController(String controllerName);
- /**
- * get controller properties
- *
- * @param controllerName controller name
- * @return properties for this controller
- *
- * @throws IllegalArgumentException if the controller name does not lead to a properties
- * configuration
- */
- public Properties getControllerProperties(String controllerName);
+ /**
+ * get controller properties.
+ *
+ * @param controllerName controller name
+ * @return properties for this controller
+ *
+ * @throws IllegalArgumentException if the controller name does not lead to a properties
+ * configuration
+ */
+ public Properties getControllerProperties(String controllerName);
- /**
- * get controllers configuration
- *
- * @return list of controllers properties
- */
- public List<Properties> getControllerProperties();
+ /**
+ * get controllers configuration.
+ *
+ * @return list of controllers properties
+ */
+ public List<Properties> getControllerProperties();
- /**
- * get environments
- *
- * @param environment name
- */
- public List<Properties> getEnvironmentProperties();
+ /**
+ * get environments.
+ *
+ */
+ public List<Properties> getEnvironmentProperties();
- /**
- * get environment properties
- *
- * @param environment name
- */
- public Properties getEnvironmentProperties(String environmentName);
+ /**
+ * get environment properties.
+ *
+ * @param environmentName name
+ */
+ public Properties getEnvironmentProperties(String environmentName);
- /**
- * get the engine properties
- *
- * @return the engine properties
- */
- public Properties getEngineProperties();
+ /**
+ * get the engine properties.
+ *
+ * @return the engine properties
+ */
+ public Properties getEngineProperties();
- /**
- * get properties by name
- *
- * @param name
- * @return properties
- *
- * @throws IllegalArgumentException if the name does not lead to a properties configuration
- */
- public Properties getProperties(String name);
+ /**
+ * get properties by name.
+ *
+ * @param name name
+ * @return properties
+ *
+ * @throws IllegalArgumentException if the name does not lead to a properties configuration
+ */
+ public Properties getProperties(String name);
}
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 d0008f08..3e4e7ecd 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
@@ -38,344 +38,355 @@ import org.slf4j.LoggerFactory;
* Coder (Encoder/Decoder) of Events.
*/
public interface EventProtocolCoder {
-
- /**
- * singleton reference to the global event protocol coder
- */
- public static EventProtocolCoder manager = new MultiplexorEventProtocolCoder();
-
- public static class CoderFilters {
-
- /**
- * coder class
- */
- protected String factClass;
-
- /**
- * filters to apply to the selection of the decodedClass;
- */
- protected JsonProtocolFilter filter;
-
- /**
- * classloader hash
- */
- protected int modelClassLoaderHash;
-
-
- /**
- * constructor
- *
- * @param codedClass coder class
- * @param filter filters to apply
- */
- public CoderFilters(String codedClass, JsonProtocolFilter filter, int modelClassLoaderHash) {
- this.factClass = codedClass;
- this.filter = filter;
- this.modelClassLoaderHash = modelClassLoaderHash;
- }
-
- /**
- * @return the codedClass
- */
- public String getCodedClass() {
- return factClass;
- }
-
- /**
- * @param codedClass the decodedClass to set
- */
- public void setCodedClass(String codedClass) {
- this.factClass = codedClass;
- }
-
- /**
- * @return the filter
- */
- public JsonProtocolFilter getFilter() {
- return filter;
- }
-
- /**
- * @param filter the filter to set
- */
- public void setFilter(JsonProtocolFilter filter) {
- this.filter = filter;
- }
-
- public int getModelClassLoaderHash() {
- return modelClassLoaderHash;
- }
-
- public void setFromClassLoaderHash(int fromClassLoaderHash) {
- this.modelClassLoaderHash = fromClassLoaderHash;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("CoderFilters [factClass=").append(factClass).append(", filter=").append(filter)
- .append(", modelClassLoaderHash=").append(modelClassLoaderHash).append("]");
- return builder.toString();
- }
-
- }
-
- /**
- * Adds a Decoder class to decode the protocol over this topic
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic the topic
- * @param eventClass the event class
- * @param protocolFilter filters to selectively choose a particular decoder
- * when there are multiples
- *
- * @throw IllegalArgumentException if an invalid parameter is passed
- */
- public void addDecoder(String groupId, String artifactId,
- String topic,
- String eventClass,
- JsonProtocolFilter protocolFilter,
- CustomGsonCoder customGsonCoder,
- CustomJacksonCoder customJacksonCoder,
- int modelClassLoaderHash);
-
- /**
- * removes all decoders associated with the controller id
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic of the controller
- *
- * @throws IllegalArgumentException if invalid arguments have been provided
- */
- void removeEncoders(String groupId, String artifactId, String topic);
-
- /**
- * removes decoders associated with the controller id and topic
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic the topic
- *
- * @throws IllegalArgumentException if invalid arguments have been provided
- */
- public void removeDecoders(String groupId, String artifactId, String topic);
-
- /**
- * Given a controller id and a topic, it gives back its filters
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic the topic
- *
- * return list of decoders
- *
- * @throw IllegalArgumentException if an invalid parameter is passed
- */
- public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic);
-
-
- /**
- * Given a controller id and a topic, it gives back the decoding configuration
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic the topic
- *
- * return decoding toolset
- *
- * @throw IllegalArgumentException if an invalid parameter is passed
- */
- public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic);
-
- /**
- * Given a controller id and a topic, it gives back all the decoding configurations
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic the topic
- *
- * return decoding toolset
- *
- * @throw IllegalArgumentException if an invalid parameter is passed
- */
- public List<ProtocolCoderToolset> getDecoders(String groupId, String artifactId);
-
-
- /**
- * gets all decoders associated with the group and artifact ids
- * @param groupId of the controller
- * @param artifactId of the controller
- *
- * @throws IllegalArgumentException if invalid arguments have been provided
- */
- public List<CoderFilters> getDecoderFilters(String groupId, String artifactId);
-
-
- /**
- * Given a controller id and a topic, it gives back the classes that implements the encoding
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic the topic
- *
- * return list of decoders
- *
- * @throw IllegalArgumentException if an invalid parameter is passed
- */
- public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic);
-
- /**
- * gets all encoders associated with the group and artifact ids
- * @param groupId of the controller
- * @param artifactId of the controller
- *
- * @throws IllegalArgumentException if invalid arguments have been provided
- */
- public List<CoderFilters> getEncoderFilters(String groupId, String artifactId);
-
- /**
- * Given a controller id, a topic, and a classname, it gives back the classes that implements the decoding
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic the topic
- * @param classname classname
- *
- * return list of decoders
- *
- * @throw IllegalArgumentException if an invalid parameter is passed
- */
- public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname);
-
- /**
- * is there a decoder supported for the controller id and topic
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic protocol
- * @return true if supported
- */
- public boolean isDecodingSupported(String groupId, String artifactId, String topic);
-
- /**
- * Adds a Encoder class to encode the protocol over this topic
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic the topic
- * @param eventClass the event class
- * @param protocolFilter filters to selectively choose a particular decoder
- * when there are multiples
- *
- * @throw IllegalArgumentException if an invalid parameter is passed
- */
- public void addEncoder(String groupId, String artifactId, String topic,
- String eventClass,
- JsonProtocolFilter protocolFilter,
- CustomGsonCoder customGsonCoder,
- CustomJacksonCoder customJacksonCoder,
- int modelClassLoaderHash);
-
- /**
- * is there an encoder supported for the controller id and topic
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic protocol
- * @return true if supported
- */
- public boolean isEncodingSupported(String groupId, String artifactId, String topic);
-
- /**
- * get encoder based on coordinates and classname
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic protocol
- * @param json event string
- * @return
- * @throws IllegalArgumentException invalid arguments passed in
- */
- public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname);
-
- /**
- * get encoder based on topic and encoded class
- *
- * @param topic topic
- * @param encodedClass encoded class
- * @return
- * @throws IllegalArgumentException invalid arguments passed in
- */
- public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass);
-
- /**
- * gets the identifier of the creator of the encoder
- *
- * @param topic topic
- * @param encodedClass encoded class
- * @return a drools controller
- * @throws IllegalArgumentException invalid arguments passed in
- */
- public DroolsController getDroolsController(String topic, Object encodedClass);
-
- /**
- * gets the identifier of the creator of the encoder
- *
- * @param topic topic
- * @param encodedClass encoded class
- * @return list of drools controllers
- * @throws IllegalArgumentException invalid arguments passed in
- */
- public List<DroolsController> getDroolsControllers(String topic, Object encodedClass);
-
- /**
- * decode topic's stringified event (json) to corresponding Event Object.
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic protocol
- * @param json event string
- * @return
- * @throws IllegalArgumentException invalid arguments passed in
- * @throws UnsupportedOperationException if the operation is not supported
- * @throws IllegalStateException if the system is in an illegal state
- */
- public Object decode(String groupId, String artifactId, String topic, String json);
-
- /**
- * encodes topic's stringified event (json) to corresponding Event Object.
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic protocol
- * @param event Object
- *
- * @throws IllegalArgumentException invalid arguments passed in
- */
- public String encode(String groupId, String artifactId, String topic, Object event);
-
- /**
- * encodes topic's stringified event (json) to corresponding Event Object.
- *
- * @param topic topic
- * @param event event object
- *
- * @throws IllegalArgumentException invalid arguments passed in
- * @throws UnsupportedOperationException operation cannot be performed
- */
- public String encode(String topic, Object event);
-
- /**
- * encodes topic's stringified event (json) to corresponding Event Object.
- *
- * @param topic topic
- * @param event event object
- * @param droolsController
- *
- * @throws IllegalArgumentException invalid arguments passed in
- * @throws UnsupportedOperationException operation cannot be performed
- */
- public String encode(String topic, Object event, DroolsController droolsController);
+
+ /**
+ * singleton reference to the global event protocol coder.
+ */
+ public static EventProtocolCoder manager = new MultiplexorEventProtocolCoder();
+
+ public static class CoderFilters {
+
+ /**
+ * coder class.
+ */
+ protected String factClass;
+
+ /**
+ * filters to apply to the selection of the decodedClass.
+ */
+ protected JsonProtocolFilter filter;
+
+ /**
+ * classloader hash.
+ */
+ protected int modelClassLoaderHash;
+
+
+ /**
+ * constructor.
+ *
+ * @param codedClass coder class
+ * @param filter filters to apply
+ */
+ public CoderFilters(String codedClass, JsonProtocolFilter filter, int modelClassLoaderHash) {
+ this.factClass = codedClass;
+ this.filter = filter;
+ this.modelClassLoaderHash = modelClassLoaderHash;
+ }
+
+ /**
+ * Get coded class.
+ *
+ * @return the codedClass
+ */
+ public String getCodedClass() {
+ return factClass;
+ }
+
+ /**
+ * Set coded class.
+ *
+ * @param codedClass the decodedClass to set
+ */
+ public void setCodedClass(String codedClass) {
+ this.factClass = codedClass;
+ }
+
+ /**
+ * Get filter.
+ *
+ * @return the filter
+ */
+ public JsonProtocolFilter getFilter() {
+ return filter;
+ }
+
+ /**
+ * Set filter.
+ *
+ * @param filter the filter to set
+ */
+ public void setFilter(JsonProtocolFilter filter) {
+ this.filter = filter;
+ }
+
+ public int getModelClassLoaderHash() {
+ return modelClassLoaderHash;
+ }
+
+ public void setFromClassLoaderHash(int fromClassLoaderHash) {
+ this.modelClassLoaderHash = fromClassLoaderHash;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("CoderFilters [factClass=").append(factClass).append(", filter=").append(filter)
+ .append(", modelClassLoaderHash=").append(modelClassLoaderHash).append("]");
+ return builder.toString();
+ }
+
+ }
+
+ /**
+ * Adds a Decoder class to decode the protocol over this topic.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic the topic
+ * @param eventClass the event class
+ * @param protocolFilter filters to selectively choose a particular decoder
+ * when there are multiples
+ *
+ * @throw IllegalArgumentException if an invalid parameter is passed
+ */
+ public void addDecoder(String groupId, String artifactId,
+ String topic,
+ String eventClass,
+ JsonProtocolFilter protocolFilter,
+ CustomGsonCoder customGsonCoder,
+ CustomJacksonCoder customJacksonCoder,
+ int modelClassLoaderHash);
+
+ /**
+ * removes all decoders associated with the controller id.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic of the controller
+ *
+ * @throws IllegalArgumentException if invalid arguments have been provided
+ */
+ void removeEncoders(String groupId, String artifactId, String topic);
+
+ /**
+ * removes decoders associated with the controller id and topic.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic the topic
+ *
+ * @throws IllegalArgumentException if invalid arguments have been provided
+ */
+ public void removeDecoders(String groupId, String artifactId, String topic);
+
+ /**
+ * Given a controller id and a topic, it gives back its filters.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic the topic
+ *
+ * @return list of decoders
+ *
+ * @throw IllegalArgumentException if an invalid parameter is passed
+ */
+ public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic);
+
+
+ /**
+ * Given a controller id and a topic, it gives back the decoding configuration.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic the topic
+ *
+ * @return decoding toolset
+ *
+ * @throw IllegalArgumentException if an invalid parameter is passed
+ */
+ public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic);
+
+ /**
+ * Given a controller id and a topic, it gives back all the decoding configurations.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ *
+ * @return decoding toolset
+ *
+ * @throw IllegalArgumentException if an invalid parameter is passed
+ */
+ public List<ProtocolCoderToolset> getDecoders(String groupId, String artifactId);
+
+ /**
+ * gets all decoders associated with the group and artifact ids.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ *
+ * @throws IllegalArgumentException if invalid arguments have been provided
+ */
+ public List<CoderFilters> getDecoderFilters(String groupId, String artifactId);
+
+
+ /**
+ * Given a controller id, a topic, and a classname, it gives back the classes that implements the decoding.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic the topic
+ * @param classname classname
+ *
+ * @return list of decoders
+ *
+ * @throw IllegalArgumentException if an invalid parameter is passed
+ */
+ public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname);
+
+ /**
+ * Given a controller id and a topic, it gives back the classes that implements the encoding.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic the topic
+ *
+ * @return list of decoders
+ *
+ * @throw IllegalArgumentException if an invalid parameter is passed
+ */
+ public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic);
+
+ /**
+ * gets all encoders associated with the group and artifact ids.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ *
+ * @throws IllegalArgumentException if invalid arguments have been provided
+ */
+ public List<CoderFilters> getEncoderFilters(String groupId, String artifactId);
+
+ /**
+ * get encoder based on coordinates and classname.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic protocol
+ * @param classname name of the class
+ * @return
+ *
+ * @throws IllegalArgumentException invalid arguments passed in
+ */
+ public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname);
+
+ /**
+ * is there a decoder supported for the controller id and topic.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic protocol
+ * @return true if supported
+ */
+ public boolean isDecodingSupported(String groupId, String artifactId, String topic);
+
+ /**
+ * Adds a Encoder class to encode the protocol over this topic.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic the topic
+ * @param eventClass the event class
+ * @param protocolFilter filters to selectively choose a particular decoder
+ * when there are multiples
+ *
+ * @throw IllegalArgumentException if an invalid parameter is passed
+ */
+ public void addEncoder(String groupId, String artifactId, String topic,
+ String eventClass,
+ JsonProtocolFilter protocolFilter,
+ CustomGsonCoder customGsonCoder,
+ CustomJacksonCoder customJacksonCoder,
+ int modelClassLoaderHash);
+
+ /**
+ * is there an encoder supported for the controller id and topic.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic protocol
+ * @return true if supported
+ */
+ public boolean isEncodingSupported(String groupId, String artifactId, String topic);
+
+ /**
+ * get encoder based on topic and encoded class.
+ *
+ * @param topic topic
+ * @param encodedClass encoded class
+ * @return list of filters
+ * @throws IllegalArgumentException invalid arguments passed in
+ */
+ public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass);
+
+ /**
+ * gets the identifier of the creator of the encoder.
+ *
+ * @param topic topic
+ * @param encodedClass encoded class
+ * @return a drools controller
+ * @throws IllegalArgumentException invalid arguments passed in
+ */
+ public DroolsController getDroolsController(String topic, Object encodedClass);
+
+ /**
+ * gets the identifier of the creator of the encoder.
+ *
+ * @param topic topic
+ * @param encodedClass encoded class
+ * @return list of drools controllers
+ * @throws IllegalArgumentException invalid arguments passed in
+ */
+ public List<DroolsController> getDroolsControllers(String topic, Object encodedClass);
+
+ /**
+ * decode topic's stringified event (json) to corresponding Event Object.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic protocol
+ * @param json event string
+ * @return object
+ * @throws IllegalArgumentException invalid arguments passed in
+ * @throws UnsupportedOperationException if the operation is not supported
+ * @throws IllegalStateException if the system is in an illegal state
+ */
+ public Object decode(String groupId, String artifactId, String topic, String json);
+
+ /**
+ * encodes topic's stringified event (json) to corresponding Event Object.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic protocol
+ * @param event Object
+ *
+ * @throws IllegalArgumentException invalid arguments passed in
+ */
+ public String encode(String groupId, String artifactId, String topic, Object event);
+
+ /**
+ * encodes topic's stringified event (json) to corresponding Event Object.
+ *
+ * @param topic topic
+ * @param event event object
+ *
+ * @throws IllegalArgumentException invalid arguments passed in
+ * @throws UnsupportedOperationException operation cannot be performed
+ */
+ public String encode(String topic, Object event);
+
+ /**
+ * encodes topic's stringified event (json) to corresponding Event Object.
+ *
+ * @param topic topic
+ * @param event event object
+ * @param droolsController
+ *
+ * @throws IllegalArgumentException invalid arguments passed in
+ * @throws UnsupportedOperationException operation cannot be performed
+ */
+ public String encode(String topic, Object event, DroolsController droolsController);
}
/**
@@ -383,247 +394,251 @@ public interface EventProtocolCoder {
* 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(String groupId, String artifactId, String topic,
- String eventClass,
- JsonProtocolFilter protocolFilter,
- CustomGsonCoder customGsonCoder,
- CustomJacksonCoder customJacksonCoder,
- int modelClassLoaderHash) {
- logger.info("{}: add-decoder {}:{}:{}:{}:{}:{}:{}:{}", this,
- groupId, artifactId, topic, eventClass,
- protocolFilter, customGsonCoder, customJacksonCoder,
- modelClassLoaderHash);
- this.decoders.add(groupId, artifactId, topic, eventClass, protocolFilter,
- customGsonCoder, customJacksonCoder, modelClassLoaderHash);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addEncoder(String groupId, String artifactId, String topic,
- String eventClass,
- JsonProtocolFilter protocolFilter,
- CustomGsonCoder customGsonCoder,
- CustomJacksonCoder customJacksonCoder,
- int modelClassLoaderHash) {
- logger.info("{}: add-decoder {}:{}:{}:{}:{}:{}:{}:{}", this,
- groupId, artifactId, topic, eventClass,
- protocolFilter, customGsonCoder, customJacksonCoder,
- modelClassLoaderHash);
- this.encoders.add(groupId, artifactId, topic, eventClass, protocolFilter,
- customGsonCoder, customJacksonCoder, modelClassLoaderHash);
- }
-
- /**
- * {@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 ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) {
- Pair<ProtocolCoderToolset,ProtocolCoderToolset> decoderToolsets = this.decoders.getCoders(groupId, artifactId, topic);
- if (decoderToolsets == null)
- throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId + ":" + topic);
-
- return decoderToolsets.first();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic) {
- return this.encoders.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 CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname) {
- return this.encoders.getFilters(groupId, artifactId, topic, classname);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass) {
- return this.encoders.getReverseFilters(topic, encodedClass);
- }
-
- /**
- * 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<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> decoderToolsets = this.decoders.getCoders(groupId, artifactId);
- if (decoderToolsets == null)
- throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId);
-
- List<ProtocolCoderToolset> parser1CoderToolset = new ArrayList<>();
- for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderToolsetPair : decoderToolsets) {
- parser1CoderToolset.add(coderToolsetPair.first());
- }
-
- return parser1CoderToolset;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List<CoderFilters> getDecoderFilters(String groupId, String artifactId) {
- return this.decoders.getFilters(groupId, artifactId);
-
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List<CoderFilters> getEncoderFilters(String groupId, String artifactId) {
- return this.encoders.getFilters(groupId, artifactId);
- }
-
- /**
- * {@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() {
- StringBuilder builder = new StringBuilder();
- builder.append("MultiplexorEventProtocolCoder [decoders=").append(decoders).append(", encoders=")
- .append(encoders).append("]");
- return builder.toString();
- }
+ /**
+ * 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(String groupId, String artifactId, String topic,
+ String eventClass,
+ JsonProtocolFilter protocolFilter,
+ CustomGsonCoder customGsonCoder,
+ CustomJacksonCoder customJacksonCoder,
+ int modelClassLoaderHash) {
+ logger.info("{}: add-decoder {}:{}:{}:{}:{}:{}:{}:{}", this,
+ groupId, artifactId, topic, eventClass,
+ protocolFilter, customGsonCoder, customJacksonCoder,
+ modelClassLoaderHash);
+ this.decoders.add(groupId, artifactId, topic, eventClass, protocolFilter,
+ customGsonCoder, customJacksonCoder, modelClassLoaderHash);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addEncoder(String groupId, String artifactId, String topic,
+ String eventClass,
+ JsonProtocolFilter protocolFilter,
+ CustomGsonCoder customGsonCoder,
+ CustomJacksonCoder customJacksonCoder,
+ int modelClassLoaderHash) {
+ logger.info("{}: add-decoder {}:{}:{}:{}:{}:{}:{}:{}", this,
+ groupId, artifactId, topic, eventClass,
+ protocolFilter, customGsonCoder, customJacksonCoder,
+ modelClassLoaderHash);
+ this.encoders.add(groupId, artifactId, topic, eventClass, protocolFilter,
+ customGsonCoder, customJacksonCoder, modelClassLoaderHash);
+ }
+
+ /**
+ * {@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) {
+ Pair<ProtocolCoderToolset,ProtocolCoderToolset> decoderToolsets =
+ this.decoders.getCoders(groupId, artifactId, topic);
+ if (decoderToolsets == null) {
+ throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId + ":" + topic);
+ }
+
+ return decoderToolsets.first();
+ }
+
+ /**
+ * 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<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> decoderToolsets =
+ this.decoders.getCoders(groupId, artifactId);
+ if (decoderToolsets == null) {
+ throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId);
+ }
+
+ List<ProtocolCoderToolset> parser1CoderToolset = new ArrayList<>();
+ for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderToolsetPair : decoderToolsets) {
+ parser1CoderToolset.add(coderToolsetPair.first());
+ }
+
+ return parser1CoderToolset;
+ }
+
+ /**
+ * {@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() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("MultiplexorEventProtocolCoder [decoders=").append(decoders).append(", encoders=")
+ .append(encoders).append("]");
+ return builder.toString();
+ }
}
/**
@@ -631,723 +646,758 @@ class MultiplexorEventProtocolCoder implements EventProtocolCoder {
* 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-pair>
- * where protocol-coder-toolset-pair contains both a jackson-protocol-coder-toolset
- * and a gson-protocol-coder-toolset. The first value of the pair will the
- * protocol coder toolset most likely to be successful with the encoding or decoding,
- * and consequently the second value will be the less likely.
- */
- protected final HashMap<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coders =
- new HashMap<>();
-
- /**
- * Mapping topic + classname -> Protocol Set
- */
- protected final HashMap<String, List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>> reverseCoders =
- new HashMap<>();
-
- protected boolean multipleToolsetRetries = false;
-
- GenericEventProtocolCoder(boolean multipleToolsetRetries) {
- this.multipleToolsetRetries = multipleToolsetRetries;
- }
-
- /**
- * Index a new coder
- *
- * @param groupId of the controller
- * @param artifactId of the controller
- * @param topic the topic
- * @param eventClass the event class
- * @param protocolFilter filters to selectively choose a particular decoder
- * when there are multiples
- *
- * @throw IllegalArgumentException if an invalid parameter is passed
- */
- public void add(String groupId, String artifactId,
- String topic,
- String eventClass,
- JsonProtocolFilter protocolFilter,
- CustomGsonCoder customGsonCoder,
- CustomJacksonCoder customJacksonCoder,
- int modelClassLoaderHash) {
- 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);
-
- if (eventClass == null) {
- throw new IllegalArgumentException("Invalid Event Class");
- }
-
- String key = this.codersKey(groupId, artifactId, topic);
- String reverseKey = this.reverseCodersKey(topic, eventClass);
-
- synchronized(this) {
- if (coders.containsKey(key)) {
- Pair<ProtocolCoderToolset, ProtocolCoderToolset> toolsets = coders.get(key);
-
- logger.info("{}: adding coders for existing {}: ", this, key, toolsets.first());
-
- toolsets.first().addCoder(eventClass, protocolFilter, modelClassLoaderHash);
- toolsets.second().addCoder(eventClass, protocolFilter, modelClassLoaderHash);
-
- if (!reverseCoders.containsKey(reverseKey)) {
- logger.info("{}: adding new reverse coders (multiple classes case) for {}:{}: {}",
- this, reverseKey, key, toolsets.first());
-
- List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> reverseMappings =
- new ArrayList<>();
- reverseMappings.add(toolsets);
- reverseCoders.put(reverseKey, reverseMappings);
- }
- return;
- }
-
- GsonProtocolCoderToolset gsonCoderTools =
- new GsonProtocolCoderToolset
- (topic, key,
- groupId, artifactId,
- eventClass, protocolFilter,
- customGsonCoder,
- modelClassLoaderHash);
-
- JacksonProtocolCoderToolset jacksonCoderTools =
- new JacksonProtocolCoderToolset
- (topic, key,
- groupId, artifactId,
- eventClass, protocolFilter,
- customJacksonCoder,
- modelClassLoaderHash);
-
- // Use Gson as the first priority encoding/decoding toolset, and Jackson
- // as second. This is because it has been observed that they can diverge
- // somewhat in the encoding/decoding data types, which can produce json
- // that may result incompatible with what some network elements are
- // expecting. As decoding takes place, this element will reconfigure
- // itself to set the jackson one as the favoured one first, if errors
- // are detected in the gson encoding
-
- Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools =
- new Pair<>(gsonCoderTools,
- jacksonCoderTools);
-
- logger.info("{}: adding coders for new {}: {}", this, key, coderTools.first());
-
- 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<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets =
- reverseCoders.get(reverseKey);
- boolean present = false;
- for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> parserSet: toolsets) {
- // just doublecheck
- present = parserSet.first().getControllerId().equals(key);
- if (present) {
- /* anomaly */
- logger.error("{}: unexpected toolset reverse mapping found for {}:{}: {}",
- this, reverseKey, key, parserSet.first());
- }
- }
-
- if (present) {
- return;
- } else {
- logger.info("{}: adding coder set for {}: {} ", this,
- reverseKey, coderTools.getFirst());
- toolsets.add(coderTools);
- }
- } else {
- List<Pair<ProtocolCoderToolset,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 group 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)) {
- Pair<ProtocolCoderToolset, ProtocolCoderToolset> p = coders.remove(key);
-
- logger.info("{}: removed toolset for {}: {}", this, key, p.getFirst());
-
- for (CoderFilters codeFilter : p.first().getCoders()) {
- String className = codeFilter.getCodedClass();
- String reverseKey = this.reverseCodersKey(topic, className);
- if (this.reverseCoders.containsKey(reverseKey) ) {
- List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsets =
- this.reverseCoders.get(reverseKey);
- Iterator<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsetsIter =
- toolsets.iterator();
- while (toolsetsIter.hasNext()) {
- Pair<ProtocolCoderToolset, ProtocolCoderToolset> toolset = toolsetsIter.next();
- if (toolset.first().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);
- Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
- try {
- Object event = coderTools.first().decode(json);
- if (event != null)
- return event;
- } catch (Exception e) {
- logger.debug("{}, cannot decode {}", this, json, e);
- }
-
- if (multipleToolsetRetries) {
- // try the less favored toolset
- try {
- Object event = coderTools.second().decode(json);
- if (event != null) {
- // change the priority of the toolset
- synchronized(this) {
- ProtocolCoderToolset first = coderTools.first();
- ProtocolCoderToolset second = coderTools.second();
- coderTools.first(second);
- coderTools.second(first);
- }
-
- return event;
- }
- } catch (Exception e) {
- throw new UnsupportedOperationException(e);
- }
- }
-
- throw new UnsupportedOperationException("Cannot decode neither with gson or jackson");
- }
-
- /**
- * 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 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);
-
- Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
- try {
- String json = coderTools.first().encode(event);
- if (json != null && !json.isEmpty())
- return json;
- } catch (Exception e) {
- logger.warn("{}: cannot encode (first) for {}: {}", this, key, event, e);
- }
-
- if (multipleToolsetRetries) {
- // try the less favored toolset
- try {
- String json = coderTools.second().encode(event);
- if (json != null) {
- // change the priority of the toolset
- synchronized(this) {
- ProtocolCoderToolset first = coderTools.first();
- ProtocolCoderToolset second = coderTools.second();
- coderTools.first(second);
- coderTools.second(first);
- }
-
- return json;
- }
- } catch (Exception e) {
- logger.error("{}: cannot encode (second) for {}: {}", this, key, event, e);
- throw new UnsupportedOperationException(e);
- }
- }
-
- throw new UnsupportedOperationException("Cannot decode neither with gson or jackson");
- }
-
- /**
- * 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");
-
+ 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-pair/>
+ * where protocol-coder-toolset-pair contains both a jackson-protocol-coder-toolset
+ * and a gson-protocol-coder-toolset. The first value of the pair will the
+ * protocol coder toolset most likely to be successful with the encoding or decoding,
+ * and consequently the second value will be the less likely.
+ */
+ protected final HashMap<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coders =
+ new HashMap<>();
+
+ /**
+ * Mapping topic + classname -> Protocol Set.
+ */
+ protected final HashMap<String, List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>> reverseCoders =
+ new HashMap<>();
+
+ protected boolean multipleToolsetRetries = false;
+
+ GenericEventProtocolCoder(boolean multipleToolsetRetries) {
+ this.multipleToolsetRetries = multipleToolsetRetries;
+ }
+
+ /**
+ * Index a new coder.
+ *
+ * @param groupId of the controller
+ * @param artifactId of the controller
+ * @param topic the topic
+ * @param eventClass the event class
+ * @param protocolFilter filters to selectively choose a particular decoder
+ * when there are multiples
+ *
+ * @throw IllegalArgumentException if an invalid parameter is passed
+ */
+ public void add(String groupId, String artifactId,
+ String topic,
+ String eventClass,
+ JsonProtocolFilter protocolFilter,
+ CustomGsonCoder customGsonCoder,
+ CustomJacksonCoder customJacksonCoder,
+ int modelClassLoaderHash) {
+ 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);
+ }
+
+ if (eventClass == null) {
+ throw new IllegalArgumentException("Invalid Event Class");
+ }
+
+ String key = this.codersKey(groupId, artifactId, topic);
+ String reverseKey = this.reverseCodersKey(topic, eventClass);
+
+ synchronized (this) {
+ if (coders.containsKey(key)) {
+ Pair<ProtocolCoderToolset, ProtocolCoderToolset> toolsets = coders.get(key);
+
+ logger.info("{}: adding coders for existing {}: ", this, key, toolsets.first());
+
+ toolsets.first().addCoder(eventClass, protocolFilter, modelClassLoaderHash);
+ toolsets.second().addCoder(eventClass, protocolFilter, modelClassLoaderHash);
+
+ if (!reverseCoders.containsKey(reverseKey)) {
+ logger.info("{}: adding new reverse coders (multiple classes case) for {}:{}: {}",
+ this, reverseKey, key, toolsets.first());
+
+ List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> reverseMappings =
+ new ArrayList<>();
+ reverseMappings.add(toolsets);
+ reverseCoders.put(reverseKey, reverseMappings);
+ }
+ return;
+ }
+
+ GsonProtocolCoderToolset gsonCoderTools =
+ new GsonProtocolCoderToolset(topic, key,
+ groupId, artifactId,
+ eventClass, protocolFilter,
+ customGsonCoder,
+ modelClassLoaderHash);
+
+ JacksonProtocolCoderToolset jacksonCoderTools =
+ new JacksonProtocolCoderToolset(topic, key,
+ groupId, artifactId,
+ eventClass, protocolFilter,
+ customJacksonCoder,
+ modelClassLoaderHash);
+
+ // Use Gson as the first priority encoding/decoding toolset, and Jackson
+ // as second. This is because it has been observed that they can diverge
+ // somewhat in the encoding/decoding data types, which can produce json
+ // that may result incompatible with what some network elements are
+ // expecting. As decoding takes place, this element will reconfigure
+ // itself to set the jackson one as the favoured one first, if errors
+ // are detected in the gson encoding
+
+ Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools =
+ new Pair<>(gsonCoderTools,
+ jacksonCoderTools);
+
+ logger.info("{}: adding coders for new {}: {}", this, key, coderTools.first());
+
+ 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<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets =
+ reverseCoders.get(reverseKey);
+ boolean present = false;
+ for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> parserSet: toolsets) {
+ // just doublecheck
+ present = parserSet.first().getControllerId().equals(key);
+ if (present) {
+ /* anomaly */
+ logger.error("{}: unexpected toolset reverse mapping found for {}:{}: {}",
+ this, reverseKey, key, parserSet.first());
+ }
+ }
+
+ if (present) {
+ return;
+ } else {
+ logger.info("{}: adding coder set for {}: {} ", this,
+ reverseKey, coderTools.getFirst());
+ toolsets.add(coderTools);
+ }
+ } else {
+ List<Pair<ProtocolCoderToolset,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 group 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)) {
+ Pair<ProtocolCoderToolset, ProtocolCoderToolset> pair = coders.remove(key);
+
+ logger.info("{}: removed toolset for {}: {}", this, key, pair.getFirst());
+
+ for (CoderFilters codeFilter : pair.first().getCoders()) {
+ String className = codeFilter.getCodedClass();
+ String reverseKey = this.reverseCodersKey(topic, className);
+ if (this.reverseCoders.containsKey(reverseKey) ) {
+ List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsets =
+ this.reverseCoders.get(reverseKey);
+ Iterator<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsetsIter =
+ toolsets.iterator();
+ while (toolsetsIter.hasNext()) {
+ Pair<ProtocolCoderToolset, ProtocolCoderToolset> toolset = toolsetsIter.next();
+ if (toolset.first().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);
+ Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
+ try {
+ Object event = coderTools.first().decode(json);
+ if (event != null) {
+ return event;
+ }
+ } catch (Exception e) {
+ logger.debug("{}, cannot decode {}", this, json, e);
+ }
+
+ if (multipleToolsetRetries) {
+ // try the less favored toolset
+ try {
+ Object event = coderTools.second().decode(json);
+ if (event != null) {
+ // change the priority of the toolset
+ synchronized (this) {
+ ProtocolCoderToolset first = coderTools.first();
+ ProtocolCoderToolset second = coderTools.second();
+ coderTools.first(second);
+ coderTools.second(first);
+ }
+
+ return event;
+ }
+ } catch (Exception e) {
+ throw new UnsupportedOperationException(e);
+ }
+ }
+
+ throw new UnsupportedOperationException("Cannot decode neither with gson or jackson");
+ }
+
+ /**
+ * 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().getCanonicalName());
- if (!this.reverseCoders.containsKey(reverseKey))
+ if (!this.reverseCoders.containsKey(reverseKey)) {
throw new IllegalArgumentException("no reverse coder has been found");
-
- List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>>
- toolsets = this.reverseCoders.get(reverseKey);
-
+ }
+
+ List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsets = this.reverseCoders.get(reverseKey);
+
String key = codersKey(toolsets.get(0).first().getGroupId(), toolsets.get(0).first().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);
- }
-
- /**
- * @param topic
- * @param encodedClass
- * @param reverseKey
- * @return
- * @throws IllegalStateException
- * @throws IllegalArgumentException
- */
- protected List<DroolsController> droolsCreators(String topic, Object encodedClass) {
-
- List<DroolsController> droolsControllers = new ArrayList<>();
-
- String reverseKey = this.reverseCodersKey(topic, encodedClass.getClass().getCanonicalName());
- if (!this.reverseCoders.containsKey(reverseKey)) {
- logger.warn("{}: no reverse mapping for {}", this, reverseKey);
- return droolsControllers;
- }
-
- List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>>
- toolsets = this.reverseCoders.get(reverseKey);
-
- // There must be multiple toolset pairs 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().getCanonicalName());
-
- for (Pair<ProtocolCoderToolset, ProtocolCoderToolset> encoderSet : toolsets) {
- // figure out the right toolset
- String groupId = encoderSet.first().getGroupId();
- String artifactId = encoderSet.first().getArtifactId();
- List<CoderFilters> coderFilters = encoderSet.first().getCoders();
- for (CoderFilters coder : coderFilters) {
- if (coder.getCodedClass().equals(encodedClass.getClass().getCanonicalName())) {
- 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().getCanonicalName());
-
- 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);
- Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
- return coderTools.first().getCoders();
- }
-
- /**
- * 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 Pair<ProtocolCoderToolset,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<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, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> entry : coders.entrySet()) {
- if (entry.getKey().startsWith(key)) {
- codersFilters.addAll(entry.getValue().first().getCoders());
- }
- }
-
- return codersFilters;
- }
-
- /**
- * 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<Pair<ProtocolCoderToolset,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<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coderToolset = new ArrayList<>();
- for (Map.Entry<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> entry : coders.entrySet()) {
- if (entry.getKey().startsWith(key)) {
- coderToolset.add(entry.getValue());
- }
- }
-
- return coderToolset;
- }
-
-
- /**
- * get all filters by maven coordinates, topic, and classname
- *
- * @param groupId group id
- * @param artifactId artifact id
- * @param topic topic
- * @param 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);
- Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
- return coderTools.first().getCoder(classname);
- }
-
- /**
- * get coded based on class and topic
- *
- * @param topic
- * @param codedClass
- * @return
- * @throws IllegalArgumentException
- */
- 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<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets = this.reverseCoders.get(key);
- if (toolsets == null)
- throw new IllegalArgumentException("No Coder found for " + key);
-
-
- List<CoderFilters> coderFilters = new ArrayList<>();
- for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> toolset: toolsets) {
- coderFilters.addAll(toolset.first().getCoders());
- }
-
- return coderFilters;
- }
-
- /**
- * returns group and artifact id of the creator of the encoder
- *
- * @param topic
- * @param fact
- * @return
- * @throws IllegalArgumentException
- */
- 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().getCanonicalName());
- // continue
- }
- return droolsControllers.get(0);
- }
-
- /**
- * returns group and artifact id of the creator of the encoder
- *
- * @param topic
- * @param fact
- * @return
- * @throws IllegalArgumentException
- */
- 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().getCanonicalName());
- // continue
- }
- return droolsControllers;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("GenericEventProtocolCoder [coders=").append(coders.keySet()).append(", reverseCoders=")
- .append(reverseCoders.keySet()).append("]");
- return builder.toString();
- }
+ }
+
+ /**
+ * 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);
+
+ Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
+ try {
+ String json = coderTools.first().encode(event);
+ if (json != null && !json.isEmpty()) {
+ return json;
+ }
+ } catch (Exception e) {
+ logger.warn("{}: cannot encode (first) for {}: {}", this, key, event, e);
+ }
+
+ if (multipleToolsetRetries) {
+ // try the less favored toolset
+ try {
+ String json = coderTools.second().encode(event);
+ if (json != null) {
+ // change the priority of the toolset
+ synchronized (this) {
+ ProtocolCoderToolset first = coderTools.first();
+ ProtocolCoderToolset second = coderTools.second();
+ coderTools.first(second);
+ coderTools.second(first);
+ }
+
+ return json;
+ }
+ } catch (Exception e) {
+ logger.error("{}: cannot encode (second) for {}: {}", this, key, event, e);
+ throw new UnsupportedOperationException(e);
+ }
+ }
+
+ throw new UnsupportedOperationException("Cannot decode neither with gson or jackson");
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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().getCanonicalName());
+ if (!this.reverseCoders.containsKey(reverseKey)) {
+ logger.warn("{}: no reverse mapping for {}", this, reverseKey);
+ return droolsControllers;
+ }
+
+ List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsets = this.reverseCoders.get(reverseKey);
+
+ // There must be multiple toolset pairs 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().getCanonicalName());
+ }
+
+ for (Pair<ProtocolCoderToolset, ProtocolCoderToolset> encoderSet : toolsets) {
+ // figure out the right toolset
+ String groupId = encoderSet.first().getGroupId();
+ String artifactId = encoderSet.first().getArtifactId();
+ List<CoderFilters> coderFilters = encoderSet.first().getCoders();
+ for (CoderFilters coder : coderFilters) {
+ if (coder.getCodedClass().equals(encodedClass.getClass().getCanonicalName())) {
+ 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().getCanonicalName());
+ }
+
+ 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);
+ Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
+ return coderTools.first().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, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> entry : coders.entrySet()) {
+ if (entry.getKey().startsWith(key)) {
+ codersFilters.addAll(entry.getValue().first().getCoders());
+ }
+ }
+
+ return codersFilters;
+ }
+
+ /**
+ * 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 Pair<ProtocolCoderToolset,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<Pair<ProtocolCoderToolset,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<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coderToolset = new ArrayList<>();
+ for (Map.Entry<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> entry : coders.entrySet()) {
+ if (entry.getKey().startsWith(key)) {
+ coderToolset.add(entry.getValue());
+ }
+ }
+
+ return coderToolset;
+ }
+
+ /**
+ * 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);
+ Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
+ return coderTools.first().getCoder(classname);
+ }
+
+ /**
+ * 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<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets = this.reverseCoders.get(key);
+ if (toolsets == null) {
+ throw new IllegalArgumentException("No Coder found for " + key);
+ }
+
+ List<CoderFilters> coderFilters = new ArrayList<>();
+ for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> toolset: toolsets) {
+ coderFilters.addAll(toolset.first().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().getCanonicalName());
+ // continue
+ }
+ return droolsControllers.get(0);
+ }
+
+ /**
+ * returns group and artifact id of the creator of the encoder.
+ *
+ * @param topic topic
+ * @param fact fact
+ * @return
+ */
+ 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().getCanonicalName());
+ // continue
+ }
+ return droolsControllers;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("GenericEventProtocolCoder [coders=").append(coders.keySet()).append(", reverseCoders=")
+ .append(reverseCoders.keySet()).append("]");
+ return builder.toString();
+ }
}
class EventProtocolDecoder extends GenericEventProtocolCoder {
- public EventProtocolDecoder(){super(false);}
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("EventProtocolDecoder [toString()=").append(super.toString()).append("]");
- return builder.toString();
- }
-
+ public EventProtocolDecoder() {
+ super(false);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("EventProtocolDecoder [toString()=").append(super.toString()).append("]");
+ return builder.toString();
+ }
+
}
-
+
class EventProtocolEncoder extends GenericEventProtocolCoder {
-
- public EventProtocolEncoder(){super(false);}
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("EventProtocolEncoder [toString()=").append(super.toString()).append("]");
- return builder.toString();
- }
+
+ public EventProtocolEncoder() {
+ super(false);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("EventProtocolEncoder [toString()=").append(super.toString()).append("]");
+ return builder.toString();
+ }
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java
index a5902d66..4fd2f522 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java
@@ -20,339 +20,378 @@
package org.onap.policy.drools.protocol.coders;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
import java.util.ArrayList;
import java.util.List;
-
import java.util.concurrent.CopyOnWriteArrayList;
import org.onap.policy.drools.utils.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-
/**
* JSON Protocol Filter.
*/
public class JsonProtocolFilter {
-
- private static final String MISSING_RULE_NAME = "no rule name provided";
- /**
- * Logger
- */
- private static final Logger logger = LoggerFactory.getLogger(JsonProtocolFilter.class);
-
- /**
- * Helper class to collect Filter information
- */
- public static class FilterRule {
- /**
- * Field name
- */
- private String name;
-
- /**
- * Field Value regex
- */
- private String regex;
-
- /**
- * Filter Constructor
- *
- * @param name field name
- * @param regex field regex value
- */
- public FilterRule(String name, String regex) {
- this.setName(name);
- this.setRegex(regex);
- }
-
- /**
- * Default constructor (for serialization only)
- */
- public FilterRule() {
- super();
- }
-
- /**
- * gets name
- *
- * @return
- */
- public String getName() {
- return name;
- }
-
- /**
- * gets regex
- *
- * @return
- */
- public String getRegex() {
- return regex;
- }
-
- /**
- * sets field name
- * @param name field name
- */
- public void setName(String name) {
- if (name == null || name.isEmpty())
- throw new IllegalArgumentException("filter field name must be provided");
-
- this.name = name;
- }
-
- /**
- * sets regex name
- * @param regex
- */
- public void setRegex(String regex) {
- if (regex == null || regex.isEmpty())
- this.regex = ".*";
-
- this.regex = regex;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("Filter [name=").append(name).append(", regex=").append(regex).append("]");
- return builder.toString();
- }
- }
-
- /**
- * all the filters to be applied
- */
- protected List<FilterRule> rules = new CopyOnWriteArrayList<>();
-
- /**
- * Create a Protocol Filter
- *
- * @throws IllegalArgumentException an invalid input has been provided
- */
- public JsonProtocolFilter() {}
-
- /**
- *
- * @param filters filter list
- *
- * @throws IllegalArgumentException an invalid input has been provided
- */
- public JsonProtocolFilter(List<FilterRule> filters) {
- List<FilterRule> temp = new ArrayList<>();
- for (FilterRule rule : filters) {
- if (rule.getName() == null || rule.getName().isEmpty()) {
- continue;
- }
-
- if (rule.getRegex() == null || rule.getRegex().isEmpty()) {
- rule.setRegex(".*");
- }
-
- temp.add(rule);
- }
-
- this.rules.addAll(temp);
- }
-
- /**
- *
- * @param rawFilters raw filter initialization
- *
- * @throws IllegalArgumentException an invalid input has been provided
- */
- public static JsonProtocolFilter fromRawFilters(List<Pair<String, String>> rawFilters) {
-
- if (rawFilters == null) {
- throw new IllegalArgumentException("No raw filters provided");
- }
-
- List<FilterRule> filters = new ArrayList<>();
- for (Pair<String, String> filterPair: rawFilters) {
- if (filterPair.first() == null || filterPair.first().isEmpty()) {
- continue;
- }
-
- filters.add(new FilterRule(filterPair.first(), filterPair.second()));
- }
- return new JsonProtocolFilter(filters);
- }
-
- /**
- * are there any filters?
- *
- * @return true if there are filters, false otherwise
- */
- public boolean isRules() {
- return !this.rules.isEmpty();
- }
-
- /**
- * accept a JSON string as conformant it if passes all filters
- *
- * @param json json is a JSON object
- * @return true if json string is conformant
- *
- * @throws IllegalArgumentException an invalid input has been provided
- */
- public boolean accept(JsonElement json) {
- if (json == null) {
- throw new IllegalArgumentException("no JSON provided");
- }
-
- if (!json.isJsonObject()) {
- return false;
- }
-
- if (rules.isEmpty()) {
- return true;
- }
-
- try {
- JsonObject event = json.getAsJsonObject();
- for (FilterRule filter: rules) {
- if (filter.getRegex() == null ||
- filter.getRegex().isEmpty() ||
- ".*".equals(filter.getRegex())) {
-
- // Only check for presence
- if (!event.has(filter.getName())) {
- return false;
- }
- } else {
- JsonElement field = event.get(filter.getName());
- if (field == null) {
- return false;
- }
-
- String fieldValue = field.getAsString();
- if (!fieldValue.matches(filter.getRegex())) {
- return false;
- }
- }
- }
- return true;
- } catch (Exception e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * accept a JSON string as conformant it if passes all filters
- *
- * @param json json string
- * @return true if json string is conformant
- *
- * @throws IllegalArgumentException an invalid input has been provided
- */
- public boolean accept(String json) {
- if (json == null || json.isEmpty()) {
- throw new IllegalArgumentException("no JSON provided");
- }
-
- if (rules.isEmpty()) {
- return true;
- }
-
- try {
- JsonElement element = new JsonParser().parse(json);
- if (element == null || !element.isJsonObject()) {
- return false;
- }
-
- return this.accept(element.getAsJsonObject());
- } catch (IllegalArgumentException ile) {
- throw ile;
- } catch (Exception e) {
- logger.info("{}: cannot accept {} because of {}",
- this, json, e.getMessage(), e);
- throw new IllegalArgumentException(e);
- }
- }
-
- public List<FilterRule> getRules() {
- return new ArrayList<>(this.rules);
- }
-
- public List<FilterRule> getRules(String name) {
- if (name == null || name.isEmpty())
- throw new IllegalArgumentException(MISSING_RULE_NAME);
-
- ArrayList<FilterRule> temp = new ArrayList<>();
- for (FilterRule rule : this.rules) {
- if (rule.getName().equals(name)) {
- temp.add(rule);
- }
- }
- return temp;
- }
-
- public void setRules(List<FilterRule> rulesFilters) {
- if (rulesFilters == null)
- throw new IllegalArgumentException("no rules provided");
-
- this.rules.clear();
- this.rules.addAll(rulesFilters);
- }
-
- public void deleteRules(String name) {
- if (name == null || name.isEmpty())
- throw new IllegalArgumentException(MISSING_RULE_NAME);
-
- List<FilterRule> temp = new ArrayList<>();
- for (FilterRule rule : this.rules) {
- if (rule.name.equals(name)) {
- temp.add(rule);
- }
- }
- this.rules.removeAll(temp);
- }
-
- public void deleteRule(String name, String regex) {
- if (name == null || name.isEmpty())
- throw new IllegalArgumentException(MISSING_RULE_NAME);
-
- String nonNullRegex = regex;
- if (regex == null || regex.isEmpty()) {
- nonNullRegex = ".*";
- }
-
- List<FilterRule> temp = new ArrayList<>();
- for (FilterRule rule : this.rules) {
- if (rule.name.equals(name) && rule.getRegex().equals(nonNullRegex)) {
- temp.add(rule);
- }
- }
-
- this.rules.removeAll(temp);
- }
-
- public void addRule(String name, String regex) {
- if (name == null || name.isEmpty())
- throw new IllegalArgumentException(MISSING_RULE_NAME);
-
- String nonNullRegex = regex;
- if (regex == null || regex.isEmpty()) {
- nonNullRegex = ".*";
- }
-
- for (FilterRule rule : this.rules) {
- if (rule.getName().equals(name) && rule.getRegex().equals(regex)) {
- return;
- }
- }
-
- this.rules.add(new FilterRule(name, nonNullRegex));
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("JsonProtocolFilter [rules=").append(rules).append("]");
- return builder.toString();
- }
+
+ private static final String MISSING_RULE_NAME = "no rule name provided";
+ /**
+ * Logger.
+ */
+ private static final Logger logger = LoggerFactory.getLogger(JsonProtocolFilter.class);
+
+ /**
+ * Helper class to collect Filter information.
+ */
+ public static class FilterRule {
+ /**
+ * Field name.
+ */
+ private String name;
+
+ /**
+ * Field Value regex.
+ */
+ private String regex;
+
+ /**
+ * Filter Constructor.
+ *
+ * @param name field name
+ * @param regex field regex value
+ */
+ public FilterRule(String name, String regex) {
+ this.setName(name);
+ this.setRegex(regex);
+ }
+
+ /**
+ * Default constructor (for serialization only).
+ */
+ public FilterRule() {
+ super();
+ }
+
+ /**
+ * gets name.
+ *
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * gets regex.
+ *
+ * @return regular expression string
+ */
+ public String getRegex() {
+ return regex;
+ }
+
+ /**
+ * Sets field name.
+ *
+ * @param name field name
+ */
+ public void setName(String name) {
+ if (name == null || name.isEmpty()) {
+ throw new IllegalArgumentException("filter field name must be provided");
+ }
+
+ this.name = name;
+ }
+
+ /**
+ * sets regex name.
+ *
+ * @param regex expression
+ */
+ public void setRegex(String regex) {
+ if (regex == null || regex.isEmpty()) {
+ this.regex = ".*";
+ }
+
+ this.regex = regex;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Filter [name=").append(name).append(", regex=").append(regex).append("]");
+ return builder.toString();
+ }
+ }
+
+ /**
+ * all the filters to be applied.
+ */
+ protected List<FilterRule> rules = new CopyOnWriteArrayList<>();
+
+ /**
+ * Create a Protocol Filter.
+ *
+ * @throws IllegalArgumentException an invalid input has been provided
+ */
+ public JsonProtocolFilter() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param filters filter list
+ *
+ * @throws IllegalArgumentException an invalid input has been provided
+ */
+ public JsonProtocolFilter(List<FilterRule> filters) {
+ List<FilterRule> temp = new ArrayList<>();
+ for (FilterRule rule : filters) {
+ if (rule.getName() == null || rule.getName().isEmpty()) {
+ continue;
+ }
+
+ if (rule.getRegex() == null || rule.getRegex().isEmpty()) {
+ rule.setRegex(".*");
+ }
+
+ temp.add(rule);
+ }
+
+ this.rules.addAll(temp);
+ }
+
+ /**
+ * From raw filters.
+ *
+ * @param rawFilters raw filter initialization
+ *
+ * @throws IllegalArgumentException an invalid input has been provided
+ */
+ public static JsonProtocolFilter fromRawFilters(List<Pair<String, String>> rawFilters) {
+
+ if (rawFilters == null) {
+ throw new IllegalArgumentException("No raw filters provided");
+ }
+
+ List<FilterRule> filters = new ArrayList<>();
+ for (Pair<String, String> filterPair: rawFilters) {
+ if (filterPair.first() == null || filterPair.first().isEmpty()) {
+ continue;
+ }
+
+ filters.add(new FilterRule(filterPair.first(), filterPair.second()));
+ }
+ return new JsonProtocolFilter(filters);
+ }
+
+ /**
+ * are there any filters.
+ *
+ * @return true if there are filters, false otherwise
+ */
+ public boolean isRules() {
+ return !this.rules.isEmpty();
+ }
+
+ /**
+ * accept a JSON string as conformant it if passes all filters.
+ *
+ * @param json json is a JSON object
+ * @return true if json string is conformant
+ *
+ * @throws IllegalArgumentException an invalid input has been provided
+ */
+ public boolean accept(JsonElement json) {
+ if (json == null) {
+ throw new IllegalArgumentException("no JSON provided");
+ }
+
+ if (!json.isJsonObject()) {
+ return false;
+ }
+
+ if (rules.isEmpty()) {
+ return true;
+ }
+
+ try {
+ JsonObject event = json.getAsJsonObject();
+ for (FilterRule filter: rules) {
+ if (filter.getRegex() == null
+ || filter.getRegex().isEmpty()
+ || ".*".equals(filter.getRegex())) {
+
+ // Only check for presence
+ if (!event.has(filter.getName())) {
+ return false;
+ }
+ } else {
+ JsonElement field = event.get(filter.getName());
+ if (field == null) {
+ return false;
+ }
+
+ String fieldValue = field.getAsString();
+ if (!fieldValue.matches(filter.getRegex())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Accept a JSON string as conformant it if passes all filters.
+ *
+ * @param json json string
+ * @return true if json string is conformant
+ *
+ * @throws IllegalArgumentException an invalid input has been provided
+ */
+ public boolean accept(String json) {
+ if (json == null || json.isEmpty()) {
+ throw new IllegalArgumentException("no JSON provided");
+ }
+
+ if (rules.isEmpty()) {
+ return true;
+ }
+
+ try {
+ JsonElement element = new JsonParser().parse(json);
+ if (element == null || !element.isJsonObject()) {
+ return false;
+ }
+
+ return this.accept(element.getAsJsonObject());
+ } catch (IllegalArgumentException ile) {
+ throw ile;
+ } catch (Exception e) {
+ logger.info("{}: cannot accept {} because of {}",
+ this, json, e.getMessage(), e);
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public List<FilterRule> getRules() {
+ return new ArrayList<>(this.rules);
+ }
+
+ /**
+ * Get rules.
+ *
+ * @param name name
+ * @return
+ */
+ public List<FilterRule> getRules(String name) {
+ if (name == null || name.isEmpty()) {
+ throw new IllegalArgumentException(MISSING_RULE_NAME);
+ }
+
+ ArrayList<FilterRule> temp = new ArrayList<>();
+ for (FilterRule rule : this.rules) {
+ if (rule.getName().equals(name)) {
+ temp.add(rule);
+ }
+ }
+ return temp;
+ }
+
+ /**
+ * Set Rules.
+ *
+ * @param rulesFilters filters
+ */
+ public void setRules(List<FilterRule> rulesFilters) {
+ if (rulesFilters == null) {
+ throw new IllegalArgumentException("no rules provided");
+ }
+
+ this.rules.clear();
+ this.rules.addAll(rulesFilters);
+ }
+
+ /**
+ * Delete rules.
+ *
+ * @param name name
+ */
+ public void deleteRules(String name) {
+ if (name == null || name.isEmpty()) {
+ throw new IllegalArgumentException(MISSING_RULE_NAME);
+ }
+
+ List<FilterRule> temp = new ArrayList<>();
+ for (FilterRule rule : this.rules) {
+ if (rule.name.equals(name)) {
+ temp.add(rule);
+ }
+ }
+ this.rules.removeAll(temp);
+ }
+
+ /**
+ * Delete rule.
+ *
+ * @param name name
+ * @param regex regex
+ */
+ public void deleteRule(String name, String regex) {
+ if (name == null || name.isEmpty()) {
+ throw new IllegalArgumentException(MISSING_RULE_NAME);
+ }
+
+ String nonNullRegex = regex;
+ if (regex == null || regex.isEmpty()) {
+ nonNullRegex = ".*";
+ }
+
+ List<FilterRule> temp = new ArrayList<>();
+ for (FilterRule rule : this.rules) {
+ if (rule.name.equals(name) && rule.getRegex().equals(nonNullRegex)) {
+ temp.add(rule);
+ }
+ }
+
+ this.rules.removeAll(temp);
+ }
+
+ /**
+ * Add rule.
+ *
+ * @param name name
+ * @param regex regex
+ */
+ public void addRule(String name, String regex) {
+ if (name == null || name.isEmpty()) {
+ throw new IllegalArgumentException(MISSING_RULE_NAME);
+ }
+
+ String nonNullRegex = regex;
+ if (regex == null || regex.isEmpty()) {
+ nonNullRegex = ".*";
+ }
+
+ for (FilterRule rule : this.rules) {
+ if (rule.getName().equals(name) && rule.getRegex().equals(regex)) {
+ return;
+ }
+ }
+
+ this.rules.add(new FilterRule(name, nonNullRegex));
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("JsonProtocolFilter [rules=").append(rules).append("]");
+ return builder.toString();
+ }
}