diff options
author | Pamela Dragosh <pdragosh@research.att.com> | 2018-09-13 19:35:18 -0400 |
---|---|---|
committer | Pamela Dragosh <pdragosh@research.att.com> | 2018-09-13 20:00:37 -0400 |
commit | c733c08b7201ffdee81c7dab2ed50a1ce8fd5bbb (patch) | |
tree | f2a55827d08f47d86ba1a838a1cd5e129731935e /policy-management/src/main/java/org/onap/policy/drools/controller | |
parent | 69c83ef510fe7e1efda5dd75e7beaa862250ef05 (diff) |
Fix checkstyle in policy-management
The submodule policy-management checkstyle fixes. There may be
one or two sonar fixes in there.
Issue-ID: POLICY-882
Change-Id: I9cb43c573c6811dd058943650ba1ea5f6dc880aa
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
Diffstat (limited to 'policy-management/src/main/java/org/onap/policy/drools/controller')
4 files changed, 1119 insertions, 1066 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"; + } } |