From 6abeb297254942c48722c2da0e7c355d523fe307 Mon Sep 17 00:00:00 2001 From: Guo Ruijing Date: Fri, 28 Jul 2017 08:23:01 +0000 Subject: [POLICY-72] replace openecomp for drools-pdp Change-Id: I8aa8e32d3ba10f7c655b50e97aaf6865514d4777 Signed-off-by: Guo Ruijing --- .../policy/drools/controller/DroolsController.java | 218 ++ .../drools/controller/DroolsControllerFactory.java | 555 +++++ .../controller/internal/MavenDroolsController.java | 910 ++++++++ .../controller/internal/NullDroolsController.java | 262 +++ .../features/PolicyControllerFeatureAPI.java | 222 ++ .../drools/features/PolicyEngineFeatureAPI.java | 202 ++ .../drools/persistence/SystemPersistence.java | 248 +++ .../drools/protocol/coders/EventProtocolCoder.java | 1393 ++++++++++++ .../drools/protocol/coders/JsonProtocolFilter.java | 308 +++ .../protocol/coders/ProtocolCoderToolset.java | 683 ++++++ .../coders/TopicCoderFilterConfiguration.java | 309 +++ .../configuration/ControllerConfiguration.java | 280 +++ .../configuration/DroolsConfiguration.java | 278 +++ .../protocol/configuration/PdpdConfiguration.java | 283 +++ .../policy/drools/server/restful/RestManager.java | 2335 ++++++++++++++++++++ .../java/org/onap/policy/drools/system/Main.java | 135 ++ .../policy/drools/system/PolicyController.java | 110 + .../drools/system/PolicyControllerFactory.java | 522 +++++ .../onap/policy/drools/system/PolicyEngine.java | 1461 ++++++++++++ .../internal/AggregatedPolicyController.java | 626 ++++++ .../policy/drools/controller/DroolsController.java | 218 -- .../drools/controller/DroolsControllerFactory.java | 555 ----- .../controller/internal/MavenDroolsController.java | 910 -------- .../controller/internal/NullDroolsController.java | 262 --- .../features/PolicyControllerFeatureAPI.java | 222 -- .../drools/features/PolicyEngineFeatureAPI.java | 202 -- .../drools/persistence/SystemPersistence.java | 248 --- .../drools/protocol/coders/EventProtocolCoder.java | 1393 ------------ .../drools/protocol/coders/JsonProtocolFilter.java | 308 --- .../protocol/coders/ProtocolCoderToolset.java | 683 ------ .../coders/TopicCoderFilterConfiguration.java | 309 --- .../configuration/ControllerConfiguration.java | 280 --- .../configuration/DroolsConfiguration.java | 278 --- .../protocol/configuration/PdpdConfiguration.java | 283 --- .../policy/drools/server/restful/RestManager.java | 2335 -------------------- .../org/openecomp/policy/drools/system/Main.java | 135 -- .../policy/drools/system/PolicyController.java | 110 - .../drools/system/PolicyControllerFactory.java | 522 ----- .../policy/drools/system/PolicyEngine.java | 1461 ------------ .../internal/AggregatedPolicyController.java | 626 ------ 40 files changed, 11340 insertions(+), 11340 deletions(-) create mode 100644 policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureAPI.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/features/PolicyEngineFeatureAPI.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/persistence/SystemPersistence.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/ControllerConfiguration.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/DroolsConfiguration.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/system/Main.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/system/PolicyController.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/system/PolicyControllerFactory.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngine.java create mode 100644 policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsControllerFactory.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/NullDroolsController.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/features/PolicyControllerFeatureAPI.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/features/PolicyEngineFeatureAPI.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/persistence/SystemPersistence.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/JsonProtocolFilter.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/ProtocolCoderToolset.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/ControllerConfiguration.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/DroolsConfiguration.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/PdpdConfiguration.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/system/Main.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyController.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyControllerFactory.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java delete mode 100644 policy-management/src/main/java/org/openecomp/policy/drools/system/internal/AggregatedPolicyController.java (limited to 'policy-management/src/main/java/org') 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 new file mode 100644 index 00000000..c4c61a8a --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java @@ -0,0 +1,218 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.controller; + +import java.util.List; +import java.util.Map; + +import org.onap.policy.drools.core.PolicyContainer; +import org.onap.policy.drools.event.comm.TopicSink; +import org.onap.policy.drools.properties.Lockable; +import org.onap.policy.drools.properties.Startable; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; + +/** + * Drools Controller is the abstractions that wraps the + * drools layer (policy-core) + */ +public interface DroolsController extends Startable, Lockable { + + /** + * No Group ID identifier + */ + public static final String NO_GROUP_ID = "NO-GROUP-ID"; + + /** + * No Artifact ID identifier + */ + public static final String NO_ARTIFACT_ID = "NO-ARTIFACT-ID"; + + /** + * No version identifier + */ + public static final String NO_VERSION = "NO-VERSION"; + + /** + * get group id + * @return group id + */ + public String getGroupId(); + + /** + * get artifact id + * @return artifact id + */ + public String getArtifactId(); + + /** + * get version + * @return version + */ + public String getVersion(); + + /** + * return the policy session names + * + * @return policy session + */ + public List getSessionNames(); + + /** + * return the policy full session names + * + * @return policy session + */ + public List getCanonicalSessionNames(); + + /** + * offers an event to this controller for processing + * + * @param topic topic associated with the event + * @param event the event + * + * @return true if the operation was successful + */ + public boolean offer(String topic, String event); + + /** + * delivers "event" to "sink" + * + * @param sink destination + * @param 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 permitted (ie. locked or stopped). + * @throws UnsupportedOperationException when the engine cannot deliver due + * to the functionality missing (ie. communication infrastructure + * not supported. + */ + public boolean deliver(TopicSink sink, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException; + + /** + * + * @return the most recent received events + */ + public Object[] getRecentSourceEvents(); + + /** + * + * @return the most recent delivered events + */ + public String[] getRecentSinkEvents(); + + /** + * @return the underlying policy container + */ + public PolicyContainer getContainer(); + + /** + * Supports this encoder? + * + * @param encodedObject + * @return + */ + public boolean ownsCoder(Class coderClass, int modelHash) throws IllegalStateException; + + /** + * fetches a class from the model + * + * @param className the class to fetch + * @return the actual class object, or null if not found + */ + public Class fetchModelClass(String className) throws IllegalArgumentException; + + /** + * is this controller Smart? + */ + public boolean isBrained(); + + /** + * update the new version of the maven jar rules file + * + * @param newGroupId - new group id + * @param newArtifactId - new artifact id + * @param newVersion - new version + * @param decoderConfigurations - decoder configurations + * @param encoderConfigurations - encoder configurations + * + * @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 decoderConfigurations, + List encoderConfigurations) + throws IllegalArgumentException, LinkageError, Exception; + + /** + * gets the classnames of facts as well as the current count + * @param sessionName the session name + * @return map of class to count + */ + public Map factClassNames(String sessionName) throws IllegalArgumentException; + + /** + * 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) throws IllegalArgumentException; + + /** + * gets all the facts of a given class for a given session + * + * @param sessionName the session identifier + * @param className the class type + * @param delete retract from drools the results of the query? + * @return the list of facts returned by the query + */ + public List facts(String sessionName, String className, boolean delete); + + /** + * 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 + * @param queriedEntity the queried entity + * @param delete retract from drools the results of the query? + * @param queryParams query parameters + * @return list of facts returned by the query + */ + public List factQuery(String sessionName, String queryName, String queriedEntity, + boolean delete, Object... queryParams); + + /** + * halts and permanently releases all resources + * @throws IllegalStateException + */ + public void halt() throws IllegalStateException; + + /** + * Factory to track and manage drools controllers + */ + public static final DroolsControllerFactory factory = + new IndexedDroolsControllerFactory(); +} 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 new file mode 100644 index 00000000..c7a63a03 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java @@ -0,0 +1,555 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.controller; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.onap.policy.drools.controller.internal.MavenDroolsController; +import org.onap.policy.drools.controller.internal.NullDroolsController; +import org.onap.policy.drools.event.comm.Topic; +import org.onap.policy.drools.event.comm.Topic.CommInfrastructure; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.onap.policy.drools.event.comm.TopicSource; +import org.onap.policy.drools.event.comm.TopicSink; +import org.onap.policy.drools.properties.PolicyProperties; +import org.onap.policy.drools.protocol.coders.JsonProtocolFilter; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter; +import org.onap.policy.drools.utils.Pair; + +/** + * Drools Controller Factory to manage controller creation, destruction, + * and retrieval for management interfaces + */ +public interface DroolsControllerFactory { + + /** + * Constructs a Drools Controller based on properties + * + * @param properties properties containing initialization parameters + * @param eventSources list of event sources + * @param eventSinks list of event sinks + * + * @return the instantiated Drools Controller + * @throws IllegalArgumentException with invalid parameters + * @throws LinkageError Failure to link rules and models in Drools Libraries + * @throws Exception Exception from Drools Libraries + */ + public DroolsController build(Properties properties, + List eventSources, + List eventSinks) + throws IllegalArgumentException, LinkageError, Exception; + + /** + * Explicit construction of a Drools Controller + * + * @param groupId maven group id of drools artifact + * @param artifactId maven artifact id of drools artifact + * @param version maven version id of drools artifact + * @param decoderConfigurations list of decoder configurations + * @param encoderConfigurations list of encoder configurations + * + * @return the instantiated Drools Controller + * @throws IllegalArgumentException with invalid parameters + * @throws LinkageError Failure to link rules and models in Drools Libraries + * @throws Exception Exception from Drools Libraries + */ + public DroolsController build(String groupId, + String artifactId, + String version, + List decoderConfigurations, + List encoderConfigurations) + throws IllegalArgumentException, LinkageError, Exception; + + /** + * 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 + */ + public void shutdown(); + + /** + * Destroys and releases resources for a Drools Controller + * + * @param controller the Drools Controller to destroy + */ + public void destroy(DroolsController controller); + + /** + * Destroys all Drools Controllers + */ + public void destroy(); + + /** + * 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 + * @param version maven version id of drools artifact + * + * @return the Drools Controller + * @throws IllegalArgumentException with invalid parameters + */ + public DroolsController get(String groupId, + String artifactId, + String version) + throws IllegalArgumentException; + + /** + * returns the current inventory of Drools Controllers + * + * @return a list of Drools Controllers + */ + public List inventory(); +} + +/* ---------------- implementation -----------------*/ + +/** + * Factory of Drools Controllers indexed by the Maven coordinates + */ +class IndexedDroolsControllerFactory implements DroolsControllerFactory { + + /** + * logger + */ + private static Logger logger = LoggerFactory.getLogger(MavenDroolsController.class); + + /** + * Policy Controller Name Index + */ + protected HashMap droolsControllers = + new HashMap(); + + /** + * Null Drools Controller + */ + protected NullDroolsController nullDroolsController = new NullDroolsController(); + + + public IndexedDroolsControllerFactory() { + + /* Add a NULL controller which will always be present in the hash */ + + DroolsController controller = new NullDroolsController(); + String controllerId = controller.getGroupId() + ":" + controller.getArtifactId(); + + synchronized(this) { + droolsControllers.put(controllerId, controller); + } + } + + /** + * {@inheritDoc} + */ + @Override + public DroolsController build(Properties properties, + List eventSources, + List eventSinks) + throws IllegalArgumentException, LinkageError, Exception { + + String groupId = properties.getProperty(PolicyProperties.RULES_GROUPID); + if (groupId == null || groupId.isEmpty()) + groupId = DroolsController.NO_GROUP_ID; + + String artifactId = properties.getProperty(PolicyProperties.RULES_ARTIFACTID); + if (artifactId == null || artifactId.isEmpty()) + artifactId = DroolsController.NO_ARTIFACT_ID; + + String version = properties.getProperty(PolicyProperties.RULES_VERSION); + if (version == null || version.isEmpty()) + version = DroolsController.NO_VERSION; + + List + topics2DecodedClasses2Filters = codersAndFilters(properties, eventSources); + + List + topics2EncodedClasses2Filters = codersAndFilters(properties, eventSinks); + + return this.build(groupId, artifactId, version, + topics2DecodedClasses2Filters, + topics2EncodedClasses2Filters); + } + + /** + * find out decoder classes and filters + * + * @param properties properties with information about decoders + * @param topicEntities topic sources + * @return list of topics, each with associated decoder classes, each + * with a list of associated filters + * @throws IllegalArgumentException invalid input data + */ + protected List codersAndFilters + (Properties properties, List topicEntities) + throws IllegalArgumentException { + + String PROPERTY_TOPIC_ENTITY_PREFIX; + + List + topics2DecodedClasses2Filters = + new ArrayList(); + + if (topicEntities.isEmpty()) + return topics2DecodedClasses2Filters; + + for (Topic topic: topicEntities) { + + /* source or sink ? ueb or dmaap? */ + boolean isSource = (topic instanceof TopicSource); + CommInfrastructure commInfra = topic.getTopicCommInfrastructure(); + if (commInfra == CommInfrastructure.UEB) { + if (isSource) { + PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + "."; + } else { + PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_UEB_SINK_TOPICS + "."; + } + } else if (commInfra == CommInfrastructure.DMAAP) { + if (isSource) { + PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + "."; + } else { + PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_DMAAP_SINK_TOPICS + "."; + } + } else if (commInfra == CommInfrastructure.NOOP) { + if (!isSource) + PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_NOOP_SINK_TOPICS + "."; + else + continue; + } else { + throw new IllegalArgumentException("Invalid Communication Infrastructure: " + commInfra); + } + + // 1. first the topic + + String aTopic = 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 + (PROPERTY_TOPIC_ENTITY_PREFIX + + aTopic + + PolicyProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_GSON_SUFFIX); + + CustomGsonCoder customGsonCoder = null; + if (customGson != null && !customGson.isEmpty()) { + try { + customGsonCoder = new CustomGsonCoder(customGson); + } catch (IllegalArgumentException e) { + logger.warn("{}: cannot create custom-gson-coder {} because of {}", + this, customGson, e.getMessage(), e); + } + } + + String customJackson = properties.getProperty + (PROPERTY_TOPIC_ENTITY_PREFIX + + aTopic + + PolicyProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_JACKSON_SUFFIX); + + CustomJacksonCoder customJacksonCoder = null; + if (customJackson != null && !customJackson.isEmpty()) { + try { + customJacksonCoder = new CustomJacksonCoder(customJackson); + } catch (IllegalArgumentException e) { + logger.warn("{}: cannot create custom-jackson-coder {} because of {}", + this, customJackson, e.getMessage(), e); + } + } + + // 3. second the list of classes associated with each topic + + String eventClasses = + properties.getProperty(PROPERTY_TOPIC_ENTITY_PREFIX + aTopic + PolicyProperties.PROPERTY_TOPIC_EVENTS_SUFFIX); + + if (eventClasses == null || eventClasses.isEmpty()) { + // TODO warn + continue; + } + + List classes2Filters = new ArrayList(); + + List aTopicClasses = + new ArrayList(Arrays.asList(eventClasses.split("\\s*,\\s*"))); + + for (String aClass: aTopicClasses) { + + + // 4. third, for each coder class, get the list of field filters + + String filter = properties.getProperty + (PROPERTY_TOPIC_ENTITY_PREFIX + + aTopic + + PolicyProperties.PROPERTY_TOPIC_EVENTS_SUFFIX + + "." + aClass + + PolicyProperties.PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX); + + List> filters = new ArrayList>(); + + if (filter == null || filter.isEmpty()) { + // 4. topic -> class -> with no filters + + JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters); + PotentialCoderFilter class2Filters = + new PotentialCoderFilter(aClass, protocolFilter); + classes2Filters.add(class2Filters); + continue; + } + + // There are filters associated with the applicability of + // this class for decoding. + List listOfFilters = + new ArrayList(Arrays.asList(filter.split("\\s*,\\s*"))); + + for (String nameValue: listOfFilters) { + String fieldName; + String regexValue; + + String[] nameValueSplit = nameValue.split("\\s*=\\s*"); + if (nameValueSplit.length <= 0 || nameValueSplit.length > 2) { + // TODO warn + // skip + continue; + } + + if (nameValueSplit.length == 2) { + fieldName = nameValueSplit[0]; + regexValue = nameValueSplit[1]; + } else if (nameValueSplit.length == 1) { + fieldName = nameValueSplit[0]; + regexValue = null; + } else { + // unreachable + continue; + } + + filters.add(new Pair(fieldName, regexValue)); + } + + JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters); + PotentialCoderFilter class2Filters = + new PotentialCoderFilter(aClass, protocolFilter); + classes2Filters.add(class2Filters); + } + + TopicCoderFilterConfiguration topic2Classes2Filters = + new TopicCoderFilterConfiguration(aTopic,classes2Filters, customGsonCoder, customJacksonCoder); + topics2DecodedClasses2Filters.add(topic2Classes2Filters); + } + + return topics2DecodedClasses2Filters; + } + + /** + * {@inheritDoc} + * @param decoderConfiguration + */ + @Override + public DroolsController build(String newGroupId, + String newArtifactId, + String newVersion, + List decoderConfigurations, + List encoderConfigurations) + throws IllegalArgumentException, LinkageError, Exception { + + if (newGroupId == null || newArtifactId == null || newVersion == null || + newGroupId.isEmpty() || newArtifactId.isEmpty() || newVersion.isEmpty()) { + throw new IllegalArgumentException("Missing maven coordinates: " + + newGroupId + ":" + newArtifactId + ":" + + newVersion); + } + + 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; + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy(DroolsController controller) throws IllegalArgumentException { + unmanage(controller); + controller.halt(); + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy() { + List controllers = this.inventory(); + for (DroolsController controller: controllers) { + controller.halt(); + } + + synchronized(this) { + this.droolsControllers.clear(); + } + } + + /** + * unmanage the drools controller + * + * @param controller + * @return + * @throws IllegalArgumentException + */ + protected void unmanage(DroolsController controller) throws IllegalArgumentException { + if (controller == null) { + throw new IllegalArgumentException("No controller provided"); + } + + if (!controller.isBrained()) { + logger.info("Drools Controller is NOT OPERATIONAL - nothing to destroy"); + return; + } + + String controllerId = controller.getGroupId() + ":" + controller.getArtifactId(); + synchronized(this) { + if (!this.droolsControllers.containsKey(controllerId)) { + return; + } + + droolsControllers.remove(controllerId); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown(DroolsController controller) throws IllegalArgumentException { + this.unmanage(controller); + controller.shutdown(); + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() { + List controllers = this.inventory(); + for (DroolsController controller: controllers) { + controller.shutdown(); + } + + synchronized(this) { + this.droolsControllers.clear(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public DroolsController get(String groupId, + String artifactId, + String version) + throws IllegalArgumentException, IllegalStateException { + + if (groupId == null || artifactId == null || + groupId.isEmpty() || artifactId.isEmpty()) { + throw new IllegalArgumentException("Missing maven coordinates: " + + groupId + ":" + artifactId); + } + + String controllerId = groupId + ":" + artifactId; + + synchronized(this) { + if (this.droolsControllers.containsKey(controllerId)) { + return droolsControllers.get(controllerId); + } else { + throw new IllegalStateException("DroolController for " + + controllerId + " not found"); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public List inventory() { + List controllers = + new ArrayList(this.droolsControllers.values()); + return controllers; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("IndexedDroolsControllerFactory [#droolsControllers=").append(droolsControllers.size()) + .append("]"); + return builder.toString(); + } + +} diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java new file mode 100644 index 00000000..db62f782 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java @@ -0,0 +1,910 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.controller.internal; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections4.queue.CircularFifoQueue; +import org.drools.core.ClassObjectFilter; +import org.kie.api.definition.KiePackage; +import org.kie.api.definition.rule.Query; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.core.PolicyContainer; +import org.onap.policy.drools.core.PolicySession; +import org.onap.policy.drools.core.jmx.PdpJmx; +import org.onap.policy.drools.event.comm.TopicSink; +import org.onap.policy.drools.protocol.coders.EventProtocolCoder; +import org.onap.policy.drools.protocol.coders.JsonProtocolFilter; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter; +import org.onap.policy.drools.utils.ReflectionUtil; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Maven-based Drools Controller that interacts with the + * policy-core PolicyContainer and PolicySession to manage + * 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 decoderConfigurations; + + /** + * list of topics, each with associated encoder classes, each + * with a list of associated filters. + */ + protected List encoderConfigurations; + + /** + * recent source events processed + */ + protected final CircularFifoQueue recentSourceEvents = new CircularFifoQueue(10); + + /** + * recent sink events processed + */ + protected final CircularFifoQueue 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 decoderConfiguration list of topic -> decoders -> filters mapping + * @param encoderConfiguration list of topic -> encoders -> filters mapping + * + * @throws IllegalArgumentException invalid arguments passed in + */ + public MavenDroolsController(String groupId, + String artifactId, + String version, + List decoderConfigurations, + List encoderConfigurations) + throws IllegalArgumentException { + + if (logger.isInfoEnabled()) + logger.info("DROOLS CONTROLLER: instantiation " + this + + " -> {" + groupId + ":" + artifactId + ":" + version + "}"); + + if (groupId == null || artifactId == null || version == null || + groupId.isEmpty() || artifactId.isEmpty() || version.isEmpty()) { + throw new IllegalArgumentException("Missing maven coordinates: " + + groupId + ":" + artifactId + ":" + + version); + } + + this.policyContainer= new PolicyContainer(groupId, artifactId, version); + this.init(decoderConfigurations, encoderConfigurations); + + if (logger.isInfoEnabled()) + logger.info("DROOLS CONTROLLER: instantiation completed " + this); + } + + /** + * init encoding/decoding configuration + * @param decoderConfiguration list of topic -> decoders -> filters mapping + * @param encoderConfiguration list of topic -> encoders -> filters mapping + */ + protected void init(List decoderConfigurations, + List encoderConfigurations) { + + this.decoderConfigurations = decoderConfigurations; + this.encoderConfigurations = encoderConfigurations; + + this.initCoders(decoderConfigurations, true); + this.initCoders(encoderConfigurations, false); + + this.modelClassLoaderHash = this.policyContainer.getClassLoader().hashCode(); + } + + /** + * {@inheritDoc} + */ + @Override + public void updateToVersion(String newGroupId, String newArtifactId, String newVersion, + List decoderConfigurations, + List encoderConfigurations) + throws IllegalArgumentException, LinkageError, Exception { + + if (logger.isInfoEnabled()) + logger.info("UPDATE-TO-VERSION: " + this + " -> {" + newGroupId + ":" + newArtifactId + ":" + newVersion + "}"); + + if (newGroupId == null || newArtifactId == null || newVersion == null || + newGroupId.isEmpty() || newArtifactId.isEmpty() || newVersion.isEmpty()) { + throw new IllegalArgumentException("Missing maven coordinates: " + + newGroupId + ":" + newArtifactId + ":" + + newVersion); + } + + 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 decoderConfiguration list of topic -> decoders -> filters mapping + */ + protected void initCoders(List coderConfigurations, + boolean decoder) + throws IllegalArgumentException { + + 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)) { + logger.error(customGsonCoderClass + " cannot be retrieved"); + throw new IllegalArgumentException(customGsonCoderClass + " cannot be retrieved"); + } else { + if (logger.isInfoEnabled()) + logger.info("CLASS FETCHED " + 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)) { + logger.error(customJacksonCoderClass + " cannot be retrieved"); + throw new IllegalArgumentException(customJacksonCoderClass + " cannot be retrieved"); + } else { + if (logger.isInfoEnabled()) + logger.info("CLASS FETCHED " + customJacksonCoderClass); + } + } + + List 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)) { + logger.error(potentialCodedClass + " cannot be retrieved"); + throw new IllegalArgumentException(potentialCodedClass + " cannot be retrieved"); + } else { + if (logger.isInfoEnabled()) + logger.info("CLASS FETCHED " + 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()); + } + } + } + + + /** + * remove decoders. + */ + protected void removeDecoders() + throws IllegalArgumentException { + 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() + throws IllegalArgumentException { + + 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); + } + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean ownsCoder(Class coderClass, int modelHash) throws IllegalStateException { + 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; + } + } + + /** + * {@inheritDoc} + */ + @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(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() { + + logger.info("STOP: " + this); + + synchronized (this) { + if (!this.alive) + return true; + + this.alive = false; + } + + return this.policyContainer.stop(); + } + + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + 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(); + } + + } + + + /** + * {@inheritDoc} + */ + @Override + public void halt() throws IllegalStateException { + 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); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + return this.alive; + } + + /** + * {@inheritDoc} + */ + @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().size() <= 0) { + // 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()); + + if (!this.policyContainer.insertAll(anEvent)) + logger.warn(this + "Failed to inject into PolicyContainer " + this.getSessionNames()); + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(TopicSink sink, Object event) + throws IllegalArgumentException, + IllegalStateException, + UnsupportedOperationException { + + 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); + + } + + /** + * {@inheritDoc} + */ + @Override + public String getVersion() { + return this.policyContainer.getVersion(); + } + + /** + * {@inheritDoc} + */ + @Override + public String getArtifactId() { + return this.policyContainer.getArtifactId(); + } + + /** + * {@inheritDoc} + */ + @Override + public String getGroupId() { + return this.policyContainer.getGroupId(); + } + + /** + * @return the modelClassLoaderHash + */ + public int getModelClassLoaderHash() { + return modelClassLoaderHash; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized boolean lock() { + logger.info("LOCK: " + this); + + this.locked = true; + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized boolean unlock() { + logger.info("UNLOCK: " + this); + + this.locked = false; + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLocked() { + return this.locked; + } + + /** + * {@inheritDoc} + */ + @JsonIgnore + public PolicyContainer getContainer() { + return this.policyContainer; + } + + /** + * {@inheritDoc} + */ + @JsonProperty("sessions") + @Override + public List getSessionNames() { + return getSessionNames(true); + } + + /** + * {@inheritDoc} + */ + @JsonProperty("sessionCoordinates") + @Override + public List getCanonicalSessionNames() { + return getSessionNames(false); + } + + /** + * get session names + * @param abbreviated true for the short form, otherwise the long form + * @return session names + */ + protected List getSessionNames(boolean abbreviated) { + List 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 getSessions() { + List 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 sessions = this.getSessions(); + for (PolicySession session : sessions) { + if (sessionName.equals(session.getName()) || sessionName.equals(session.getName())) + return session; + } + + throw new IllegalArgumentException("Invalid Session Name: " + sessionName); + } + + /** + * {@inheritDoc} + */ + @Override + public Map factClassNames(String sessionName) throws IllegalArgumentException { + if (sessionName == null || sessionName.isEmpty()) + throw new IllegalArgumentException("Invalid Session Name: " + sessionName); + + // List classNames = new ArrayList<>(); + Map classNames = new HashMap<>(); + + PolicySession session = getSession(sessionName); + KieSession kieSession = session.getKieSession(); + + Collection 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) { + if (logger.isInfoEnabled()) + logger.info("Object cannot be retrieved from fact: " + fact); + } + } + + return classNames; + } + + /** + * {@inheritDoc} + */ + @Override + public long factCount(String sessionName) throws IllegalArgumentException { + if (sessionName == null || sessionName.isEmpty()) + throw new IllegalArgumentException("Invalid Session Name: " + sessionName); + + PolicySession session = getSession(sessionName); + return session.getKieSession().getFactCount(); + } + + /** + * {@inheritDoc} + */ + @Override + public List facts(String sessionName, String className, boolean delete) { + if (sessionName == null || sessionName.isEmpty()) + throw new IllegalArgumentException("Invalid Session Name: " + 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 factObjects = new ArrayList<>(); + + Collection factHandles = kieSession.getFactHandles(new ClassObjectFilter(factClass)); + for (FactHandle factHandle : factHandles) { + try { + factObjects.add(kieSession.getObject(factHandle)); + if (delete) + kieSession.delete(factHandle); + } catch (Exception e) { + if (logger.isInfoEnabled()) + logger.info("Object cannot be retrieved from fact: " + factHandle); + } + } + + return factObjects; + } + + /** + * {@inheritDoc} + */ + @Override + public List factQuery(String sessionName, String queryName, String queriedEntity, boolean delete, Object... queryParams) { + if (sessionName == null || sessionName.isEmpty()) + throw new IllegalArgumentException("Invalid Session Name: " + 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 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) { + if (logger.isInfoEnabled()) + logger.info("Object cannot be retrieved from fact: " + row); + } + } + + return factObjects; + } + + /** + * {@inheritDoc} + */ + @Override + public Class fetchModelClass(String className) throws IllegalStateException { + Class modelClass = + ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className); + return modelClass; + } + + /** + * @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); + } + } + + + /** + * {@inheritDoc} + */ + @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 new file mode 100644 index 00000000..3fef6fa9 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java @@ -0,0 +1,262 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.controller.internal; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.core.PolicyContainer; +import org.onap.policy.drools.event.comm.TopicSink; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; + +/** + * no-op Drools Controller + */ +public class NullDroolsController implements DroolsController { + + /** + * {@inheritDoc} + */ + @Override + public boolean start() throws IllegalStateException { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() throws IllegalStateException { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public void halt() throws IllegalStateException { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean lock() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean unlock() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLocked() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public String getGroupId() { + return NO_GROUP_ID; + } + + /** + * {@inheritDoc} + */ + @Override + public String getArtifactId() { + return NO_ARTIFACT_ID; + } + + /** + * {@inheritDoc} + */ + @Override + public String getVersion() { + return NO_VERSION; + } + + /** + * {@inheritDoc} + */ + @Override + public List getSessionNames() { + return new ArrayList(); + } + + /** + * {@inheritDoc} + */ + @Override + public List getCanonicalSessionNames() { + return new ArrayList(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean offer(String topic, String event) { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(TopicSink sink, Object event) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + throw new IllegalStateException(this.getClass().getCanonicalName() + " invoked"); + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] getRecentSourceEvents() { + return new String[0]; + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyContainer getContainer() { + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public String[] getRecentSinkEvents() { + return new String[0]; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean ownsCoder(Class coderClass, int modelHash) throws IllegalStateException { + throw new IllegalStateException(this.getClass().getCanonicalName() + " invoked"); + } + + /** + * {@inheritDoc} + */ + @Override + public Class fetchModelClass(String className) throws IllegalArgumentException { + throw new IllegalArgumentException(this.getClass().getCanonicalName() + " invoked"); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isBrained() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("NullDroolsController []"); + return builder.toString(); + } + + /** + * {@inheritDoc} + */ + @Override + public void updateToVersion(String newGroupId, String newArtifactId, String newVersion, + List decoderConfigurations, + List encoderConfigurations) + throws IllegalArgumentException, LinkageError, Exception { + throw new IllegalArgumentException(this.getClass().getCanonicalName() + " invoked"); + } + + /** + * {@inheritDoc} + */ + @Override + public Map factClassNames(String sessionName) + throws IllegalArgumentException { + return new HashMap(); + } + + /** + * {@inheritDoc} + */ + @Override + public long factCount(String sessionName) throws IllegalArgumentException { + return 0; + } + + /** + * {@inheritDoc} + */ + @Override + public List facts(String sessionName, String className, boolean delete) { + return new ArrayList(); + } + + /** + * {@inheritDoc} + */ + @Override + public List factQuery(String sessionName, String queryName, + String queriedEntity, + boolean delete, Object... queryParams) { + return new ArrayList(); + } +} 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 new file mode 100644 index 00000000..9d166f58 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureAPI.java @@ -0,0 +1,222 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.features; + +import java.util.Properties; + +import org.onap.policy.drools.event.comm.Topic.CommInfrastructure; +import org.onap.policy.drools.system.PolicyController; +import org.onap.policy.drools.utils.OrderedService; +import org.onap.policy.drools.utils.OrderedServiceImpl; + +public interface PolicyControllerFeatureAPI extends OrderedService { + + /** + * 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 providers = + new OrderedServiceImpl(PolicyControllerFeatureAPI.class); +} 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 new file mode 100644 index 00000000..eb65c706 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyEngineFeatureAPI.java @@ -0,0 +1,202 @@ +/*- + * ============LICENSE_START======================================================= + * policy-engine + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.features; + +import java.util.Properties; + +import org.onap.policy.drools.system.PolicyEngine; +import org.onap.policy.drools.utils.OrderedService; +import org.onap.policy.drools.utils.OrderedServiceImpl; + +/** + * Policy Engine Feature API. + * Provides Interception Points during the Policy Engine lifecycle. + */ +public interface PolicyEngineFeatureAPI extends OrderedService { + + /** + * 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;}; + + /** + * Feature providers implementing this interface + */ + public static final OrderedServiceImpl providers = + new OrderedServiceImpl<>(PolicyEngineFeatureAPI.class); +} 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 new file mode 100644 index 00000000..52aac744 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/persistence/SystemPersistence.java @@ -0,0 +1,248 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.persistence; + +import java.io.File; +import java.io.FileWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Properties; + +import org.onap.policy.drools.utils.PropertyUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public interface SystemPersistence { + + /** + * configuration directory + */ + public static String CONFIG_DIR_NAME = "config"; + + /** + * policy controllers suffix + */ + public final static String CONTROLLER_SUFFIX_IDENTIFIER = "-controller"; + + /** + * policy controller properties file suffix + */ + public final static String PROPERTIES_FILE_CONTROLLER_SUFFIX = + CONTROLLER_SUFFIX_IDENTIFIER + ".properties"; + + /** + * policy engine properties file name + */ + public final static String PROPERTIES_FILE_ENGINE = "policy-engine.properties"; + + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) throws IllegalArgumentException; + + /** + * 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 SystemPropertiesPersistence(); +} + +/** + * Properties based Persistence + */ +class SystemPropertiesPersistence implements SystemPersistence { + + /** + * logger + */ + private static Logger logger = LoggerFactory.getLogger(SystemPropertiesPersistence.class); + + /** + * backs up the properties-based controller configuration + * @param controllerName the controller name + * @return true if the configuration is backed up in disk or back up does not apply, false otherwise. + */ + @Override + public boolean backupController(String controllerName) { + Path controllerPropertiesPath = + Paths.get(CONFIG_DIR_NAME, controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX); + + if (Files.exists(controllerPropertiesPath)) { + try { + logger.warn("There is an existing configuration file at " + + controllerPropertiesPath.toString() + + " with contents: " + Files.readAllBytes(controllerPropertiesPath)); + Path controllerPropertiesBakPath = + Paths.get(CONFIG_DIR_NAME, controllerName + + PROPERTIES_FILE_CONTROLLER_SUFFIX + ".bak"); + Files.copy(controllerPropertiesPath, + controllerPropertiesBakPath, StandardCopyOption.REPLACE_EXISTING); + } catch (Exception e) { + logger.warn("{}: cannot be backed up", controllerName, e); + return false; + } + } + + return true; + } + + /** + * persists properties-based controller configuration and makes a backup if necessary + * @param controllerName the controller name + * @return true if the properties has been stored in disk, false otherwise + */ + @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"); + } + + Properties properties = (Properties) configuration; + + Path controllerPropertiesPath = + Paths.get(CONFIG_DIR_NAME, controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX); + if (Files.exists(controllerPropertiesPath)) { + try { + Properties oldProperties = PropertyUtil.getProperties(controllerPropertiesPath.toFile()); + if (oldProperties.equals(properties)) { + logger.info("A properties file with the same contents already exists for controller " + + controllerName + + ". No action is taken"); + return true; + } else { + this.backupController(controllerName); + } + } catch (Exception e) { + logger.info("{}: no existing Properties", controllerName); + // continue + } + } + + try { + File controllerPropertiesFile = controllerPropertiesPath.toFile(); + FileWriter writer = new FileWriter(controllerPropertiesFile); + properties.store(writer, "Machine created Policy Controller Configuration"); + } catch (Exception e) { + logger.warn("{}: cannot be STORED", controllerName, e); + return false; + } + + return true; + } + + /** + * deletes properties-based controller configuration + * @param controllerName the controller name + * @return true if the properties has been deleted from disk, false otherwise + */ + @Override + public boolean deleteController(String controllerName) { + + Path controllerPropertiesPath = + Paths.get(CONFIG_DIR_NAME, + controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX); + + if (Files.exists(controllerPropertiesPath)) { + try { + Path controllerPropertiesBakPath = + Paths.get(CONFIG_DIR_NAME, controllerName + + PROPERTIES_FILE_CONTROLLER_SUFFIX + ".bak"); + Files.move(controllerPropertiesPath, + controllerPropertiesBakPath, + StandardCopyOption.REPLACE_EXISTING); + } catch (Exception e) { + logger.warn("{}: cannot be DELETED", controllerName, e); + return false; + } + } + + return true; + } + + @Override + public Properties getControllerProperties(String controllerName) throws IllegalArgumentException { + return this.getProperties(controllerName + CONTROLLER_SUFFIX_IDENTIFIER); + } + + @Override + public Properties getProperties(String name) throws IllegalArgumentException { + Path propertiesPath = + Paths.get(CONFIG_DIR_NAME, name + ".properties"); + + if (!Files.exists(propertiesPath)) { + throw new IllegalArgumentException("properties for " + name + " are not persisted."); + } + + try { + return PropertyUtil.getProperties(propertiesPath.toFile()); + } catch (Exception e) { + logger.warn("{}: can't read properties @ {}", name, propertiesPath); + throw new IllegalArgumentException("can't read properties for " + + name + " @ " + + propertiesPath); + } + } +} 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 new file mode 100644 index 00000000..762f4476 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java @@ -0,0 +1,1393 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.protocol.coders; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; +import org.onap.policy.drools.utils.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Coder (Encoder/Decoder) of Events. + */ +public interface EventProtocolCoder { + + 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 synchronized JsonProtocolFilter getFilter() { + return filter; + } + + /** + * @param filter the filter to set + */ + public synchronized 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) + throws IllegalArgumentException; + + /** + * 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) throws IllegalArgumentException; + + /** + * 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) throws IllegalArgumentException; + + /** + * 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 getDecoderFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException; + + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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 getDecoders(String groupId, String artifactId) + throws IllegalArgumentException; + + + /** + * 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 getDecoderFilters(String groupId, String artifactId) throws IllegalArgumentException; + + + /** + * 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 getEncoderFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException; + + /** + * 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 getEncoderFilters(String groupId, String artifactId) throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * get encoder based on topic and encoded class + * + * @param topic topic + * @param encodedClass encoded class + * @return + * @throws IllegalArgumentException invalid arguments passed in + */ + public List getReverseEncoderFilters(String topic, String encodedClass) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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 getDroolsControllers(String topic, Object encodedClass) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException; + + /** + * 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) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; + + /** + * 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) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; + + /** + * 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) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; + + /** + * singleton reference to the global event protocol coder + */ + public static EventProtocolCoder manager = new MultiplexorEventProtocolCoder(); +} + +/** + * Protocol Coder that does its best attempt to decode/encode, selecting the best + * class and best fitted json parsing tools. + */ +class MultiplexorEventProtocolCoder implements EventProtocolCoder { + /** + * Logger + */ + private static Logger logger = LoggerFactory.getLogger(MultiplexorEventProtocolCoder.class); + + /** + * Decoders + */ + protected EventProtocolDecoder decoders = new EventProtocolDecoder(); + + /** + * Encoders + */ + protected EventProtocolEncoder encoders = new EventProtocolEncoder(); + + + /** + * {@inheritDoc} + */ + @Override + public void addDecoder(String groupId, String artifactId, String topic, + String eventClass, + JsonProtocolFilter protocolFilter, + CustomGsonCoder customGsonCoder, + CustomJacksonCoder customJacksonCoder, + int modelClassLoaderHash) + throws IllegalArgumentException { + 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) + throws IllegalArgumentException { + 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) + throws IllegalArgumentException { + 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) + throws IllegalArgumentException { + 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) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + 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) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + 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) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + logger.debug("{}: encode {}:{}", this, topic, event); + return this.encoders.encode(topic, event); + } + + /** + * {@inheritDoc} + */ + @Override + public String encode(String topic, Object event, DroolsController droolsController) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + logger.debug("{}: encode {}:{}:{}", this, topic, event, droolsController); + return this.encoders.encode(topic, event, droolsController); + } + + /** + * {@inheritDoc} + */ + @Override + public List getDecoderFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + return this.decoders.getFilters(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + Pair 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 getEncoderFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + return this.encoders.getFilters(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname) + throws IllegalArgumentException { + return this.decoders.getFilters(groupId, artifactId, topic, classname); + } + + /** + * {@inheritDoc} + */ + @Override + public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname) + throws IllegalArgumentException { + return this.encoders.getFilters(groupId, artifactId, topic, classname); + } + + /** + * {@inheritDoc} + */ + @Override + public List getReverseEncoderFilters(String topic, String encodedClass) throws IllegalArgumentException { + 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 getDecoders(String groupId, String artifactId) + throws IllegalArgumentException { + + List> decoderToolsets = this.decoders.getCoders(groupId, artifactId); + if (decoderToolsets == null) + throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId); + + List parser1CoderToolset = new ArrayList<>(); + for (Pair coderToolsetPair : decoderToolsets) { + parser1CoderToolset.add(coderToolsetPair.first()); + } + + return parser1CoderToolset; + } + + /** + * {@inheritDoc} + */ + @Override + public List getDecoderFilters(String groupId, String artifactId) throws IllegalArgumentException { + return this.decoders.getFilters(groupId, artifactId); + + } + + /** + * {@inheritDoc} + */ + @Override + public List getEncoderFilters(String groupId, String artifactId) throws IllegalArgumentException { + return this.encoders.getFilters(groupId, artifactId); + } + + /** + * {@inheritDoc} + */ + @Override + public DroolsController getDroolsController(String topic, Object encodedClass) throws IllegalArgumentException { + return this.encoders.getDroolsController(topic, encodedClass); + } + + /** + * {@inheritDoc} + */ + @Override + public List getDroolsControllers(String topic, Object encodedClass) throws IllegalArgumentException { + 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(); + } +} + +/** + * This protocol Coder that does its best attempt to decode/encode, selecting the best + * class and best fitted json parsing tools. + */ +abstract class GenericEventProtocolCoder { + private static Logger logger = LoggerFactory.getLogger(GenericEventProtocolCoder.class); + + /** + * Mapping topic:controller-id -> + * 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> coders = + new HashMap>(); + + /** + * Mapping topic + classname -> Protocol Set + */ + protected final HashMap>> 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) + throws IllegalArgumentException { + if (groupId == null || groupId.isEmpty()) { + throw new IllegalArgumentException("Invalid group id"); + } + + if (artifactId == null || artifactId.isEmpty()) + throw new IllegalArgumentException("Invalid artifact id"); + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + 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 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> 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 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> toolsets = + reverseCoders.get(reverseKey); + boolean present = false; + for (Pair 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> 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) + throws IllegalArgumentException { + + if (groupId == null || groupId.isEmpty()) + throw new IllegalArgumentException("Invalid group id"); + + if (artifactId == null || artifactId.isEmpty()) + throw new IllegalArgumentException("Invalid artifact id"); + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + String key = this.codersKey(groupId, artifactId, topic); + + synchronized(this) { + if (coders.containsKey(key)) { + Pair 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> toolsets = + this.reverseCoders.get(reverseKey); + Iterator> toolsetsIter = + toolsets.iterator(); + while (toolsetsIter.hasNext()) { + Pair 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"); + + if (artifactId == null || artifactId.isEmpty()) + throw new IllegalArgumentException("Invalid artifact id"); + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + 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) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + + if (!isCodingSupported(groupId, artifactId, topic)) + throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic) + " for encoding"); + + String key = this.codersKey(groupId, artifactId, topic); + Pair 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) + throws IllegalArgumentException, UnsupportedOperationException { + + 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) + throws IllegalArgumentException, UnsupportedOperationException { + + logger.debug("{}: encode for {}: {}", this, key, event); + + Pair 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) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + + if (event == null) + throw new IllegalArgumentException("Invalid encoded class"); + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid topic"); + + List droolsControllers = droolsCreators(topic, event); + + if (droolsControllers.isEmpty()) + throw new IllegalArgumentException("no drools controller has been found"); + + if (droolsControllers.size() > 1) { + logger.warn("{}: multiple drools-controller {} for {}:{} ", this, topic, + droolsControllers, event.getClass().getCanonicalName()); + // continue + } + + String key = codersKey(droolsControllers.get(0).getGroupId(), droolsControllers.get(0).getArtifactId(), topic); + return this.encodeInternal(key, event); + } + + /** + * encode an object into a json string + * + * @param topic topic + * @param encodedClass object to convert to string + * @return the json string + * @throws IllegalArgumentException if invalid argument is provided + * @throws UnsupportedOperationException if the operation cannot be performed + */ + public String encode(String topic, Object encodedClass, DroolsController droolsController) + throws IllegalArgumentException, IllegalArgumentException, UnsupportedOperationException { + + 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 droolsCreators(String topic, Object encodedClass) + throws IllegalStateException, IllegalArgumentException { + + List 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> + toolsets = this.reverseCoders.get(reverseKey); + + // There must be multiple toolset pairs associated with 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 encoderSet : toolsets) { + // figure out the right toolset + String groupId = encoderSet.first().getGroupId(); + String artifactId = encoderSet.first().getArtifactId(); + List coders = encoderSet.first().getCoders(); + for (CoderFilters coder : coders) { + 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 getFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + + if (!isCodingSupported(groupId, artifactId, topic)) + throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic)); + + String key = this.codersKey(groupId, artifactId, topic); + Pair 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 getCoders(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + + if (!isCodingSupported(groupId, artifactId, topic)) + throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic)); + + String key = this.codersKey(groupId, artifactId, topic); + Pair coderTools = coders.get(key); + return coderTools; + } + + /** + * 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 getFilters(String groupId, String artifactId) + throws IllegalArgumentException { + + if (groupId == null || groupId.isEmpty()) + throw new IllegalArgumentException("Invalid group id"); + + if (artifactId == null || artifactId.isEmpty()) + throw new IllegalArgumentException("Invalid artifact id"); + + String key = this.codersKey(groupId, artifactId, ""); + + List codersFilters = new ArrayList(); + for (Map.Entry> 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> getCoders(String groupId, String artifactId) + throws IllegalArgumentException { + + if (groupId == null || groupId.isEmpty()) + throw new IllegalArgumentException("Invalid group id"); + + if (artifactId == null || artifactId.isEmpty()) + throw new IllegalArgumentException("Invalid artifact id"); + + String key = this.codersKey(groupId, artifactId, ""); + + List> coderToolset = new ArrayList>(); + for (Map.Entry> 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) + throws IllegalArgumentException { + + 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 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 getReverseFilters(String topic, String codedClass) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Unsupported"); + + if (codedClass == null) + throw new IllegalArgumentException("class must be provided"); + + String key = this.reverseCodersKey(topic, codedClass); + List> toolsets = this.reverseCoders.get(key); + if (toolsets == null) + throw new IllegalArgumentException("No Coder found for " + key); + + + List coders = new ArrayList(); + for (Pair toolset: toolsets) { + coders.addAll(toolset.first().getCoders()); + } + + return coders; + } + + /** + * returns group and artifact id of the creator of the encoder + * + * @param topic + * @param fact + * @return + * @throws IllegalArgumentException + */ + DroolsController getDroolsController(String topic, Object fact) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Unsupported"); + + if (fact == null) + throw new IllegalArgumentException("class must be provided"); + + List 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 getDroolsControllers(String topic, Object fact) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Unsupported"); + + if (fact == null) + throw new IllegalArgumentException("class must be provided"); + + List 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(); + } + +} + +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(); + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..6afeb26a --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java @@ -0,0 +1,308 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.protocol.coders; + +import java.util.ArrayList; +import java.util.List; + +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. Evaluates an JSON string and evaluates if it + * passes its filters. + */ +public class JsonProtocolFilter { + + /** + * Logger + */ + private static Logger logger = LoggerFactory.getLogger(JsonProtocolFilter.class); + + /** + * Helper class to collect Filter information + */ + public static class FilterRule { + /** + * Field name + */ + protected String name; + + /** + * Field Value regex + */ + protected String regex; + + /** + * Filter Constructor + * + * @param name field name + * @param regex field regex value + */ + public FilterRule(String name, String regex) { + this.name = name; + this.regex = 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) { + this.name = name; + } + + /** + * sets regex name + * @param regex + */ + public void setRegex(String 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 rules = new ArrayList(); + + /** + * + * @param rawFilters raw filter initialization + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public static JsonProtocolFilter fromRawFilters(List> rawFilters) + throws IllegalArgumentException { + + if (rawFilters == null) { + throw new IllegalArgumentException("No raw filters provided"); + } + + List filters = new ArrayList(); + for (Pair filterPair: rawFilters) { + if (filterPair.first() == null || filterPair.first().isEmpty()) { + continue; + } + + filters.add(new FilterRule(filterPair.first(), filterPair.second())); + } + return new JsonProtocolFilter(filters); + } + + /** + * Create a Protocol Filter + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public JsonProtocolFilter() throws IllegalArgumentException {} + + /** + * + * @param rawFilters raw filter initialization + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public JsonProtocolFilter(List filters) throws IllegalArgumentException { + this.rules = 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 synchronized boolean accept(JsonElement json) throws IllegalArgumentException { + if (json == null) { + throw new IllegalArgumentException("no JSON provided"); + } + + if (rules.isEmpty()) { + return true; + } + + try { + if (!json.isJsonObject()) { + return false; + } + + JsonObject event = json.getAsJsonObject(); + for (FilterRule filter: rules) { + if (filter.regex == null || + filter.regex.isEmpty() || + filter.regex.equals(".*")) { + + // Only check for presence + if (!event.has(filter.name)) { + return false; + } + } else { + JsonElement field = event.get(filter.name); + if (field == null) { + return false; + } + + String fieldValue = field.getAsString(); + if (!fieldValue.matches(filter.regex)) { + 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 synchronized boolean accept(String json) throws IllegalArgumentException { + 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 getRules() { + return rules; + } + + public synchronized void setRules(List rulesFilters) { + this.rules = rulesFilters; + } + + public synchronized void deleteRules(String name) { + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name)) { + this.rules.remove(rule); + } + } + } + + public List getRules(String name) { + ArrayList temp = new ArrayList<>(); + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name)) { + temp.add(rule); + } + } + return temp; + } + + public synchronized void deleteRule(String name, String regex) { + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name) && rule.regex.equals(regex)) { + this.rules.remove(rule); + } + } + } + + public synchronized void addRule(String name, String regex) { + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name) && rule.regex.equals(regex)) { + return; + } + } + + this.rules.add(new FilterRule(name,regex)); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("JsonProtocolFilter [rules=").append(rules).append("]"); + return builder.toString(); + } + +} diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java new file mode 100644 index 00000000..8e7dec0b --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java @@ -0,0 +1,683 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.protocol.coders; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomCoder; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +/** + * Protocol Coding/Decoding Toolset + */ +public abstract class ProtocolCoderToolset { + + /** + * Logger + */ + private static Logger logger = LoggerFactory.getLogger(ProtocolCoderToolset.class); + + /** + * topic + */ + protected final String topic; + + /** + * controller id + */ + protected final String controllerId; + + /** + * group id + */ + protected final String groupId; + + /** + * artifact id + */ + protected final String artifactId; + + /** + * Protocols and associated Filters + */ + protected final List coders = new ArrayList(); + + /** + * Tree model (instead of class model) generic parsing to be able to inspect elements + */ + protected JsonParser filteringParser = new JsonParser(); + + /** + * custom coder + */ + protected CustomCoder customCoder; + + /** + * Constructor + * + * @param topic the topic + * @param controllerId the controller id + * @param codedClass the decoded class + * @param filters list of filters that apply to the + * selection of this decodedClass in case of multiplicity + * @throws IllegalArgumentException if invalid data has been passed in + */ + public ProtocolCoderToolset(String topic, + String controllerId, + String groupId, + String artifactId, + String codedClass, + JsonProtocolFilter filters, + CustomCoder customCoder, + int modelClassLoaderHash) + throws IllegalArgumentException { + + if (topic == null || controllerId == null || + groupId == null || artifactId == null || + codedClass == null || filters == null || + topic.isEmpty() || controllerId.isEmpty()) { + // TODO + throw new IllegalArgumentException("Invalid input"); + } + + this.topic = topic; + this.controllerId = controllerId; + this.groupId = groupId; + this.artifactId = artifactId; + this.coders.add(new CoderFilters(codedClass, filters, modelClassLoaderHash)); + this.customCoder = customCoder; + } + + /** + * gets the coder + filters associated with this class name + * + * @param classname class name + * @return the decoder filters or null if not found + */ + public CoderFilters getCoder(String classname) { + for (CoderFilters decoder: this.coders) { + if (decoder.factClass.equals(classname)) { + return decoder; + } + } + return null; + } + + /** + * get all coder filters in use + * + * @return coder filters + */ + public List getCoders() { + return this.coders; + } + + /** + * add coder or replace it exists + * + * @param eventClass decoder + * @param filter filter + */ + public void addCoder(String eventClass, JsonProtocolFilter filter, int modelClassLoaderHash) { + synchronized(this) { + for (CoderFilters coder: this.coders) { + if (coder.factClass.equals(eventClass)) { + // this is a better check than checking pointers, just + // in case classloader is different and this is just an update + coder.factClass = eventClass; + coder.filter = filter; + coder.modelClassLoaderHash = modelClassLoaderHash; + return; + } + } + } + + this.coders.add(new CoderFilters(eventClass, filter, modelClassLoaderHash)); + } + + /** + * remove coder + * + * @param eventClass decoder + * @param filter filter + */ + public void removeCoders(String eventClass) { + synchronized(this) { + Iterator codersIt = this.coders.iterator(); + while (codersIt.hasNext()) { + CoderFilters coder = codersIt.next(); + if (coder.factClass.equals(eventClass)) { + codersIt.remove(); + } + } + } + } + + /** + * gets the topic + * + * @return the topic + */ + public String getTopic() {return topic;} + + /** + * gets the controller id + * + * @return the controller id + */ + public String getControllerId() {return controllerId;} + + /** + * @return the groupId + */ + public String getGroupId() { + return groupId; + } + + /** + * @return the artifactId + */ + public String getArtifactId() { + return artifactId; + } + + /** + * @return the customCoder + */ + public CustomCoder getCustomCoder() { + return customCoder; + } + + /** + * @param customCoder the customCoder to set + */ + public void setCustomCoder(CustomCoder customCoder) { + this.customCoder = customCoder; + } + + /** + * performs filtering on a json string + * + * @param json json string + * @return the decoder that passes the filter, otherwise null + * @throws UnsupportedOperationException can't filter + * @throws IllegalArgumentException invalid input + */ + protected CoderFilters filter(String json) + throws UnsupportedOperationException, IllegalArgumentException, IllegalStateException { + + + // 1. Get list of decoding classes for this controller Id and topic + // 2. If there are no classes, return error + // 3. Otherwise, from the available classes for decoding, pick the first one that + // passes the filters + + // Don't parse if it is not necessary + + if (this.coders.isEmpty()) { + // TODO this is an error + throw new IllegalStateException("No coders available"); + } + + if (this.coders.size() == 1) { + JsonProtocolFilter filter = this.coders.get(0).getFilter(); + if (!filter.isRules()) { + return this.coders.get(0); + } + } + + JsonElement event; + try { + event = this.filteringParser.parse(json); + } catch (Exception e) { + throw new UnsupportedOperationException(e); + } + + for (CoderFilters decoder: this.coders) { + try { + boolean accepted = decoder.getFilter().accept(event); + if (accepted) { + return decoder; + } + } catch (Exception e) { + logger.info("{}: unexpected failure accepting {} because of {}", + this, event, e.getMessage(), e); + // continue + } + } + + return null; + } + + /** + * Decode json into a POJO object + * @param json json string + * + * @return a POJO object for the json string + * @throws IllegalArgumentException if an invalid parameter has been received + * @throws UnsupportedOperationException if parsing into POJO is not possible + */ + public abstract Object decode(String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException; + + /** + * Encodes a POJO object into a JSON String + * + * @param event JSON POJO event to be converted to String + * @return JSON string version of POJO object + * @throws IllegalArgumentException if an invalid parameter has been received + * @throws UnsupportedOperationException if parsing into POJO is not possible + */ + public abstract String encode(Object event) + throws IllegalArgumentException, UnsupportedOperationException; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("ProtocolCoderToolset [topic=").append(topic).append(", controllerId=").append(controllerId) + .append(", groupId=").append(groupId).append(", artifactId=").append(artifactId).append(", coders=") + .append(coders).append(", filteringParser=").append(filteringParser).append(", customCoder=") + .append(customCoder).append("]"); + return builder.toString(); + } +} + +/** + * Tools used for encoding/decoding using Jackson + */ +class JacksonProtocolCoderToolset extends ProtocolCoderToolset { + private static Logger logger = LoggerFactory.getLogger(JacksonProtocolCoderToolset.class); + /** + * decoder + */ + @JsonIgnore + protected final ObjectMapper decoder = new ObjectMapper(); + + /** + * encoder + */ + @JsonIgnore + protected final ObjectMapper encoder = new ObjectMapper(); + + /** + * Toolset to encode/decode tools associated with a topic + * + * @param topic topic + * @param decodedClass decoded class of an event + * @param filter + */ + public JacksonProtocolCoderToolset(String topic, String controllerId, + String groupId, String artifactId, + String decodedClass, + JsonProtocolFilter filter, + CustomJacksonCoder customJacksonCoder, + int modelClassLoaderHash) { + super(topic, controllerId, groupId, artifactId, decodedClass, filter, customJacksonCoder, modelClassLoaderHash); + decoder.registerModule(new JavaTimeModule()); + decoder.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, + false); + } + + /** + * gets the Jackson decoder + * + * @return the Jackson decoder + */ + @JsonIgnore + protected ObjectMapper getDecoder() {return decoder;} + + /** + * gets the Jackson encoder + * + * @return the Jackson encoder + */ + @JsonIgnore + protected ObjectMapper getEncoder() {return encoder;} + + /** + * {@inheritDoc} + */ + @Override + public Object decode(String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + + // 0. Use custom coder if available + + if (this.customCoder != null) { + throw new UnsupportedOperationException + ("Jackon Custom Decoder is not supported at this time"); + } + + DroolsController droolsController = + DroolsController.factory.get(groupId, artifactId, ""); + if (droolsController == null) { + logger.warn("{}: no drools-controller to process {}", this, json); + throw new IllegalStateException("no drools-controller to process event"); + } + + CoderFilters decoderFilter = filter(json); + if (decoderFilter == null) { + logger.debug("{}: no decoder to process {}", this, json); + throw new UnsupportedOperationException("no decoder to process event"); + } + + Class decoderClass; + try { + decoderClass = + droolsController.fetchModelClass(decoderFilter.getCodedClass()); + if (decoderClass == null) { + logger.warn("{}: cannot fetch application class {}", this, decoderFilter.getCodedClass()); + throw new IllegalStateException("cannot fetch application class " + decoderFilter.getCodedClass()); + } + } catch (Exception e) { + logger.warn("{}: cannot fetch application class {} because of {}", this, + decoderFilter.getCodedClass(), e.getMessage()); + throw new UnsupportedOperationException("cannot fetch application class " + decoderFilter.getCodedClass(), e); + } + + + try { + Object fact = this.decoder.readValue(json, decoderClass); + return fact; + } catch (Exception e) { + logger.warn("{} cannot decode {} into {} because of {}", + this, json, decoderClass.getName(), e.getMessage(), e); + throw new UnsupportedOperationException("cannont decode into " + decoderFilter.getCodedClass(), e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String encode(Object event) + throws IllegalArgumentException, UnsupportedOperationException { + + // 0. Use custom coder if available + + if (this.customCoder != null) { + throw new UnsupportedOperationException + ("Jackon Custom Encoder is not supported at this time"); + } + + try { + String encodedEvent = this.encoder.writeValueAsString(event); + return encodedEvent; + } catch (JsonProcessingException e) { + logger.error("{} cannot encode {} because of {}", this, event, e.getMessage(), e); + throw new UnsupportedOperationException("event cannot be encoded"); + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("JacksonProtocolCoderToolset [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + +} + +/** + * Tools used for encoding/decoding using Jackson + */ +class GsonProtocolCoderToolset extends ProtocolCoderToolset { + + /** + * Logger + */ + private static Logger logger = LoggerFactory.getLogger(GsonProtocolCoderToolset.class); + + /** + * Formatter for JSON encoding/decoding + */ + @JsonIgnore + public static DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSxxx"); + + @JsonIgnore + public static DateTimeFormatter zuluFormat = DateTimeFormatter.ISO_INSTANT; + + /** + * Adapter for ZonedDateTime + */ + + public static class GsonUTCAdapter implements JsonSerializer, JsonDeserializer { + + public ZonedDateTime deserialize(JsonElement element, Type type, JsonDeserializationContext context) + throws JsonParseException { + try { + return ZonedDateTime.parse(element.getAsString(), format); + } catch (Exception e) { + logger.info("GsonUTCAdapter: cannot parse {} because of {}", + element, e.getMessage(), e); + } + return null; + } + + public JsonElement serialize(ZonedDateTime datetime, Type type, JsonSerializationContext context) { + return new JsonPrimitive(datetime.format(format)); + } + } + + public static class GsonInstantAdapter implements JsonSerializer, JsonDeserializer { + + @Override + public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return Instant.ofEpochMilli(json.getAsLong()); + } + + @Override + public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.toEpochMilli()); + } + + } + + + /** + * decoder + */ + @JsonIgnore + protected final Gson decoder = new GsonBuilder().disableHtmlEscaping(). + registerTypeAdapter(ZonedDateTime.class, new GsonUTCAdapter()). + create(); + + /** + * encoder + */ + @JsonIgnore + protected final Gson encoder = new GsonBuilder().disableHtmlEscaping(). + registerTypeAdapter(ZonedDateTime.class, new GsonUTCAdapter()). + create(); + + /** + * Toolset to encode/decode tools associated with a topic + * + * @param topic topic + * @param decodedClass decoded class of an event + * @param filter + */ + public GsonProtocolCoderToolset(String topic, String controllerId, + String groupId, String artifactId, + String decodedClass, + JsonProtocolFilter filter, + CustomGsonCoder customGsonCoder, + int modelClassLoaderHash) { + super(topic, controllerId, groupId, artifactId, decodedClass, filter, customGsonCoder, modelClassLoaderHash); + } + + /** + * gets the Gson decoder + * + * @return the Gson decoder + */ + @JsonIgnore + protected Gson getDecoder() {return decoder;} + + /** + * gets the Gson encoder + * + * @return the Gson encoder + */ + @JsonIgnore + protected Gson getEncoder() {return encoder;} + + /** + * {@inheritDoc} + */ + @Override + public Object decode(String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + + DroolsController droolsController = + DroolsController.factory.get(groupId, artifactId, ""); + if (droolsController == null) { + logger.warn("{}: no drools-controller to process {}", this, json); + throw new IllegalStateException("no drools-controller to process event"); + } + + CoderFilters decoderFilter = filter(json); + if (decoderFilter == null) { + logger.debug("{}: no decoder to process {}", this, json); + throw new UnsupportedOperationException("no decoder to process event"); + } + + Class decoderClass; + try { + decoderClass = + droolsController.fetchModelClass(decoderFilter.getCodedClass()); + if (decoderClass == null) { + logger.warn("{}: cannot fetch application class {}", this, decoderFilter.getCodedClass()); + throw new IllegalStateException("cannot fetch application class " + decoderFilter.getCodedClass()); + } + } catch (Exception e) { + logger.warn("{}: cannot fetch application class {} because of {}", this, + decoderFilter.getCodedClass(), e.getMessage()); + throw new UnsupportedOperationException("cannot fetch application class " + decoderFilter.getCodedClass(), e); + } + + if (this.customCoder != null) { + try { + Class gsonClassContainer = + droolsController.fetchModelClass(this.customCoder.getClassContainer()); + Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField); + Object gsonObject = gsonField.get(null); + Method fromJsonMethod = gsonObject.getClass(). + getDeclaredMethod + ("fromJson", new Class[]{String.class, Class.class}); + Object fact = fromJsonMethod.invoke(gsonObject, json, decoderClass); + return fact; + } catch (Exception e) { + logger.warn("{}: cannot fetch application class {} because of {}", this, + decoderFilter.getCodedClass(), e.getMessage()); + throw new UnsupportedOperationException("cannot fetch application class " + decoderFilter.getCodedClass(), e); + } + } else { + try { + Object fact = this.decoder.fromJson(json, decoderClass); + return fact; + } catch (Exception e) { + logger.warn("{} cannot decode {} into {} because of {}", + this, json, decoderClass.getName(), e.getMessage(), e); + throw new UnsupportedOperationException("cannont decode into " + decoderFilter.getCodedClass(), e); + } + } + } + + + + /** + * {@inheritDoc} + */ + @Override + public String encode(Object event) + throws IllegalArgumentException, UnsupportedOperationException { + + DroolsController droolsController = + DroolsController.factory.get(groupId, artifactId, null); + if (droolsController == null) { + logger.info("{}: no drools-controller to process {} (continue)", this, event); + throw new IllegalStateException("custom-coder but no drools-controller"); + } + + if (this.customCoder != null) { + try { + Class gsonClassContainer = + droolsController.fetchModelClass(this.customCoder.getClassContainer()); + Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField); + Object gsonObject = gsonField.get(null); + Method toJsonMethod = gsonObject.getClass(). + getDeclaredMethod + ("toJson", new Class[]{Object.class}); + String encodedJson = (String) toJsonMethod.invoke(gsonObject, event); + return encodedJson; + } catch (Exception e) { + logger.warn("{} cannot custom-encode {} because of {}", this, event, e.getMessage(), e); + throw new UnsupportedOperationException("event cannot be encoded", e); + } + } else { + try { + String encodedEvent = this.encoder.toJson(event); + return encodedEvent; + } catch (Exception e) { + logger.warn("{} cannot encode {} because of {}", this, event, e.getMessage(), e); + throw new UnsupportedOperationException("event cannot be encoded", e); + } + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("GsonProtocolCoderToolset [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } +} diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java new file mode 100644 index 00000000..93737267 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java @@ -0,0 +1,309 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.protocol.coders; + +import java.util.List; + +public class TopicCoderFilterConfiguration { + + /** + * Custom coder, contains class and static field to access parser that the controller + * desires to use instead of the framework provided parser + */ + public static abstract class CustomCoder { + protected String className; + protected String staticCoderField; + + /** + * create custom coder from raw string in the following format + * (typically embedded in a property file): + * + * Note this is to support decoding/encoding of partial structures that are + * only known by the model. + * + * @param rawCustomCoder with format: , + */ + public CustomCoder(String rawCustomCoder) throws IllegalArgumentException { + if (rawCustomCoder != null && !rawCustomCoder.isEmpty()) { + + this.className = rawCustomCoder.substring(0,rawCustomCoder.indexOf(",")); + if (this.className == null || this.className.isEmpty()) { + throw new IllegalArgumentException("No classname to create CustomCoder cannot be created"); + } + + this.staticCoderField = rawCustomCoder.substring(rawCustomCoder.indexOf(",")+1); + if (this.staticCoderField == null || this.staticCoderField.isEmpty()) { + throw new IllegalArgumentException + ("No staticCoderField to create CustomCoder cannot be created for class " + + className); + } + + } + } + /** + * @param classContainer + * @param staticCoderField + */ + public CustomCoder(String className, String staticCoderField) throws IllegalArgumentException { + if (className == null || className.isEmpty()) { + throw new IllegalArgumentException("No classname to create CustomCoder cannot be created"); + } + + if (staticCoderField == null || staticCoderField.isEmpty()) { + throw new IllegalArgumentException + ("No staticCoderField to create CustomCoder cannot be created for class " + + className); + } + + this.className = className; + this.staticCoderField = staticCoderField; + } + + /** + * @return the className + */ + public String getClassContainer() { + return className; + } + + /** + * @param className the className to set + */ + public void setClassContainer(String className) { + this.className = className; + } + + /** + * @return the staticCoderField + */ + public String getStaticCoderField() { + return staticCoderField; + } + + /** + * @param staticCoderField the staticGson to set + */ + public void setStaticCoderField(String staticCoderField) { + this.staticCoderField = staticCoderField; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CustomCoder [className=").append(className).append(", staticCoderField=") + .append(staticCoderField).append("]"); + return builder.toString(); + } + } + + public static class CustomGsonCoder extends CustomCoder { + + public CustomGsonCoder(String className, String staticCoderField) { + super(className, staticCoderField); + } + + public CustomGsonCoder(String customGson) throws IllegalArgumentException { + super(customGson); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CustomGsonCoder [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + + } + + public static class CustomJacksonCoder extends CustomCoder { + + public CustomJacksonCoder(String className, String staticCoderField) { + super(className, staticCoderField); + } + + public CustomJacksonCoder(String customJackson) throws IllegalArgumentException { + super(customJackson); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CustomJacksonCoder [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + + } + + /** + * Coder/Decoder class and Filter container. The decoder class is potential, + * in order to be operational needs to be fetched from an available + * class loader. + * + */ + public static class PotentialCoderFilter { + + /** + * decoder class (pending from being able to be fetched and found + * in some class loader) + */ + protected String codedClass; + + /** + * filters to apply to the selection of the decodedClass; + */ + protected JsonProtocolFilter filter; + + /** + * constructor + * + * @param codedClass decoder class + * @param filter filters to apply + */ + public PotentialCoderFilter(String codedClass, JsonProtocolFilter filter) { + this.codedClass = codedClass; + this.filter = filter; + } + + /** + * @return the decodedClass + */ + public String getCodedClass() { + return codedClass; + } + + /** + * @param decodedClass the decodedClass to set + */ + public void setCodedClass(String decodedClass) { + this.codedClass = decodedClass; + } + + /** + * @return the filter + */ + public JsonProtocolFilter getFilter() { + return filter; + } + + /** + * @param filter the filter to set + */ + public void setFilter(JsonProtocolFilter filter) { + this.filter = filter; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("PotentialCoderFilter [codedClass=").append(codedClass).append(", filter=").append(filter) + .append("]"); + return builder.toString(); + } + } + + /** + * the source topic + */ + protected final String topic; + + /** + * List of decoder -> filters + */ + protected final List coderFilters; + + /** + * custom gson coder that this controller prefers to use instead of the framework ones + */ + protected CustomGsonCoder customGsonCoder; + + /** + * custom jackson coder that this controller prefers to use instead of the framework ones + */ + protected CustomJacksonCoder customJacksonCoder; + + /** + * Constructor + * + * @param decoderFilters list of decoders and associated filters + * @param topic the topic + */ + public TopicCoderFilterConfiguration(String topic, List decoderFilters, + CustomGsonCoder customGsonCoder, + CustomJacksonCoder customJacksonCoder) { + this.coderFilters = decoderFilters; + this.topic = topic; + this.customGsonCoder = customGsonCoder; + this.customJacksonCoder = customJacksonCoder; + } + + /** + * @return the topic + */ + public String getTopic() { + return topic; + } + + /** + * @return the decoderFilters + */ + public List getCoderFilters() { + return coderFilters; + } + + /** + * @return the customGsonCoder + */ + public CustomGsonCoder getCustomGsonCoder() { + return customGsonCoder; + } + + /** + * @param customGsonCoder the customGsonCoder to set + */ + public void setCustomGsonCoder(CustomGsonCoder customGsonCoder) { + this.customGsonCoder = customGsonCoder; + } + + /** + * @return the customJacksonCoder + */ + public CustomJacksonCoder getCustomJacksonCoder() { + return customJacksonCoder; + } + + /** + * @param customJacksonCoder the customJacksonCoder to set + */ + public void setCustomJacksonCoder(CustomJacksonCoder customJacksonCoder) { + this.customJacksonCoder = customJacksonCoder; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("TopicCoderFilterConfiguration [topic=").append(topic).append(", coderFilters=") + .append(coderFilters).append(", customGsonCoder=").append(customGsonCoder) + .append(", customJacksonCoder=").append(customJacksonCoder).append("]"); + return builder.toString(); + } + + +} diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/ControllerConfiguration.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/ControllerConfiguration.java new file mode 100644 index 00000000..ded7a52c --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/ControllerConfiguration.java @@ -0,0 +1,280 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.protocol.configuration; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + +/** + * Drools Related Information + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ControllerConfiguration { + + public static final String CONFIG_CONTROLLER_OPERATION_CREATE = "create"; + public static final String CONFIG_CONTROLLER_OPERATION_UPDATE = "update"; + public static final String CONFIG_CONTROLLER_OPERATION_LOCK = "lock"; + public static final String CONFIG_CONTROLLER_OPERATION_UNLOCK = "unlock"; + + /** + * + * (Required) + * + */ + @JsonProperty("name") + private String name; + /** + * Set of operations that can be applied to a controller: create, lock + * (Required) + * + */ + @JsonProperty("operation") + private String operation; + /** + * Maven Related Information + * + */ + @JsonProperty("drools") + private DroolsConfiguration drools; + @JsonIgnore + private Map additionalProperties = new HashMap(); + protected final static Object NOT_FOUND_VALUE = new Object(); + + /** + * No args constructor for use in serialization + * + */ + public ControllerConfiguration() { + } + + /** + * + * @param name + * @param drools + * @param operation + */ + public ControllerConfiguration(String name, String operation, DroolsConfiguration drools) { + this.name = name; + this.operation = operation; + this.drools = drools; + } + + /** + * + * (Required) + * + * @return + * The name + */ + @JsonProperty("name") + public String getName() { + return name; + } + + /** + * + * (Required) + * + * @param name + * The name + */ + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + public ControllerConfiguration withName(String name) { + this.name = name; + return this; + } + + /** + * Set of operations that can be applied to a controller: create, lock + * (Required) + * + * @return + * The operation + */ + @JsonProperty("operation") + public String getOperation() { + return operation; + } + + /** + * Set of operations that can be applied to a controller: create, lock + * (Required) + * + * @param operation + * The operation + */ + @JsonProperty("operation") + public void setOperation(String operation) { + this.operation = operation; + } + + public ControllerConfiguration withOperation(String operation) { + this.operation = operation; + return this; + } + + /** + * Maven Related Information + * + * @return + * The drools + */ + @JsonProperty("drools") + public DroolsConfiguration getDrools() { + return drools; + } + + /** + * Maven Related Information + * + * @param drools + * The drools + */ + @JsonProperty("drools") + public void setDrools(DroolsConfiguration drools) { + this.drools = drools; + } + + public ControllerConfiguration withDrools(DroolsConfiguration drools) { + this.drools = drools; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public ControllerConfiguration withAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + return this; + } + + protected boolean declaredProperty(String name, Object value) { + switch (name) { + case "name": + if (value instanceof String) { + setName(((String) value)); + } else { + throw new IllegalArgumentException(("property \"name\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "operation": + if (value instanceof String) { + setOperation(((String) value)); + } else { + throw new IllegalArgumentException(("property \"operation\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "drools": + if (value instanceof DroolsConfiguration) { + setDrools(((DroolsConfiguration) value)); + } else { + throw new IllegalArgumentException(("property \"drools\" is of type \"org.onap.policy.drools.protocol.configuration.Drools\", but got "+ value.getClass().toString())); + } + return true; + default: + return false; + } + } + + protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { + switch (name) { + case "name": + return getName(); + case "operation": + return getOperation(); + case "drools": + return getDrools(); + default: + return notFoundValue; + } + } + + @SuppressWarnings({ + "unchecked" + }) + publicT get(String name) { + Object value = declaredPropertyOrNotFound(name, ControllerConfiguration.NOT_FOUND_VALUE); + if (ControllerConfiguration.NOT_FOUND_VALUE!= value) { + return ((T) value); + } else { + return ((T) getAdditionalProperties().get(name)); + } + } + + public void set(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + } + + public ControllerConfiguration with(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + return this; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(name).append(operation).append(drools).append(additionalProperties).toHashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof ControllerConfiguration) == false) { + return false; + } + ControllerConfiguration rhs = ((ControllerConfiguration) other); + return new EqualsBuilder().append(name, rhs.name).append(operation, rhs.operation).append(drools, rhs.drools).append(additionalProperties, rhs.additionalProperties).isEquals(); + } + +} diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/DroolsConfiguration.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/DroolsConfiguration.java new file mode 100644 index 00000000..5f32d7a4 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/DroolsConfiguration.java @@ -0,0 +1,278 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.protocol.configuration; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + +/** + * Maven Related Information + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DroolsConfiguration { + + /** + * Maven Artifact ID + * (Required) + * + */ + @JsonProperty("artifactId") + private String artifactId; + /** + * Maven Group ID + * (Required) + * + */ + @JsonProperty("groupId") + private String groupId; + /** + * Maven Version + * (Required) + * + */ + @JsonProperty("version") + private String version; + @JsonIgnore + private Map additionalProperties = new HashMap(); + protected final static Object NOT_FOUND_VALUE = new Object(); + + /** + * No args constructor for use in serialization + * + */ + public DroolsConfiguration() { + } + + /** + * + * @param groupId + * @param artifactId + * @param version + */ + public DroolsConfiguration(String artifactId, String groupId, String version) { + this.artifactId = artifactId; + this.groupId = groupId; + this.version = version; + } + + /** + * Maven Artifact ID + * (Required) + * + * @return + * The artifactId + */ + @JsonProperty("artifactId") + public String getArtifactId() { + return artifactId; + } + + /** + * Maven Artifact ID + * (Required) + * + * @param artifactId + * The artifactId + */ + @JsonProperty("artifactId") + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public DroolsConfiguration withArtifactId(String artifactId) { + this.artifactId = artifactId; + return this; + } + + /** + * Maven Group ID + * (Required) + * + * @return + * The groupId + */ + @JsonProperty("groupId") + public String getGroupId() { + return groupId; + } + + /** + * Maven Group ID + * (Required) + * + * @param groupId + * The groupId + */ + @JsonProperty("groupId") + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public DroolsConfiguration withGroupId(String groupId) { + this.groupId = groupId; + return this; + } + + /** + * Maven Version + * (Required) + * + * @return + * The version + */ + @JsonProperty("version") + public String getVersion() { + return version; + } + + /** + * Maven Version + * (Required) + * + * @param version + * The version + */ + @JsonProperty("version") + public void setVersion(String version) { + this.version = version; + } + + public DroolsConfiguration withVersion(String version) { + this.version = version; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public DroolsConfiguration withAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + return this; + } + + protected boolean declaredProperty(String name, Object value) { + switch (name) { + case "artifactId": + if (value instanceof String) { + setArtifactId(((String) value)); + } else { + throw new IllegalArgumentException(("property \"artifactId\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "groupId": + if (value instanceof String) { + setGroupId(((String) value)); + } else { + throw new IllegalArgumentException(("property \"groupId\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "version": + if (value instanceof String) { + setVersion(((String) value)); + } else { + throw new IllegalArgumentException(("property \"version\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + default: + return false; + } + } + + protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { + switch (name) { + case "artifactId": + return getArtifactId(); + case "groupId": + return getGroupId(); + case "version": + return getVersion(); + default: + return notFoundValue; + } + } + + @SuppressWarnings({ + "unchecked" + }) + publicT get(String name) { + Object value = declaredPropertyOrNotFound(name, DroolsConfiguration.NOT_FOUND_VALUE); + if (DroolsConfiguration.NOT_FOUND_VALUE!= value) { + return ((T) value); + } else { + return ((T) getAdditionalProperties().get(name)); + } + } + + public void set(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + } + + public DroolsConfiguration with(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + return this; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(artifactId).append(groupId).append(version).append(additionalProperties).toHashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof DroolsConfiguration) == false) { + return false; + } + DroolsConfiguration rhs = ((DroolsConfiguration) other); + return new EqualsBuilder().append(artifactId, rhs.artifactId).append(groupId, rhs.groupId).append(version, rhs.version).append(additionalProperties, rhs.additionalProperties).isEquals(); + } + +} diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java new file mode 100644 index 00000000..d7295fd4 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java @@ -0,0 +1,283 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.protocol.configuration; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + + +/** + * ENGINE-CONFIGURATION + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class PdpdConfiguration { + + /** + * Controller Entity ID + */ + public static final String CONFIG_ENTITY_CONTROLLER = "controller"; + + /** + * Unique Transaction ID. This is an UUID. + * (Required) + * + */ + @JsonProperty("requestID") + private String requestID; + /** + * Set of entities on which configuration can be performed: controller + * (Required) + * + */ + @JsonProperty("entity") + private String entity; + /** + * Controller Information, only applicable when the entity is set to controller + * + */ + @JsonProperty("controllers") + private List controllers = new ArrayList(); + @JsonIgnore + private Map additionalProperties = new HashMap(); + protected final static Object NOT_FOUND_VALUE = new Object(); + + /** + * No args constructor for use in serialization + * + */ + public PdpdConfiguration() { + } + + /** + * + * @param controller + * @param requestID + * @param entity + */ + public PdpdConfiguration(String requestID, String entity, List controllers) { + this.requestID = requestID; + this.entity = entity; + this.controllers = controllers; + } + + /** + * Unique Transaction ID. This is an UUID. + * (Required) + * + * @return + * The requestID + */ + @JsonProperty("requestID") + public String getRequestID() { + return requestID; + } + + /** + * Unique Transaction ID. This is an UUID. + * (Required) + * + * @param requestID + * The requestID + */ + @JsonProperty("requestID") + public void setRequestID(String requestID) { + this.requestID = requestID; + } + + public PdpdConfiguration withRequestID(String requestID) { + this.requestID = requestID; + return this; + } + + /** + * Set of entities on which configuration can be performed: controller + * (Required) + * + * @return + * The entity + */ + @JsonProperty("entity") + public String getEntity() { + return entity; + } + + /** + * Set of entities on which configuration can be performed: controller + * (Required) + * + * @param entity + * The entity + */ + @JsonProperty("entity") + public void setEntity(String entity) { + this.entity = entity; + } + + public PdpdConfiguration withEntity(String entity) { + this.entity = entity; + return this; + } + + /** + * Controller Information, only applicable when the entity is set to controller + * + * @return + * The controller + */ + @JsonProperty("controller") + public List getControllers() { + return controllers; + } + + /** + * Controller Information, only applicable when the entity is set to controller + * + * @param controller + * The controller + */ + @JsonProperty("controller") + public void setControllers(List controllers) { + this.controllers = controllers; + } + + public PdpdConfiguration withController(List controllers) { + this.controllers = controllers; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public PdpdConfiguration withAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + return this; + } + + @SuppressWarnings("unchecked") + protected boolean declaredProperty(String name, Object value) { + switch (name) { + case "requestID": + if (value instanceof String) { + setRequestID(((String) value)); + } else { + throw new IllegalArgumentException(("property \"requestID\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "entity": + if (value instanceof String) { + setEntity(((String) value)); + } else { + throw new IllegalArgumentException(("property \"entity\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "controllers": + if (value instanceof List) { + setControllers(((List ) value)); + } else { + throw new IllegalArgumentException(("property \"controllers\" is of type \"java.util.List\", but got "+ value.getClass().toString())); + } + return true; + default: + return false; + } + } + + protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { + switch (name) { + case "requestID": + return getRequestID(); + case "entity": + return getEntity(); + case "controllers": + return getControllers(); + default: + return notFoundValue; + } + } + + @SuppressWarnings({ + "unchecked" + }) + publicT get(String name) { + Object value = declaredPropertyOrNotFound(name, PdpdConfiguration.NOT_FOUND_VALUE); + if (PdpdConfiguration.NOT_FOUND_VALUE!= value) { + return ((T) value); + } else { + return ((T) getAdditionalProperties().get(name)); + } + } + + public void set(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + } + + public PdpdConfiguration with(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + return this; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(requestID).append(entity).append(controllers).append(additionalProperties).toHashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof PdpdConfiguration) == false) { + return false; + } + PdpdConfiguration rhs = ((PdpdConfiguration) other); + return new EqualsBuilder().append(requestID, rhs.requestID).append(entity, rhs.entity).append(controllers, rhs.controllers).append(additionalProperties, rhs.additionalProperties).isEquals(); + } + +} diff --git a/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java b/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java new file mode 100644 index 00000000..4f5e33e7 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java @@ -0,0 +1,2335 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.server.restful; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; +import java.util.regex.Pattern; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.event.comm.TopicEndpoint; +import org.onap.policy.drools.event.comm.TopicSink; +import org.onap.policy.drools.event.comm.TopicSource; +import org.onap.policy.drools.event.comm.bus.DmaapTopicSink; +import org.onap.policy.drools.event.comm.bus.DmaapTopicSource; +import org.onap.policy.drools.event.comm.bus.UebTopicSink; +import org.onap.policy.drools.event.comm.bus.UebTopicSource; +import org.onap.policy.drools.features.PolicyControllerFeatureAPI; +import org.onap.policy.drools.features.PolicyEngineFeatureAPI; +import org.onap.policy.drools.properties.PolicyProperties; +import org.onap.policy.drools.protocol.coders.EventProtocolCoder; +import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; +import org.onap.policy.drools.protocol.coders.JsonProtocolFilter; +import org.onap.policy.drools.protocol.coders.JsonProtocolFilter.FilterRule; +import org.onap.policy.drools.protocol.coders.ProtocolCoderToolset; +import org.onap.policy.drools.protocol.configuration.ControllerConfiguration; +import org.onap.policy.drools.protocol.configuration.PdpdConfiguration; +import org.onap.policy.drools.system.PolicyController; +import org.onap.policy.drools.system.PolicyEngine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Info; +import io.swagger.annotations.SwaggerDefinition; +import io.swagger.annotations.Tag; + + +/** + * Telemetry JAX-RS Interface to the PDP-D + */ + +@Path("/policy/pdp") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +@Api +@SwaggerDefinition( + info = @Info( + description = "PDP-D Telemetry Services", + version = "v1.0", + title = "PDP-D Telemetry" + ), + consumes = {MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN}, + produces = {MediaType.APPLICATION_JSON}, + schemes = {SwaggerDefinition.Scheme.HTTP}, + tags = { + @Tag(name = "pdp-d-telemetry", description = "Drools PDP Telemetry Operations") + } +) +public class RestManager { + /** + * Logger + */ + private static Logger logger = LoggerFactory.getLogger(RestManager.class); + + @GET + @Path("engine") + @ApiOperation( + value="Retrieves the Engine Operational Status", + notes="Top-level abstraction. Provides a global view of resources", + response=PolicyEngine.class + ) + public Response engine() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); + } + + @DELETE + @Path("engine") + @ApiOperation( + value="Shuts down the Engine", + notes="Deleting the engine, the top-level abstraction, equivalenty shuts it down", + response=PolicyEngine.class + ) + public Response engineShutdown() { + try { + PolicyEngine.manager.shutdown(); + } catch (IllegalStateException e) { + logger.error("{}: cannot shutdown {} because of {}", this, PolicyEngine.manager, e.getMessage(), e); + return Response.status(Response.Status.BAD_REQUEST). + entity(PolicyEngine.manager). + build(); + } + + return Response.status(Response.Status.OK). + entity(PolicyEngine.manager). + build(); + } + + @GET + @Path("engine/features") + @ApiOperation( + value="Engine Features", + notes="Provides the list of loaded features using the PolicyEngineFeatureAPI", + responseContainer="List" + ) + public Response engineFeatures() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatures()).build(); + } + + @GET + @Path("engine/features/inventory") + @ApiOperation( + value="Engine Detailed Feature Inventory", + notes="Provides detailed list of loaded features using the PolicyEngineFeatureAPI", + responseContainer="List", + response=PolicyEngineFeatureAPI.class + ) + public Response engineFeaturesInventory() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatureProviders()).build(); + } + + @GET + @Path("engine/features/{featureName}") + @ApiOperation( + value="Engine Feature", + notes="Provides Details for a given feature Engine Provider", + response=PolicyEngineFeatureAPI.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message = "The feature cannot be found") + }) + public Response engineFeature(@ApiParam(value="Feature Name", required=true) + @PathParam("featureName") String featureName) { + try { + return Response.status(Response.Status.OK). + entity(PolicyEngine.manager.getFeatureProvider(featureName)).build(); + } catch(IllegalArgumentException iae) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(iae.getMessage())).build(); + } + } + + @GET + @Path("engine/inputs") + @ApiOperation( + value="Engine Input Ports", + notes="List of input ports", + responseContainer="List" + ) + public Response engineInputs() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Inputs.values())). + build(); + } + + @POST + @Path("engine/inputs/configuration") + @ApiOperation( + value="Engine Input Configuration Requests", + notes="Feeds a configuration request input into the Engine" + ) + @ApiResponses(value={ + @ApiResponse(code=406, message = "The configuration request cannot be honored") + }) + public Response engineUpdate( + @ApiParam(value="Configuration to apply", required=true) PdpdConfiguration configuration) { + PolicyController controller = null; + boolean success = true; + try { + success = PolicyEngine.manager.configure(configuration); + } catch (Exception e) { + success = false; + logger.info("{}: cannot configure {} because of {}", this, PolicyEngine.manager, e.getMessage(), e); + } + + if (!success) + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")).build(); + else + return Response.status(Response.Status.OK).entity(controller).build(); + } + + @GET + @Path("engine/properties") + @ApiOperation( + value="Engine Configuration Properties", + notes="Used for booststrapping the engine", + response=Properties.class + ) + public Response engineProperties() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getProperties()).build(); + } + + @GET + @Path("engine/switches") + @ApiOperation( + value="Engine Control Switches", + notes="List of the Engine Control Switches", + responseContainer="List" + ) + public Response engineSwitches() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Switches.values())). + build(); + } + + @PUT + @Path("engine/switches/activation") + @ApiOperation( + value="Switches on the Engine Activation Switch", + notes="Turns on Activation Switch on the Engine. This order entails that the engine " + + "and controllers are unlocked and started", + response=PolicyEngine.class + ) + public Response engineActivation() { + boolean success = true; + try { + PolicyEngine.manager.activate(); + } catch (Exception e) { + success = false; + logger.info("{}: cannot activate {} because of {}", this, PolicyEngine.manager, e.getMessage(), e); + } + + if (!success) + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")).build(); + else + return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); + } + + @DELETE + @Path("engine/switches/activation") + @ApiOperation( + value="Switches off Engine Activation Switch", + notes="Turns off the Activation Switch on the Engine. This order entails that the engine " + + "and controllers are locked (with the exception of those resources defined as unmanaged)", + response=PolicyEngine.class + ) + public Response engineDeactivation() { + boolean success = true; + try { + PolicyEngine.manager.deactivate(); + } catch (Exception e) { + success = false; + logger.info("{}: cannot deactivate {} because of {}", this, PolicyEngine.manager, e.getMessage(), e); + } + + if (!success) + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")).build(); + else + return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); + } + + @PUT + @Path("engine/switches/lock") + @ApiOperation( + value="Switches on the Engine Lock Control", + notes="This switch locks all the engine resources as a whole, except those that are defined unmanaged", + response=PolicyEngine.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response engineLock() { + boolean success = PolicyEngine.manager.lock(); + if (success) + return Response.status(Status.OK). + entity(PolicyEngine.manager). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")). + build(); + } + + @DELETE + @Path("engine/switches/lock") + @ApiOperation( + value="Switches off the Lock control", + notes="This switch locks all the engine resources as a whole, except those that are defined unmanaged", + response=PolicyEngine.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response engineUnlock() { + boolean success = PolicyEngine.manager.unlock(); + if (success) + return Response.status(Status.OK). + entity(PolicyEngine.manager). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")). + build(); + } + + @GET + @Path("engine/controllers") + @ApiOperation( + value="Lists the Policy Controllers Names", + notes="Unique Policy Controller Identifiers", + responseContainer="List" + ) + public Response controllers() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getPolicyControllerIds()).build(); + } + + @GET + @Path("engine/controllers/inventory") + @ApiOperation( + value="Lists the Policy Controllers", + notes="Detailed list of Policy Controllers", + responseContainer="List", + response=PolicyController.class + ) + public Response controllerInventory() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getPolicyControllers()).build(); + } + + @POST + @Path("engine/controllers") + @ApiOperation( + value="Creates and starts a new Policy Controller", + notes="Controller creation based on properties", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=400, message = "Invalid configuration information has been provided"), + @ApiResponse(code=304, message = "The controller already exists"), + @ApiResponse(code=406, message = "The administrative state of the system prevents it " + + "from processing this request"), + @ApiResponse(code=206, message = "The controller has been created " + + "but cannot be started"), + @ApiResponse(code=201, message = "The controller has been succesfully created and started") + }) + public Response controllerAdd(@ApiParam(value="Configuration Properties to apply", required = true) + Properties config) { + if (config == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error("A configuration must be provided")). + build(); + + String controllerName = config.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME); + if (controllerName == null || controllerName.isEmpty()) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error + ("Configuration must have an entry for " + + PolicyProperties.PROPERTY_CONTROLLER_NAME)). + build(); + + PolicyController controller; + try { + controller = PolicyController.factory.get(controllerName); + if (controller != null) + return Response.status(Response.Status.NOT_MODIFIED). + entity(controller). + build(); + } catch (IllegalArgumentException e) { + // This is OK + } catch (IllegalStateException e) { + logger.info("{}: cannot get policy-controller because of {}", this, e.getMessage(), e); + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not found")).build(); + } + + try { + controller = PolicyEngine.manager.createPolicyController + (config.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME), config); + } catch (IllegalArgumentException | IllegalStateException e) { + logger.warn("{}: cannot create policy-controller because of {}", this, e.getMessage(), e); + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(e.getMessage())). + build(); + } + + try { + boolean success = controller.start(); + if (!success) { + logger.info("{}: cannot start {}", this, controller); + return Response.status(Response.Status.PARTIAL_CONTENT). + entity(new Error(controllerName + " can't be started")).build(); + } + } catch (IllegalStateException e) { + logger.info("{}: cannot start {} because of {}", this, controller, e.getMessage(), e);; + return Response.status(Response.Status.PARTIAL_CONTENT). + entity(controller).build(); + } + + return Response.status(Response.Status.CREATED). + entity(controller). + build(); + } + + @GET + @Path("engine/controllers/features") + @ApiOperation( + value="Lists of Feature Providers Identifiers", + notes="Unique Policy Controller Identifiers", + responseContainer="List" + ) + public Response controllerFeatures() { + return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatures()).build(); + } + + @GET + @Path("engine/controllers/features/inventory") + @ApiOperation( + value="Detailed Controllers Feature Inventory", + notes="Provides detailed list of loaded features using the PolicyControllerFeatureAPI", + responseContainer="List", + response=PolicyControllerFeatureAPI.class + ) + public Response controllerFeaturesInventory() { + return Response.status(Response.Status.OK). + entity(PolicyController.factory.getFeatureProviders()). + build(); + } + + @GET + @Path("engine/controllers/features/{featureName}") + @ApiOperation( + value="Controller Feature", + notes="Provides Details for a given Policy Controller feature provider", + response=PolicyControllerFeatureAPI.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message = "The feature cannot be found") + }) + public Response controllerFeature(@ApiParam(value="Feature Name", required=true) + @PathParam("featureName") String featureName) { + try { + return Response.status(Response.Status.OK). + entity(PolicyController.factory.getFeatureProvider(featureName)). + build(); + } catch(IllegalArgumentException iae) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(iae.getMessage())).build(); + } + } + + @GET + @Path("engine/controllers/{controller}") + @ApiOperation( + value="Retrieves a Policy Controller", + notes="A Policy Controller is a concrete drools application abstraction. " + + "It aggregates networking, drools, and other resources," + + "as provides operational controls over drools applications", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response controller(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + try { + return Response.status(Response.Status.OK). + entity(PolicyController.factory.get(controllerName)). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); + } + } + + @DELETE + @Path("engine/controllers/{controller}") + @ApiOperation( + value="Deletes a Policy Controller", + notes="A Policy Controller is a concrete drools application abstraction. " + + "It aggregates networking, drools, and other resources," + + "as provides operational controls over drools applications", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A problem has occurred while deleting the Policy Controller") + }) + public Response controllerDelete(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + + PolicyController controller; + try { + controller = + PolicyController.factory.get(controllerName); + if (controller == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " does not exist")). + build(); + } catch (IllegalArgumentException e) { + logger.info("{}: cannot get policy-controller {} because of {}", this, controllerName, e.getMessage(), e); + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " not found: " + e.getMessage())). + build(); + } catch (IllegalStateException e) { + logger.info("{}: cannot get policy-controller {} because of {}", this, controllerName, e.getMessage(), e); + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")).build(); + } + + try { + PolicyEngine.manager.removePolicyController(controllerName); + } catch (IllegalArgumentException | IllegalStateException e) { + logger.info("{}: cannot remove policy-controller {} because of {}", this, controllerName, e.getMessage(), e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(e.getMessage())). + build(); + } + + return Response.status(Response.Status.OK). + entity(controller). + build(); + } + + @GET + @Path("engine/controllers/{controller}/properties") + @ApiOperation( + value="Retrieves the configuration properties of a Policy Controller", + notes="Configuration resources used by the controller if Properties format", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response controllerProperties(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + try { + PolicyController controller = PolicyController.factory.get(controllerName); + return Response.status(Response.Status.OK). + entity(controller.getProperties()). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/inputs") + @ApiOperation( + value="Policy Controller Input Ports", + notes="List of input ports", + responseContainer="List" + ) + public Response controllerInputs() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Inputs.values())). + build(); + } + + @POST + @Path("engine/controllers/{controller}/inputs/configuration") + @ApiOperation( + value="Policy Controller Input Configuration Requests", + notes="Feeds a configuration request input into the given Policy Controller" + ) + @ApiResponses(value={ + @ApiResponse(code=400, message = "The configuration request is invalid"), + @ApiResponse(code=406, message = "The configuration request cannot be honored") + }) + public Response controllerUpdate(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Configuration to apply", required=true) + ControllerConfiguration controllerConfiguration) { + + if (controllerName == null || controllerName.isEmpty() || + controllerConfiguration == null || + controllerConfiguration.getName().intern() != controllerName) + return Response.status(Response.Status.BAD_REQUEST). + entity("A valid or matching controller names must be provided"). + build(); + + PolicyController controller; + try { + controller = PolicyEngine.manager.updatePolicyController(controllerConfiguration); + if (controller == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " does not exist")). + build(); + } catch (IllegalArgumentException e) { + logger.info("{}: cannot update policy-controller {} because of {}", this, controllerName, e.getMessage(), e); + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " not found: " + e.getMessage())). + build(); + } catch (Exception e) { + logger.info("{}: cannot update policy-controller {} because of {}", this, controllerName, e.getMessage(), e); + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")).build(); + } + + return Response.status(Response.Status.OK). + entity(controller). + build(); + } + + @GET + @Path("engine/controllers/{controller}/switches") + @ApiOperation( + value="Policy Controller Switches", + notes="List of the Policy Controller Switches", + responseContainer="List" + ) + public Response controllerSwitches() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Switches.values())). + build(); + } + + @PUT + @Path("engine/controllers/{controller}/switches/lock") + @ApiOperation( + value="Switches on the Policy Controller Lock Control", + notes="This action on the switch locks the Policy Controller", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response controllerLock(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + PolicyController policyController = PolicyController.factory.get(controllerName); + boolean success = policyController.lock(); + if (success) + return Response.status(Status.OK). + entity(policyController). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("Controller " + controllerName + " cannot be locked")). + build(); + } + + @DELETE + @Path("engine/controllers/{controller}/switches/lock") + @ApiOperation( + value="Switches off the Policy Controller Lock Control", + notes="This action on the switch unlocks the Policy Controller", + response=PolicyController.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response controllerUnlock(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + PolicyController policyController = PolicyController.factory.get(controllerName); + boolean success = policyController.unlock(); + if (success) + return Response.status(Status.OK). + entity(policyController). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("Controller " + controllerName + " cannot be unlocked")). + build(); + } + + @GET + @Path("engine/controllers/{controller}/drools") + @ApiOperation( + value="Retrieves the Drools Controller subcomponent of the Policy Controller", + notes="The Drools Controller provides an abstraction over the Drools subsystem", + response=DroolsController.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response drools(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + try { + DroolsController drools = getDroolsController(controllerName); + return Response.status(Response.Status.OK). + entity(drools). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/drools/facts") + @ApiOperation( + value="Retrieves Facts Summary information for a given controller", + notes="Provides the session names, and a count of fact object in the drools working memory", + responseContainer="Map" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response droolsFacts(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + try { + Map sessionCounts = new HashMap<>(); + DroolsController drools = getDroolsController(controllerName); + for (String session : drools.getSessionNames()) { + sessionCounts.put(session, drools.factCount(session)); + } + return Response.status(Response.Status.OK). + entity(sessionCounts). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/drools/facts/{session}") + @ApiOperation( + value="Retrieves Fact Types (classnames) for a given controller and its count", + notes="The fact types are the classnames of the objects inserted in the drools working memory", + responseContainer="Map" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller or session cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response droolsFacts(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName) { + try { + DroolsController drools = getDroolsController(controllerName); + return Response.status(Response.Status.OK). + entity(drools.factClassNames(sessionName)). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error("entity not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/drools/facts/{session}/{factType}") + @ApiOperation( + value="Retrieves fact objects of a given type in the drools working memory" + + "for a given controller and session", + notes="The fact types are the classnames of the objects inserted in the drools working memory", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, session, or fact type cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response droolsFacts(@ApiParam(value="Fact count", required=false) + @DefaultValue("false") @QueryParam("count") boolean count, + @ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName, + @ApiParam(value="Drools Fact Type", required=true) + @PathParam("factType") String factType) { + try { + DroolsController drools = getDroolsController(controllerName); + List facts = drools.facts(sessionName, factType, false); + if (!count) + return Response.status(Response.Status.OK).entity(facts).build(); + else + return Response.status(Response.Status.OK).entity(facts.size()).build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + sessionName + ":" + factType + + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + ":" + factType + + " not acceptable")). + build(); + } + } + + @DELETE + @Path("engine/controllers/{controller}/drools/facts/{session}/{factType}") + @ApiOperation( + value="Deletes all the fact objects of a given type from the drools working memory" + + "for a given controller and session. The objects retracted from the working " + + "memory are provided in the response.", + notes="The fact types are the classnames of the objects inserted in the drools working memory", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, session, or fact type, cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response droolsFactsDelete(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName, + @ApiParam(value="Drools Fact Type", required=true) + @PathParam("factType") String factType) { + try { + DroolsController drools = getDroolsController(controllerName); + List facts = drools.facts(sessionName, factType, true); + return Response.status(Response.Status.OK).entity(facts).build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + sessionName + ":" + factType + + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + ":" + factType + + " not acceptable")). + build(); + } catch (Exception e) { + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(e.getMessage())). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}") + @ApiOperation( + value="Gets all the fact objects returned by a DRL query with no parameters from the drools working memory" + + "for a given controller and session", + notes="The DRL query must be defined in the DRL file", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, session, or query information, cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response droolsFacts(@ApiParam(value="Fact count", required=false) + @DefaultValue("false") @QueryParam("count") boolean count, + @ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName, + @ApiParam(value="Query Name Present in DRL", required=true) + @PathParam("query") String queryName, + @ApiParam(value="Query Identifier Present in the DRL Query", required=true) + @PathParam("queriedEntity") String queriedEntity) { + try { + DroolsController drools = getDroolsController(controllerName); + List facts = drools.factQuery(sessionName, queryName, queriedEntity, false); + if (!count) + return Response.status(Response.Status.OK).entity(facts).build(); + else + return Response.status(Response.Status.OK).entity(facts.size()).build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not acceptable")). + build(); + } catch (Exception e) { + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(e.getMessage())). + build(); + } + } + + @POST + @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}") + @ApiOperation( + value="Gets all the fact objects returned by a DRL query with parameters from the drools working memory" + + "for a given controller and session", + notes="The DRL query with parameters must be defined in the DRL file", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, session, or query information, cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response droolsFacts(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName, + @ApiParam(value="Query Name Present in DRL", required=true) + @PathParam("query") String queryName, + @ApiParam(value="Query Identifier Present in the DRL Query", required=true) + @PathParam("queriedEntity") String queriedEntity, + @ApiParam(value="Query Parameter Values to pass in the DRL Query", required=false) + List queryParameters) { + try { + DroolsController drools = getDroolsController(controllerName); + List facts; + if (queryParameters == null || queryParameters.isEmpty()) + facts = drools.factQuery(sessionName, queryName, queriedEntity, false); + else + facts = drools.factQuery(sessionName, queryName, queriedEntity, false, queryParameters.toArray()); + return Response.status(Response.Status.OK).entity(facts).build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not acceptable")). + build(); + } catch (Exception e) { + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(e.getMessage())). + build(); + } + } + + @DELETE + @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}") + @ApiOperation( + value="Deletes all the fact objects returned by a DRL query with parameters from the drools working memory" + + "for a given controller and session", + notes="The DRL query with parameters must be defined in the DRL file", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, session, or query information, cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response droolsFactsDelete(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Drools Session Name", required=true) + @PathParam("session") String sessionName, + @ApiParam(value="Query Name Present in DRL", required=true) + @PathParam("query") String queryName, + @ApiParam(value="Query Identifier Present in the DRL Query", required=true) + @PathParam("queriedEntity") String queriedEntity, + @ApiParam(value="Query Parameter Values to pass in the DRL Query", required=false) + List queryParameters) { + try { + DroolsController drools = getDroolsController(controllerName); + List facts; + if (queryParameters == null || queryParameters.isEmpty()) + facts = drools.factQuery(sessionName, queryName, queriedEntity, true); + else + facts = drools.factQuery(sessionName, queryName, queriedEntity, true, queryParameters.toArray()); + return Response.status(Response.Status.OK).entity(facts).build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + sessionName + ":" + queryName + + queriedEntity + " not acceptable")). + build(); + } catch (Exception e) { + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(e.getMessage())). + build(); + } + } + + @POST + @Path("engine/controllers/tools/coders/decoders/filters/rules/{ruleName}") + @ApiOperation( + value="Produces a Decoder Rule Filter in a format that the Policy Controller can understand", + notes="The result can be used with other APIs to attach a filter to a decoder" + ) + public Response rules(@ApiParam(value="Negate regex?", required=true) + @DefaultValue("false") @QueryParam("negate") boolean negate, + @ApiParam(value="Rule Name", required=true) + @PathParam("ruleName") String name, + @ApiParam(value="Regex expression", required=true) + String regex) { + String literalRegex = Pattern.quote(regex); + if (negate) + literalRegex = "^(?!" + literalRegex + "$).*"; + + return Response.status(Status.OK). + entity(new JsonProtocolFilter.FilterRule(name,literalRegex)). + build(); + } + + @GET + @Path("engine/controllers/{controller}/decoders") + @ApiOperation( + value="Gets all the decoders used by a controller", + notes="A Policy Controller uses decoders to deserialize incoming network messages from " + + "subscribed network topics into specific (fact) objects. " + + "The deserialized (fact) object will typically be inserted in the drools working " + + " memory of the controlled drools application.", + responseContainer="List", + response=ProtocolCoderToolset.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoders(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + try { + DroolsController drools = getDroolsController(controllerName); + List decoders = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId()); + return Response.status(Response.Status.OK). + entity(decoders). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/decoders/filters") + @ApiOperation( + value="Gets all the filters used by a controller", + notes="A Policy Controller uses decoders to deserialize incoming network messages from " + + "subscribed network topics into specific (fact) objects. " + + "The deserialized (fact) object will typically be inserted in the drools working " + + " memory of the controlled drools application." + + "Acceptance filters are used to filter out undesired network messages for the given controller", + responseContainer="List", + response=CoderFilters.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilters(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + try { + DroolsController drools = getDroolsController(controllerName); + List filters = EventProtocolCoder.manager.getDecoderFilters + (drools.getGroupId(), drools.getArtifactId()); + return Response.status(Response.Status.OK). + entity(filters). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/decoders/{topic}") + @ApiOperation( + value="Gets all the decoders in use by a controller for a networked topic", + notes="A Policy Controller uses decoders to deserialize incoming network messages from " + + "subscribed network topics into specific (fact) objects. " + + "The deserialized (fact) object will typically be inserted in the drools working " + + " memory of the controlled drools application.", + responseContainer="List", + response=ProtocolCoderToolset.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller or topic cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoder(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Networked Topic Name", required=true) + @PathParam("topic") String topic) { + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topic); + return Response.status(Response.Status.OK). + entity(decoder). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/decoders/{topic}/filters") + @ApiOperation( + value="Gets all filters attached to decoders for a given networked topic in use by a controller", + notes="A Policy Controller uses decoders to deserialize incoming network messages from " + + "subscribed network topics into specific (fact) objects. " + + "The deserialized (fact) object will typically be inserted in the drools working " + + " memory of the controlled drools application." + + "Acceptance filters are used to filter out undesired network messages for the given controller", + responseContainer="List", + response=CoderFilters.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller or topic cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilter(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Networked Topic Name", required=true) + @PathParam("topic") String topic) { + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topic); + if (decoder == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(topic + " does not exist")). + build(); + else + return Response.status(Response.Status.OK). + entity(decoder.getCoders()). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}") + @ApiOperation( + value="Gets all filters attached to decoders for a given subscribed networked topic " + + "and fact type", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type (classname).", + responseContainer="List", + response=CoderFilters.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, or fact type cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilter(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Networked Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass) { + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topic); + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(topic + ":" + factClass + " does not exist")). + build(); + else + return Response.status(Response.Status.OK). + entity(filters). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not acceptable")). + build(); + } + } + + @PUT + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}") + @ApiOperation( + value="Attaches filters to the decoder for a given networked topic " + + "and fact type", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type (classname).", + responseContainer="List", + response=CoderFilters.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, fact type, cannot be found, " + + "or a filter has not been provided"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilter(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass, + @ApiParam(value="Configuration Filter", required=true) + JsonProtocolFilter configFilters) { + + if (configFilters == null) { + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error("Configuration Filters not provided")). + build(); + } + + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topic); + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(topic + ":" + factClass + " does not exist")). + build(); + filters.setFilter(configFilters); + return Response.status(Response.Status.OK). + entity(filters). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules") + @ApiOperation( + value="Gets the filter rules attached to a topic decoder of a controller", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type and are composed of field matching rules. ", + responseContainer="List", + response=FilterRule.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, or fact type cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilterRules(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass) { + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topic); + + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). + build(); + + JsonProtocolFilter filter = filters.getFilter(); + if (filter == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). + build(); + + return Response.status(Response.Status.OK). + entity(filter.getRules()). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not acceptable")). + build(); + } + } + + @GET + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}") + @ApiOperation( + value="Gets a filter rule by name attached to a topic decoder of a controller", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type and are composed of field matching rules. ", + responseContainer="List", + response=FilterRule.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, fact type, or rule name cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilterRules(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass, + @ApiParam(value="Rule Name", required=true) + @PathParam("ruleName") String ruleName) { + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topic); + + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). + build(); + + JsonProtocolFilter filter = filters.getFilter(); + if (filter == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). + build(); + + return Response.status(Response.Status.OK). + entity(filter.getRules(ruleName)). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + ": " + ruleName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + ":" + ruleName + " not acceptable")). + build(); + } + } + + @DELETE + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}") + @ApiOperation( + value="Deletes a filter rule by name attached to a topic decoder of a controller", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type and are composed of field matching rules. ", + responseContainer="List", + response=FilterRule.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, fact type, or rule name cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilterRuleDelete(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass, + @ApiParam(value="Rule Name", required=true) + @PathParam("ruleName") String ruleName, + @ApiParam(value="Filter Rule", required=true) + FilterRule rule) { + + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topic); + + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). + build(); + + JsonProtocolFilter filter = filters.getFilter(); + if (filter == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). + build(); + + if (rule == null) { + filter.deleteRules(ruleName); + return Response.status(Response.Status.OK). + entity(filter.getRules()). + build(); + } + + if (rule.getName() == null || !rule.getName().equals(ruleName)) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topic + ":" + factClass + ":" + ruleName + + " rule name request inconsistencies (" + rule.getName() + ")")). + build(); + + filter.deleteRule(ruleName, rule.getRegex()); + return Response.status(Response.Status.OK). + entity(filter.getRules()). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + ": " + ruleName + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + ":" + ruleName + " not acceptable")). + build(); + } + } + + @PUT + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules") + @ApiOperation( + value="Places a new filter rule in a topic decoder", + notes="Decoders are associated with networked topics. A Policy Controller manages " + + "multiple topics and therefore its attached decoders. " + + "A Policy Controller uses filters to further specify the fact mapping. " + + "Filters are applied on a per fact type and are composed of field matching rules. ", + responseContainer="List", + response=FilterRule.class + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The controller, topic, or fact type cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decoderFilterRule(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Fact Type", required=true) + @PathParam("factType") String factClass, + @ApiParam(value="Rule Name", required=true) + @PathParam("ruleName") String ruleName, + @ApiParam(value="Filter Rule", required=true) + FilterRule rule) { + + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topic); + + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). + build(); + + JsonProtocolFilter filter = filters.getFilter(); + if (filter == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). + build(); + + if (rule.getName() == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topic + ":" + factClass + + " rule name request inconsistencies (" + rule.getName() + ")")). + build(); + + filter.addRule(rule.getName(), rule.getRegex()); + return Response.status(Response.Status.OK). + entity(filter.getRules()). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + factClass + " not acceptable")). + build(); + } + } + + @POST + @Path("engine/controllers/{controller}/decoders/{topic}") + @Consumes(MediaType.TEXT_PLAIN) + @ApiOperation( + value="Decodes a string into a fact object, and encodes it back into a string", + notes="Tests the decode/encode functions of a controller", + response=CodingResult.class + ) + @ApiResponses(value = { + @ApiResponse(code=400, message="Bad input has been provided"), + @ApiResponse(code=404, message="The controller cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response decode(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName, + @ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="JSON String to decode", required=true) + String json) { + + PolicyController policyController; + try { + policyController = PolicyController.factory.get(controllerName); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + ":" + topic + ":" + + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + ":" + topic + ":" + + " not acceptable")). + build(); + } + + CodingResult result = new CodingResult(); + result.decoding = false; + result.encoding = false; + result.jsonEncoding = null; + + Object event; + try { + event = EventProtocolCoder.manager.decode + (policyController.getDrools().getGroupId(), + policyController.getDrools().getArtifactId(), + topic, + json); + result.decoding = true; + } catch (Exception e) { + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(e.getMessage())). + build(); + } + + try { + result.jsonEncoding = EventProtocolCoder.manager.encode(topic, event); + result.encoding = true; + } catch (Exception e) { + // continue so to propagate decoding results .. + } + + return Response.status(Response.Status.OK). + entity(result). + build(); + } + + @GET + @Path("engine/controllers/{controller}/encoders") + @ApiOperation( + value="Retrieves the encoder filters of a controller", + notes="The encoders serializes a fact object, typically for network transmission", + responseContainer="List", + response=CoderFilters.class + ) + @ApiResponses(value = { + @ApiResponse(code=400, message="Bad input has been provided"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response encoderFilters(@ApiParam(value="Policy Controller Name", required=true) + @PathParam("controller") String controllerName) { + List encoders; + try { + PolicyController controller = PolicyController.factory.get(controllerName); + DroolsController drools = controller.getDrools(); + encoders = EventProtocolCoder.manager.getEncoderFilters + (drools.getGroupId(), drools.getArtifactId()); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " not found: " + e.getMessage())). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " is not accepting the request")).build(); + } + + return Response.status(Response.Status.OK). + entity(encoders). + build(); + } + + @GET + @Path("engine/topics") + @ApiOperation( + value="Retrieves the managed topics", + notes="Network Topics Aggregation", + response=TopicEndpoint.class + ) + public Response topics() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager). + build(); + } + + @GET + @Path("engine/topics/switches") + @ApiOperation( + value="Topics Control Switches", + notes="List of the Topic Control Switches", + responseContainer="List" + ) + public Response topicSwitches() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Switches.values())). + build(); + } + + @PUT + @Path("engine/topics/switches/lock") + @ApiOperation( + value="Locks all the managed topics", + notes="The operation affects all managed sources and sinks", + response=TopicEndpoint.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response topicsLock() { + boolean success = TopicEndpoint.manager.lock(); + if (success) + return Response.status(Status.OK). + entity(TopicEndpoint.manager). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")). + build(); + } + + @DELETE + @Path("engine/topics/switches/lock") + @ApiOperation( + value="Unlocks all the managed topics", + notes="The operation affects all managed sources and sinks", + response=TopicEndpoint.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response topicsUnlock() { + boolean success = TopicEndpoint.manager.unlock(); + if (success) + return Response.status(Status.OK). + entity(TopicEndpoint.manager). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")). + build(); + } + + @GET + @Path("engine/topics/sources") + @ApiOperation( + value="Retrieves the managed topic sources", + notes="Network Topic Sources Agregation", + responseContainer="List", + response=TopicSource.class + ) + public Response sources() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getTopicSources()). + build(); + } + + @GET + @Path("engine/topics/sinks") + @ApiOperation( + value="Retrieves the managed topic sinks", + notes="Network Topic Sinks Agregation", + responseContainer="List", + response=TopicSink.class + ) + public Response sinks() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getTopicSinks()). + build(); + } + + @GET + @Path("engine/topics/sources/ueb") + @ApiOperation( + value="Retrieves the UEB managed topic sources", + notes="UEB Topic Sources Agregation", + responseContainer="List", + response=UebTopicSource.class + ) + public Response uebSources() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getUebTopicSources()). + build(); + } + + @GET + @Path("engine/topics/sinks/ueb") + @ApiOperation( + value="Retrieves the UEB managed topic sinks", + notes="UEB Topic Sinks Agregation", + responseContainer="List", + response=UebTopicSource.class + ) + public Response uebSinks() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getUebTopicSinks()). + build(); + } + + @GET + @Path("engine/topics/sources/dmaap") + @ApiOperation( + value="Retrieves the DMaaP managed topic sources", + notes="DMaaP Topic Sources Agregation", + responseContainer="List", + response=DmaapTopicSource.class + ) + public Response dmaapSources() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getDmaapTopicSources()). + build(); + } + + @GET + @Path("engine/topics/sinks/dmaap") + @ApiOperation( + value="Retrieves the DMaaP managed topic sinks", + notes="DMaaP Topic Sinks Agregation", + responseContainer="List", + response=DmaapTopicSink.class + ) + public Response dmaapSinks() { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getDmaapTopicSinks()). + build(); + } + + @GET + @Path("engine/topics/sources/ueb/{topic}") + @ApiOperation( + value="Retrieves an UEB managed topic source", + notes="This is an UEB Network Communicaton Endpoint source of messages for the Engine", + response=UebTopicSource.class + ) + public Response uebSourceTopic(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getUebTopicSource(topic)). + build(); + } + + @GET + @Path("engine/topics/sinks/ueb/{topic}") + @ApiOperation( + value="Retrieves an UEB managed topic sink", + notes="This is an UEB Network Communicaton Endpoint destination of messages from the Engine", + response=UebTopicSink.class + ) + public Response uebSinkTopic(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getUebTopicSink(topic)). + build(); + } + + @GET + @Path("engine/topics/sources/dmaap/{topic}") + @ApiOperation( + value="Retrieves a DMaaP managed topic source", + notes="This is a DMaaP Network Communicaton Endpoint source of messages for the Engine", + response=DmaapTopicSource.class + ) + public Response dmaapSourceTopic(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getDmaapTopicSource(topic)). + build(); + } + + @GET + @Path("engine/topics/sinks/dmaap/{topic}") + @ApiOperation( + value="Retrieves a DMaaP managed topic sink", + notes="This is a DMaaP Network Communicaton Endpoint destination of messages from the Engine", + response=DmaapTopicSink.class + ) + public Response dmaapSinkTopic(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Response.Status.OK). + entity(TopicEndpoint.manager.getDmaapTopicSink(topic)). + build(); + } + + @GET + @Path("engine/topics/sources/ueb/{topic}/events") + @ApiOperation( + value="Retrieves the latest events received by an UEB topic", + notes="This is a UEB Network Communicaton Endpoint source of messages for the Engine", + responseContainer="List" + ) + public Response uebSourceEvents(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Status.OK). + entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSource(topic).getRecentEvents())). + build(); + } + + @GET + @Path("engine/topics/sinks/ueb/{topic}/events") + @ApiOperation( + value="Retrieves the latest events sent from a topic", + notes="This is a UEB Network Communicaton Endpoint sink of messages from the Engine", + responseContainer="List" + ) + public Response uebSinkEvents(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Status.OK). + entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSink(topic).getRecentEvents())). + build(); + } + + @GET + @Path("engine/topics/sources/dmaap/{topic}/events") + @ApiOperation( + value="Retrieves the latest events received by a DMaaP topic", + notes="This is a DMaaP Network Communicaton Endpoint source of messages for the Engine", + responseContainer="List" + ) + public Response dmaapSourceEvents(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + return Response.status(Status.OK). + entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSource(topic).getRecentEvents())). + build(); + } + + @GET + @Path("engine/topics/sinks/dmaap/{topic}/events") + @ApiOperation( + value="Retrieves the latest events send through a DMaaP topic", + notes="This is a DMaaP Network Communicaton Endpoint destination of messages from the Engine", + responseContainer="List" + ) + public Response dmaapSinkEvents( + @PathParam("topic") String topic) { + return Response.status(Status.OK). + entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSink(topic).getRecentEvents())). + build(); + } + + @GET + @Path("engine/topics/sources/ueb/{topic}/switches") + @ApiOperation( + value="UEB Topic Control Switches", + notes="List of the UEB Topic Control Switches", + responseContainer="List" + ) + public Response uebTopicSwitches() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Switches.values())). + build(); + } + + @PUT + @Path("engine/topics/sources/ueb/{topic}/switches/lock") + @ApiOperation( + value="Locks an UEB Source topic", + response=UebTopicSource.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response uebTopicLock(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + UebTopicSource source = TopicEndpoint.manager.getUebTopicSource(topic); + boolean success = source.lock(); + if (success) + return Response.status(Status.OK). + entity(source). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation on " + topic)). + build(); + } + + @DELETE + @Path("engine/topics/sources/ueb/{topic}/switches/lock") + @ApiOperation( + value="Unlocks an UEB Source topic", + response=UebTopicSource.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response uebTopicUnlock(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + UebTopicSource source = TopicEndpoint.manager.getUebTopicSource(topic); + boolean success = source.unlock(); + if (success) + return Response.status(Status.OK). + entity(source). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation on " + topic)). + build(); + } + + @GET + @Path("engine/topics/sources/dmaap/{topic}/switches") + @ApiOperation( + value="DMaaP Topic Control Switches", + notes="List of the DMaaP Topic Control Switches", + responseContainer="List" + ) + public Response dmaapTopicSwitches() { + return Response.status(Response.Status.OK). + entity(Arrays.asList(Switches.values())). + build(); + } + + @PUT + @Path("engine/topics/sources/dmaap/{topic}/switches/lock") + @ApiOperation( + value="Locks an DMaaP Source topic", + response=DmaapTopicSource.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response dmmapTopicLock(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + DmaapTopicSource source = TopicEndpoint.manager.getDmaapTopicSource(topic); + boolean success = source.lock(); + if (success) + return Response.status(Status.OK). + entity(source). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation on " + topic)). + build(); + } + + @DELETE + @Path("engine/topics/sources/dmaap/{topic}/switches/lock") + @ApiOperation( + value="Unlocks an DMaaP Source topic", + response=DmaapTopicSource.class + ) + @ApiResponses(value = { + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled") + }) + public Response dmaapTopicUnlock(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic) { + DmaapTopicSource source = TopicEndpoint.manager.getDmaapTopicSource(topic); + boolean success = source.unlock(); + if (success) + return Response.status(Status.OK). + entity(source). + build(); + else + return Response.status(Status.SERVICE_UNAVAILABLE). + entity(new Error("cannot perform operation on " + topic)). + build(); + } + + @PUT + @Path("engine/topics/sources/ueb/{topic}/events") + @Consumes(MediaType.TEXT_PLAIN) + @ApiOperation( + value="Offers an event to an UEB topic for internal processing by the engine", + notes="The offered event is treated as it was incoming from the network", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The topic information cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response uebOffer(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Network Message", required=true) + String json) { + try { + UebTopicSource uebReader = TopicEndpoint.manager.getUebTopicSource(topic); + boolean success = uebReader.offer(json); + if (success) + return Response.status(Status.OK). + entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSource(topic).getRecentEvents())). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("Failure to inject event over " + topic)). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(topic + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(topic + " not acceptable due to current state")). + build(); + } catch (Exception e) { + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(e.getMessage())). + build(); + } + } + + @PUT + @Path("engine/topics/sources/dmaap/{topic}/events") + @Consumes(MediaType.TEXT_PLAIN) + @ApiOperation( + value="Offers an event to a DMaaP topic for internal processing by the engine", + notes="The offered event is treated as it was incoming from the network", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=404, message="The topic information cannot be found"), + @ApiResponse(code=406, message="The system is an administrative state that prevents " + + "this request to be fulfilled"), + @ApiResponse(code=500, message="A server error has occurred processing this request") + }) + public Response dmaapOffer(@ApiParam(value="Topic Name", required=true) + @PathParam("topic") String topic, + @ApiParam(value="Network Message", required=true) + String json) { + try { + DmaapTopicSource dmaapReader = TopicEndpoint.manager.getDmaapTopicSource(topic); + boolean success = dmaapReader.offer(json); + if (success) + return Response.status(Status.OK). + entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSource(topic).getRecentEvents())). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity(new Error("Failure to inject event over " + topic)). + build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(topic + " not found")). + build(); + } catch (IllegalStateException e) { + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(topic + " not acceptable due to current state")). + build(); + } catch (Exception e) { + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(e.getMessage())). + build(); + } + } + + @GET + @Path("engine/tools/uuid") + @ApiOperation( + value="Produces an UUID", + notes="UUID generation utility" + ) + @Produces(MediaType.TEXT_PLAIN) + public Response uuid() { + return Response.status(Status.OK). + entity(UUID.randomUUID().toString()). + build(); + } + + @GET + @Path("engine/tools/loggers") + @ApiOperation( + value="all active loggers", + responseContainer="List" + ) + @ApiResponses(value = { + @ApiResponse(code=500, message="logging misconfiguration") + }) + public Response loggers() { + List names = new ArrayList(); + if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) { + logger.warn("The SLF4J logger factory is not configured for logback"); + return Response.status(Status.INTERNAL_SERVER_ERROR). + entity(names).build(); + } + + LoggerContext context = + (LoggerContext) LoggerFactory.getILoggerFactory(); + for (Logger logger: context.getLoggerList()) { + names.add(logger.getName()); + } + + return Response.status(Status.OK). + entity(names). + build(); + } + + @GET + @Path("engine/tools/loggers/{logger}") + @ApiOperation( + value="logging level of a logger" + ) + @ApiResponses(value = { + @ApiResponse(code=500, message="logging misconfiguration"), + @ApiResponse(code=404, message="logger not found") + }) + public Response loggerName(@ApiParam(value="Logger Name", required=true) + @PathParam("logger") String loggerName) { + if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) { + logger.warn("The SLF4J logger factory is not configured for logback"); + return Response.status(Status.INTERNAL_SERVER_ERROR).build(); + } + + LoggerContext context = + (LoggerContext) LoggerFactory.getILoggerFactory(); + ch.qos.logback.classic.Logger logger = context.getLogger(loggerName); + if (logger == null) { + return Response.status(Status.NOT_FOUND).build(); + } + + String loggerLevel = (logger.getLevel() != null) ? logger.getLevel().toString() : ""; + return Response.status(Status.OK).entity(loggerLevel).build(); + } + + @PUT + @Path("engine/tools/loggers/{logger}/{level}") + @ApiOperation( + value="sets the logger level", + notes="Please use the SLF4J logger levels" + ) + @ApiResponses(value = { + @ApiResponse(code=500, message="logging misconfiguration"), + @ApiResponse(code=404, message="logger not found") + }) + public Response loggerName(@ApiParam(value="Logger Name", required=true) + @PathParam("logger") String loggerName, + @ApiParam(value="Logger Level", required=true) + @PathParam("level") String loggerLevel) { + if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) { + logger.warn("The SLF4J logger factory is not configured for logback"); + return Response.status(Status.INTERNAL_SERVER_ERROR).build(); + } + + LoggerContext context = + (LoggerContext) LoggerFactory.getILoggerFactory(); + ch.qos.logback.classic.Logger logger = context.getLogger(loggerName); + if (logger == null) { + return Response.status(Status.NOT_FOUND).build(); + } + + logger.setLevel(ch.qos.logback.classic.Level.toLevel(loggerLevel)); + return Response.status(Status.OK).entity(logger.getLevel().toString()).build(); + } + + /** + * gets the underlying drools controller from the named policy controller + * @param controllerName the policy controller name + * @return the underlying drools controller + * @throws IllegalArgumentException if an invalid controller name has been passed in + */ + protected DroolsController getDroolsController(String controllerName) throws IllegalArgumentException { + PolicyController controller = PolicyController.factory.get(controllerName); + if (controller == null) + throw new IllegalArgumentException(controllerName + " does not exist"); + + DroolsController drools = controller.getDrools(); + if (drools == null) + throw new IllegalArgumentException(controllerName + " has no drools configuration"); + + return drools; + } + + /* + * Helper classes for aggregation of results + */ + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("rest-telemetry-api []"); + return builder.toString(); + } + + /** + * Coding/Encoding Results Aggregation Helper class + */ + public static class CodingResult { + /** + * serialized output + */ + + public String jsonEncoding; + /** + * encoding result + */ + + public Boolean encoding; + + /** + * decoding result + */ + public Boolean decoding; + } + + /** + * Generic Error Reporting class + */ + public static class Error { + public String error; + + public Error(String error) { + this.error = error; + } + } + + /** + * Feed Ports into Resources + */ + public enum Inputs { + configuration, + } + + /** + * Resource Toggles + */ + public enum Switches { + activation, + lock, + } +} + diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/Main.java b/policy-management/src/main/java/org/onap/policy/drools/system/Main.java new file mode 100644 index 00000000..fe0cc01f --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/system/Main.java @@ -0,0 +1,135 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.system; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; + +import org.onap.policy.drools.persistence.SystemPersistence; +import org.onap.policy.drools.utils.PropertyUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Programmatic entry point to the management layer + */ +public class Main { + + /** + * logback configuration file system property + */ + public static final String LOGBACK_CONFIGURATION_FILE_SYSTEM_PROPERTY = "logback.configurationFile"; + + /** + * logback configuration file system property + */ + public static final String LOGBACK_CONFIGURATION_FILE_DEFAULT = "config/logback.xml"; + + /** + * constructor (hides public default one) + */ + private Main() {} + + /** + * main + * + * @param args program arguments + */ + public static void main(String args[]) { + + /* logging defaults */ + + if (System.getProperty(LOGBACK_CONFIGURATION_FILE_SYSTEM_PROPERTY) == null) + System.setProperty(LOGBACK_CONFIGURATION_FILE_SYSTEM_PROPERTY, LOGBACK_CONFIGURATION_FILE_DEFAULT); + + /* 0. boot */ + + PolicyEngine.manager.boot(args); + + Logger logger = LoggerFactory.getLogger(Main.class); + + File configDir = new File(SystemPersistence.CONFIG_DIR_NAME); + + if (!configDir.isDirectory()) { + throw new IllegalArgumentException + ("config directory: " + configDir.getAbsolutePath() + + " not found"); + } + + /* 1. Configure the Engine */ + + try { + Path policyEnginePath = Paths.get(configDir.toPath().toString(), SystemPersistence.PROPERTIES_FILE_ENGINE); + Properties properties = PropertyUtil.getProperties(policyEnginePath.toFile()); + PolicyEngine.manager.configure(properties); + } catch (Exception e) { + logger.warn("Main: cannot initialize {} because of {}", PolicyEngine.manager, e.getMessage(), e); + } + + /* 2. Start the Engine with the basic services only (no Policy Controllers) */ + + try { + boolean success = PolicyEngine.manager.start(); + if (!success) { + logger.warn("Main: {} has been partially started", PolicyEngine.manager); + } + } catch (IllegalStateException e) { + logger.warn("Main: cannot start {} (bad state) because of {}", PolicyEngine.manager, e.getMessage(), e); + } catch (Exception e) { + logger.warn("Main: cannot start {} because of {}", PolicyEngine.manager, e.getMessage(), e); + System.exit(1); + } + + /* 3. Create and start the controllers */ + + File[] controllerFiles = configDir.listFiles(); + for (File config : controllerFiles) { + + if (config.getName().endsWith(SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX)) { + int idxSuffix = + config.getName().indexOf(SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX); + int lastIdxSuffix = + config.getName().lastIndexOf(SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX); + if (idxSuffix != lastIdxSuffix) { + throw new IllegalArgumentException + ("Improper naming of controller properties file: " + + "Expected " + + SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX); + } + + String name = + config.getName().substring(0, lastIdxSuffix); + try { + Properties properties = PropertyUtil.getProperties(config); + PolicyController controller = PolicyEngine.manager.createPolicyController(name, properties); + controller.start(); + } catch (Exception e) { + logger.error("Main: cannot instantiate policy-controller {} because of {}", name, e.getMessage(), e); + } catch (LinkageError e) { + logger.warn("Main: cannot instantiate policy-controller {} (linkage) because of {}", + name, e.getMessage(), e); + } + } + } + } +} diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/PolicyController.java b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyController.java new file mode 100644 index 00000000..e6e1ca7e --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyController.java @@ -0,0 +1,110 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.system; + +import java.util.List; +import java.util.Properties; + +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.event.comm.TopicSource; +import org.onap.policy.drools.event.comm.Topic.CommInfrastructure; +import org.onap.policy.drools.event.comm.TopicSink; +import org.onap.policy.drools.properties.Lockable; +import org.onap.policy.drools.properties.Startable; +import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; + +/** + * A Policy Controller is the higher level unit of control. It corresponds to + * the ncomp equivalent of a controller. It provides management of underlying + * resources associated with the policy controller, which is a) communication + * infrastructure, and b) policy-core (drools) session infrastructure + * + */ +public interface PolicyController extends Startable, Lockable { + + /** + * name of this Policy Controller + */ + public String getName(); + + /** + * Get the topic readers of interest for this controller + */ + public List getTopicSources(); + + /** + * Get the topic readers of interest for this controller + */ + public List getTopicSinks(); + + /** + * Get the Drools Controller + */ + public DroolsController getDrools(); + + /** + * update maven configuration + * + * @param newDroolsConfiguration new drools configuration + * @return true if the update was successful, false otherwise + */ + public boolean updateDrools(DroolsConfiguration newDroolsConfiguration); + + /** + * Get the Properties + */ + public Properties getProperties(); + + /** + * Attempts delivering of an String over communication + * infrastructure "busType" + * + * @param eventBus Communication infrastructure identifier + * @param topic topic + * @param event the event object to send + * + * @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 permitted (ie. locked or stopped). + * @throws UnsupportedOperationException when the engine cannot deliver due + * to the functionality missing (ie. communication infrastructure + * not supported. + */ + public boolean deliver(CommInfrastructure busType, String topic, + Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException; + + /** + * halts and permanently releases all resources + * @throws IllegalStateException + */ + public void halt() throws IllegalStateException; + + /** + * Factory that tracks and manages Policy Controllers + */ + public static PolicyControllerFactory factory = + new IndexedPolicyControllerFactory(); + +} diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/PolicyControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyControllerFactory.java new file mode 100644 index 00000000..34c8589f --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyControllerFactory.java @@ -0,0 +1,522 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.system; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.features.PolicyControllerFeatureAPI; +import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; +import org.onap.policy.drools.system.internal.AggregatedPolicyController; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * Policy Controller Factory to manage controller creation, destruction, + * and retrieval for management interfaces + */ +public interface PolicyControllerFactory { + /** + * Build a controller from a properties file + * + * @param name the global name of this controller + * @param properties input parameters in form of properties for controller + * initialization. + * + * @return a Policy Controller + * + * @throws IllegalArgumentException invalid values provided in properties + */ + public PolicyController build(String name, Properties properties) + throws IllegalArgumentException; + + /** + * patches (updates) a controller from a critical configuration update. + * + * @param name + * @param configController + * + * @return a Policy Controller + */ + public PolicyController patch(String name, DroolsConfiguration configController); + + /** + * rebuilds (updates) a controller from a configuration update. + * + * @param controller + * @param configController + * + * @return a Policy Controller + */ + public PolicyController patch(PolicyController controller, + DroolsConfiguration configController); + + /** + * get PolicyController from DroolsController + * + * @param droolsController + * @return + * @throws IllegalArgumentException + * @throws IllegalStateException + */ + public PolicyController get(DroolsController droolsController) + throws IllegalArgumentException, IllegalStateException; + + /** + * Makes the Policy Controller identified by controllerName not operational, but + * does not delete its associated data + * + * @param controllerName name of the policy controller + * @throws IllegalArgumentException invalid arguments + */ + public void shutdown(String controllerName) throws IllegalArgumentException;; + + /** + * Makes the Policy Controller identified by controller not operational, but + * does not delete its associated data + * + * @param controller a Policy Controller + * @throws IllegalArgumentException invalid arguments + */ + public void shutdown(PolicyController controller) throws IllegalArgumentException; + + /** + * Releases all Policy Controllers from operation + */ + public void shutdown(); + + /** + * Destroys this Policy Controller + * + * @param controllerName name of the policy controller + * @throws IllegalArgumentException invalid arguments + */ + public void destroy(String controllerName) throws IllegalArgumentException;; + + /** + * Destroys this Policy Controller + * + * @param controller a Policy Controller + * @throws IllegalArgumentException invalid arguments + */ + public void destroy(PolicyController controller) throws IllegalArgumentException; + + /** + * Releases all Policy Controller resources + */ + public void destroy(); + + /** + * gets the Policy Controller identified by its name + * + * @param policyControllerName + * @return + * @throws IllegalArgumentException + * @throws IllegalStateException + */ + public PolicyController get(String policyControllerName) + throws IllegalArgumentException, IllegalStateException; + + /** + * gets the Policy Controller identified by group and artifact ids + * + * @param groupId group id + * @param artifactId artifact id + * @return + * @throws IllegalArgumentException + * @throws IllegalStateException + */ + public PolicyController get(String groupId, String artifactId) + throws IllegalArgumentException, IllegalStateException; + + /** + * get features attached to the Policy Controllers + * @return list of features + */ + public List getFeatureProviders(); + + /** + * get named feature attached to the Policy Controllers + * @return the feature + */ + public PolicyControllerFeatureAPI getFeatureProvider(String featureName) + throws IllegalArgumentException; + + /** + * get features attached to the Policy Controllers + * @return list of features + */ + public List getFeatures(); + + /** + * returns the current inventory of Policy Controllers + * + * @return a list of Policy Controllers + */ + public List inventory(); +} + +/** + * Factory of Policy Controllers indexed by the name of the Policy Controller + */ +class IndexedPolicyControllerFactory implements PolicyControllerFactory { + // get an instance of logger + private static Logger logger = LoggerFactory.getLogger(PolicyControllerFactory.class); + + /** + * Policy Controller Name Index + */ + protected HashMap policyControllers = + new HashMap(); + + /** + * Group/Artifact Ids Index + */ + protected HashMap coordinates2Controller = + new HashMap(); + + /** + * produces key for indexing controller names + * + * @param group group id + * @param artifactId artifact id + * @return index key + */ + protected String toKey(String groupId, String artifactId) { + return groupId + ":" + artifactId; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized PolicyController build(String name, Properties properties) + throws IllegalArgumentException { + + if (this.policyControllers.containsKey(name)) { + return this.policyControllers.get(name); + } + + /* A PolicyController does not exist */ + + PolicyController controller = + new AggregatedPolicyController(name, properties); + + String coordinates = toKey(controller.getDrools().getGroupId(), + controller.getDrools().getArtifactId()); + + this.policyControllers.put(name, controller); + + + if (controller.getDrools().isBrained()) + this.coordinates2Controller.put(coordinates, controller); + + return controller; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized PolicyController patch(String name, DroolsConfiguration droolsConfig) + throws IllegalArgumentException { + + if (name == null || name.isEmpty() || !this.policyControllers.containsKey(name)) { + throw new IllegalArgumentException("Invalid " + name); + } + + if (droolsConfig == null) + throw new IllegalArgumentException("Invalid Drools Configuration"); + + PolicyController controller = this.get(name); + + if (controller == null) { + logger.warn("A POLICY CONTROLLER of name " + name + + "does not exist for patch operation: " + droolsConfig); + + throw new IllegalArgumentException("Not a valid controller of name " + name); + } + + this.patch(controller, droolsConfig); + + if (logger.isInfoEnabled()) + logger.info("UPDATED drools configuration: " + droolsConfig + " on " + this); + + return controller; + } + + + /** + * {@inheritDoc} + */ + @Override + public PolicyController patch(PolicyController controller, DroolsConfiguration droolsConfig) + throws IllegalArgumentException { + + if (controller == null) + throw new IllegalArgumentException("Not a valid controller: null"); + + if (!controller.updateDrools(droolsConfig)) { + logger.warn("Cannot update drools configuration: " + droolsConfig + " on " + this); + throw new IllegalArgumentException("Cannot update drools configuration Drools Configuration"); + } + + if (logger.isInfoEnabled()) + logger.info("UPDATED drools configuration: " + droolsConfig + " on " + this); + + String coordinates = toKey(controller.getDrools().getGroupId(), + controller.getDrools().getArtifactId()); + + if (controller.getDrools().isBrained()) + this.coordinates2Controller.put(coordinates, controller); + + return controller; + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown(String controllerName) throws IllegalArgumentException { + + if (controllerName == null || controllerName.isEmpty()) { + throw new IllegalArgumentException("Invalid " + controllerName); + } + + synchronized(this) { + if (!this.policyControllers.containsKey(controllerName)) { + return; + } + + PolicyController controller = this.policyControllers.get(controllerName); + this.shutdown(controller); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown(PolicyController controller) throws IllegalArgumentException { + this.unmanage(controller); + controller.shutdown(); + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() { + List controllers = this.inventory(); + for (PolicyController controller: controllers) { + controller.shutdown(); + } + + synchronized(this) { + this.policyControllers.clear(); + this.coordinates2Controller.clear(); + } + } + + /** + * unmanage the controller + * + * @param controller + * @return + * @throws IllegalArgumentException + */ + protected void unmanage(PolicyController controller) throws IllegalArgumentException { + if (controller == null) { + throw new IllegalArgumentException("Invalid Controller"); + } + + synchronized(this) { + if (!this.policyControllers.containsKey(controller.getName())) { + return; + } + controller = this.policyControllers.remove(controller.getName()); + + String coordinates = toKey(controller.getDrools().getGroupId(), + controller.getDrools().getArtifactId()); + this.coordinates2Controller.remove(coordinates); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy(String controllerName) throws IllegalArgumentException { + + if (controllerName == null || controllerName.isEmpty()) { + throw new IllegalArgumentException("Invalid " + controllerName); + } + + synchronized(this) { + if (!this.policyControllers.containsKey(controllerName)) { + return; + } + + PolicyController controller = this.policyControllers.get(controllerName); + this.destroy(controller); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy(PolicyController controller) throws IllegalArgumentException { + this.unmanage(controller); + controller.halt(); + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy() { + List controllers = this.inventory(); + for (PolicyController controller: controllers) { + controller.halt(); + } + + synchronized(this) { + this.policyControllers.clear(); + this.coordinates2Controller.clear(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyController get(String name) throws IllegalArgumentException, IllegalStateException { + + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException("Invalid " + name); + } + + synchronized(this) { + if (this.policyControllers.containsKey(name)) { + return this.policyControllers.get(name); + } else { + throw new IllegalArgumentException("Invalid " + name); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyController get(String groupId, String artifactId) + throws IllegalArgumentException, IllegalStateException { + + if (groupId == null || groupId.isEmpty() || + artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid group/artifact ids"); + } + + synchronized(this) { + String key = toKey(groupId,artifactId); + if (this.coordinates2Controller.containsKey(key)) { + return this.coordinates2Controller.get(key); + } else { + throw new IllegalArgumentException("Invalid " + key); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyController get(DroolsController droolsController) + throws IllegalArgumentException, IllegalStateException { + + if (droolsController == null) { + throw new IllegalArgumentException("No Drools Controller provided"); + } + + synchronized(this) { + String key = toKey(droolsController.getGroupId(), droolsController.getArtifactId()); + if (this.coordinates2Controller.containsKey(key)) { + return this.coordinates2Controller.get(key); + } else { + logger.error("Drools Controller not associated with Policy Controller " + droolsController + ":" + this); + throw new IllegalStateException("Drools Controller not associated with Policy Controller " + droolsController + ":" + this); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public List inventory() { + List controllers = + new ArrayList(this.policyControllers.values()); + return controllers; + } + + /** + * {@inheritDoc} + */ + @Override + public List getFeatures() { + List features = new ArrayList(); + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + features.add(feature.getName()); + } + return features; + } + + /** + * {@inheritDoc} + */ + @JsonIgnore + @Override + public List getFeatureProviders() { + return PolicyControllerFeatureAPI.providers.getList(); + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyControllerFeatureAPI getFeatureProvider(String featureName) throws IllegalArgumentException { + if (featureName == null || featureName.isEmpty()) + throw new IllegalArgumentException("A feature name must be provided"); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + if (feature.getName().equals(featureName)) + return feature; + } + + throw new IllegalArgumentException("Invalid Feature Name: " + featureName); + } +} diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngine.java b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngine.java new file mode 100644 index 00000000..1ee12304 --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngine.java @@ -0,0 +1,1461 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.system; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.core.PolicyContainer; +import org.onap.policy.drools.core.jmx.PdpJmxListener; +import org.onap.policy.drools.event.comm.Topic; +import org.onap.policy.drools.event.comm.Topic.CommInfrastructure; +import org.onap.policy.drools.event.comm.TopicEndpoint; +import org.onap.policy.drools.event.comm.TopicListener; +import org.onap.policy.drools.event.comm.TopicSink; +import org.onap.policy.drools.event.comm.TopicSource; +import org.onap.policy.drools.features.PolicyControllerFeatureAPI; +import org.onap.policy.drools.features.PolicyEngineFeatureAPI; +import org.onap.policy.drools.http.server.HttpServletServer; +import org.onap.policy.drools.persistence.SystemPersistence; +import org.onap.policy.drools.properties.Lockable; +import org.onap.policy.drools.properties.PolicyProperties; +import org.onap.policy.drools.properties.Startable; +import org.onap.policy.drools.protocol.coders.EventProtocolCoder; +import org.onap.policy.drools.protocol.configuration.ControllerConfiguration; +import org.onap.policy.drools.protocol.configuration.PdpdConfiguration; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +/** + * Policy Engine, the top abstraction for the Drools PDP Policy Engine. + * It abstracts away a Drools PDP Engine from management purposes. + * This is the best place to looking at the code from a top down approach. + * Other managed entities can be obtained from the PolicyEngine, hierarchically. + *
+ * PolicyEngine 1 --- * PolicyController 1 --- 1 DroolsController 1 --- 1 PolicyContainer 1 --- * PolicySession + *
+ * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicReader 1 --- 1 UebTopicReader + *
+ * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicReader 1 --- 1 DmaapTopicReader + *
+ * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicWriter 1 --- 1 DmaapTopicWriter + *
+ * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicReader 1 --- 1 RestTopicReader + *
+ * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicWriter 1 --- 1 RestTopicWriter + *
+ * PolicyEngine 1 --- 1 ManagementServer + */ +public interface PolicyEngine extends Startable, Lockable, TopicListener { + + /** + * Default Config Server Port + */ + public static final int CONFIG_SERVER_DEFAULT_PORT = 9696; + + /** + * Default Config Server Hostname + */ + public static final String CONFIG_SERVER_DEFAULT_HOST = "localhost"; + + /** + * Boot the engine + * + * @param cliArgs command line arguments + */ + public void boot(String cliArgs[]); + + /** + * configure the policy engine according to the given properties + * + * @param properties Policy Engine properties + * @throws IllegalArgumentException when invalid or insufficient + * properties are provided + */ + public void configure(Properties properties) throws IllegalArgumentException; + + /** + * registers a new Policy Controller with the Policy Engine + * initialized per properties. + * + * @param controller name + * @param properties properties to initialize the Policy Controller + * @throws IllegalArgumentException when invalid or insufficient + * properties are provided + * @throws IllegalStateException when the engine is in a state where + * this operation is not permitted. + * @return the newly instantiated Policy Controller + */ + public PolicyController createPolicyController(String name, Properties properties) + throws IllegalArgumentException, IllegalStateException; + + /** + * updates the Policy Engine with the given configuration + * + * @param configuration the configuration + * @return success or failure + * @throws IllegalArgumentException if invalid argument provided + * @throws IllegalStateException if the system is in an invalid state + */ + public boolean configure(PdpdConfiguration configuration) + throws IllegalArgumentException, IllegalStateException; + + /** + * updates a set of Policy Controllers with configuration information + * + * @param configuration + * @return + * @throws IllegalArgumentException + * @throws IllegalStateException + */ + public List updatePolicyControllers(List configuration) + throws IllegalArgumentException, IllegalStateException; + + /** + * updates an already existing Policy Controller with configuration information + * + * @param configuration configuration + * + * @return the updated Policy Controller + * @throws IllegalArgumentException in the configuration is invalid + * @throws IllegalStateException if the controller is in a bad state + * @throws Exception any other reason + */ + public PolicyController updatePolicyController(ControllerConfiguration configuration) + throws Exception; + + /** + * removes the Policy Controller identified by its name from the Policy Engine + * + * @param name name of the Policy Controller + * @return the removed Policy Controller + */ + public void removePolicyController(String name); + + /** + * removes a Policy Controller from the Policy Engine + * @param controller the Policy Controller to remove from the Policy Engine + */ + public void removePolicyController(PolicyController controller); + + /** + * returns a list of the available Policy Controllers + * + * @return list of Policy Controllers + */ + public List getPolicyControllers(); + + + /** + * get policy controller names + * + * @return list of controller names + */ + public List getPolicyControllerIds(); + + /** + * get unmanaged sources + * + * @return unmanaged sources + */ + public List getSources(); + + /** + * get unmanaged sinks + * + * @return unmanaged sinks + */ + public List getSinks(); + + /** + * get unmmanaged http servers list + * @return http servers + */ + public List getHttpServers(); + + /** + * get properties configuration + * + * @return properties objects + */ + public Properties getProperties(); + + /** + * get features attached to the Policy Engine + * @return list of features + */ + public List getFeatureProviders(); + + /** + * get named feature attached to the Policy Engine + * @return the feature + */ + public PolicyEngineFeatureAPI getFeatureProvider(String featureName) + throws IllegalArgumentException; + + /** + * get features attached to the Policy Engine + * @return list of features + */ + public List getFeatures(); + + /** + * Attempts the dispatching of an "event" object + * + * @param topic topic + * @param event the event object to send + * + * @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 permitted (ie. locked or stopped). + */ + public boolean deliver(String topic, Object event) + throws IllegalArgumentException, IllegalStateException; + + /** + * Attempts the dispatching of an "event" object over communication + * infrastructure "busType" + * + * @param eventBus Communication infrastructure identifier + * @param topic topic + * @param event the event object to send + * + * @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 permitted (ie. locked or stopped). + * @throws UnsupportedOperationException when the engine cannot deliver due + * to the functionality missing (ie. communication infrastructure + * not supported. + */ + public boolean deliver(String busType, String topic, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException; + + /** + * Attempts the dispatching of an "event" object over communication + * infrastructure "busType" + * + * @param eventBus Communication infrastructure enum + * @param topic topic + * @param event the event object to send + * + * @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 permitted (ie. locked or stopped). + * @throws UnsupportedOperationException when the engine cannot deliver due + * to the functionality missing (ie. communication infrastructure + * not supported. + */ + public boolean deliver(CommInfrastructure busType, String topic, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException; + + /** + * Attempts delivering of an String over communication + * infrastructure "busType" + * + * @param eventBus Communication infrastructure identifier + * @param topic topic + * @param event the event object to send + * + * @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 permitted (ie. locked or stopped). + * @throws UnsupportedOperationException when the engine cannot deliver due + * to the functionality missing (ie. communication infrastructure + * not supported. + */ + public boolean deliver(CommInfrastructure busType, String topic, + String event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException; + + /** + * Invoked when the host goes into the active state. + */ + public void activate(); + + /** + * Invoked when the host goes into the standby state. + */ + public void deactivate(); + + /** + * Policy Engine Manager + */ + public final static PolicyEngine manager = new PolicyEngineManager(); +} + +/** + * Policy Engine Manager Implementation + */ +class PolicyEngineManager implements PolicyEngine { + /** + * logger + */ + private static Logger logger = LoggerFactory.getLogger(PolicyEngineManager.class); + + /** + * Is the Policy Engine running? + */ + protected boolean alive = false; + + /** + * Is the engine locked? + */ + protected boolean locked = false; + + /** + * Properties used to initialize the engine + */ + protected Properties properties; + + /** + * Policy Engine Sources + */ + protected List sources = new ArrayList<>(); + + /** + * Policy Engine Sinks + */ + protected List sinks = new ArrayList<>(); + + /** + * Policy Engine HTTP Servers + */ + protected List httpServers = new ArrayList(); + + /** + * gson parser to decode configuration requests + */ + protected Gson decoder = new GsonBuilder().disableHtmlEscaping().create(); + + + /** + * {@inheritDoc} + */ + @Override + public synchronized void boot(String cliArgs[]) { + + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.beforeBoot(this, cliArgs)) + return; + } catch (Exception e) { + logger.error("{}: feature {} before-boot failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + try { + PolicyContainer.globalInit(cliArgs); + } catch (Exception e) { + logger.error("{}: cannot init policy-container because of {}", this, e.getMessage(), e); + } + + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.afterBoot(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} after-boot failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized void configure(Properties properties) throws IllegalArgumentException { + + if (properties == null) { + logger.warn("No properties provided"); + throw new IllegalArgumentException("No properties provided"); + } + + /* policy-engine dispatch pre configure hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.beforeConfigure(this, properties)) + return; + } catch (Exception e) { + logger.error("{}: feature {} before-configure failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + this.properties = properties; + + try { + this.sources = TopicEndpoint.manager.addTopicSources(properties); + for (TopicSource source: this.sources) { + source.register(this); + } + } catch (Exception e) { + logger.error("{}: add-sources failed", this, e); + } + + try { + this.sinks = TopicEndpoint.manager.addTopicSinks(properties); + } catch (IllegalArgumentException e) { + logger.error("{}: add-sinks failed", this, e); + } + + try { + this.httpServers = HttpServletServer.factory.build(properties); + } catch (IllegalArgumentException e) { + logger.error("{}: add-http-servers failed", this, e); + } + + /* policy-engine dispatch post configure hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.afterConfigure(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} after-configure failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + return; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized PolicyController createPolicyController(String name, Properties properties) + throws IllegalArgumentException, IllegalStateException { + + // check if a PROPERTY_CONTROLLER_NAME property is present + // if so, override the given name + + String propertyControllerName = properties.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME); + if (propertyControllerName != null && !propertyControllerName.isEmpty()) { + if (!propertyControllerName.equals(name)) { + throw new IllegalStateException("Proposed name (" + name + + ") and properties name (" + propertyControllerName + + ") don't match"); + } + name = propertyControllerName; + } + + PolicyController controller; + for (PolicyControllerFeatureAPI controllerFeature : PolicyControllerFeatureAPI.providers.getList()) { + try { + controller = controllerFeature.beforeCreate(name, properties); + if (controller != null) + return controller; + } catch (Exception e) { + logger.error("{}: feature {} before-controller-create failure because of {}", + this, controllerFeature.getClass().getName(), e.getMessage(), e); + } + } + + controller = PolicyController.factory.build(name, properties); + if (this.isLocked()) + controller.lock(); + + // feature hook + for (PolicyControllerFeatureAPI controllerFeature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (controllerFeature.afterCreate(controller)) + return controller; + } catch (Exception e) { + logger.error("{}: feature {} after-controller-create failure because of {}", + this, controllerFeature.getClass().getName(), e.getMessage(), e); + } + } + + return controller; + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean configure(PdpdConfiguration config) throws IllegalArgumentException, IllegalStateException { + + if (config == null) + throw new IllegalArgumentException("No configuration provided"); + + String entity = config.getEntity(); + + switch (entity) { + case PdpdConfiguration.CONFIG_ENTITY_CONTROLLER: + /* only this one supported for now */ + List configControllers = config.getControllers(); + if (configControllers == null || configControllers.isEmpty()) { + if (logger.isInfoEnabled()) + logger.info("No controller configuration provided: " + config); + return false; + } + List policyControllers = this.updatePolicyControllers(config.getControllers()); + if (policyControllers == null || policyControllers.isEmpty()) + return false; + else if (policyControllers.size() == configControllers.size()) + return true; + + return false; + default: + String msg = "Configuration Entity is not supported: " + entity; + logger.warn(msg); + throw new IllegalArgumentException(msg); + } + } + + /** + * {@inheritDoc} + */ + @Override + public List updatePolicyControllers(List configControllers) + throws IllegalArgumentException, IllegalStateException { + + List policyControllers = new ArrayList(); + if (configControllers == null || configControllers.isEmpty()) { + if (logger.isInfoEnabled()) + logger.info("No controller configuration provided: " + configControllers); + return policyControllers; + } + + for (ControllerConfiguration configController: configControllers) { + try { + PolicyController policyController = this.updatePolicyController(configController); + policyControllers.add(policyController); + } catch (Exception e) { + logger.error("{}: cannot update-policy-controllers because of {}", this, e.getMessage(), e); + } + } + + return policyControllers; + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyController updatePolicyController(ControllerConfiguration configController) + throws Exception { + + if (configController == null) + throw new IllegalArgumentException("No controller configuration has been provided"); + + String controllerName = configController.getName(); + if (controllerName == null || controllerName.isEmpty()) { + logger.warn("controller-name must be provided"); + throw new IllegalArgumentException("No controller configuration has been provided"); + } + + PolicyController policyController = null; + try { + String operation = configController.getOperation(); + if (operation == null || operation.isEmpty()) { + logger.warn("operation must be provided"); + throw new IllegalArgumentException("operation must be provided"); + } + + try { + policyController = PolicyController.factory.get(controllerName); + } catch (IllegalArgumentException e) { + // not found + logger.warn("Policy Controller " + controllerName + " not found"); + } + + if (policyController == null) { + + if (operation.equalsIgnoreCase(ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_LOCK) || + operation.equalsIgnoreCase(ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UNLOCK)) { + throw new IllegalArgumentException(controllerName + " is not available for operation " + operation); + } + + /* Recovery case */ + + logger.warn("controller " + controllerName + " does not exist. " + + "Attempting recovery from disk"); + + Properties properties = + SystemPersistence.manager.getControllerProperties(controllerName); + + /* + * returned properties cannot be null (per implementation) + * assert (properties != null) + */ + + if (properties == null) { + throw new IllegalArgumentException(controllerName + " is invalid"); + } + + logger.warn("controller " + controllerName + " being recovered. " + + "Reset controller's bad maven coordinates to brainless"); + + /* + * try to bring up bad controller in brainless mode, + * after having it working, apply the new create/update operation. + */ + properties.setProperty(PolicyProperties.RULES_GROUPID, DroolsController.NO_GROUP_ID); + properties.setProperty(PolicyProperties.RULES_ARTIFACTID, DroolsController.NO_ARTIFACT_ID); + properties.setProperty(PolicyProperties.RULES_VERSION, DroolsController.NO_VERSION); + + policyController = PolicyEngine.manager.createPolicyController(controllerName, properties); + + /* fall through to do brain update operation*/ + } + + switch (operation) { + case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_CREATE: + PolicyController.factory.patch(policyController, configController.getDrools()); + break; + case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UPDATE: + policyController.unlock(); + PolicyController.factory.patch(policyController, configController.getDrools()); + break; + case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_LOCK: + policyController.lock(); + break; + case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UNLOCK: + policyController.unlock(); + break; + default: + String msg = "Controller Operation Configuration is not supported: " + + operation + " for " + controllerName; + logger.warn(msg); + throw new IllegalArgumentException(msg); + } + + return policyController; + } catch (Exception e) { + logger.error("{}: cannot update-policy-controller because of {}", this, e.getMessage(), e); + throw e; + } catch (LinkageError e) { + logger.error("{}: cannot update-policy-controllers (rules) because of {}", this, e.getMessage(), e); + throw new IllegalStateException(e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized boolean start() throws IllegalStateException { + + /* policy-engine dispatch pre start hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.beforeStart(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} before-start failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + boolean success = true; + if (this.locked) + throw new IllegalStateException("Engine is locked"); + + this.alive = true; + + /* Start Policy Engine exclusively-owned (unmanaged) http servers */ + + for (HttpServletServer httpServer: this.httpServers) { + try { + if (!httpServer.waitedStart(5 * 1000L)) + success = false; + } catch (Exception e) { + logger.error("{}: cannot start http-server {} because of {}", this, + httpServer, e.getMessage(), e); + } + } + + /* Start Policy Engine exclusively-owned (unmanaged) sources */ + + for (TopicSource source: this.sources) { + try { + if (!source.start()) + success = false; + } catch (Exception e) { + logger.error("{}: cannot start topic-source {} because of {}", this, + source, e.getMessage(), e); + } + } + + /* Start Policy Engine owned (unmanaged) sinks */ + + for (TopicSink sink: this.sinks) { + try { + if (!sink.start()) + success = false; + } catch (Exception e) { + logger.error("{}: cannot start topic-sink {} because of {}", this, + sink, e.getMessage(), e); + } + } + + /* Start Policy Controllers */ + + List controllers = PolicyController.factory.inventory(); + for (PolicyController controller : controllers) { + try { + if (!controller.start()) + success = false; + } catch (Exception e) { + logger.error("{}: cannot start policy-controller {} because of {}", this, + controller, e.getMessage(), e); + success = false; + } + } + + /* Start managed Topic Endpoints */ + + try { + if (!TopicEndpoint.manager.start()) + success = false; + } catch (IllegalStateException e) { + logger.warn("{}: Topic Endpoint Manager is in an invalid state because of {}", this, e.getMessage(), e); + } + + + // Start the JMX listener + + PdpJmxListener.start(); + + /* policy-engine dispatch after start hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.afterStart(this)) + return success; + } catch (Exception e) { + logger.error("{}: feature {} after-start failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized boolean stop() { + + /* policy-engine dispatch pre stop hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.beforeStop(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} before-stop failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + /* stop regardless of the lock state */ + + boolean success = true; + if (!this.alive) + return true; + + this.alive = false; + + List controllers = PolicyController.factory.inventory(); + for (PolicyController controller : controllers) { + try { + if (!controller.stop()) + success = false; + } catch (Exception e) { + logger.error("{}: cannot stop policy-controller {} because of {}", this, + controller, e.getMessage(), e); + success = false; + } + } + + /* Stop Policy Engine owned (unmanaged) sources */ + for (TopicSource source: this.sources) { + try { + if (!source.stop()) + success = false; + } catch (Exception e) { + logger.error("{}: cannot start topic-source {} because of {}", this, + source, e.getMessage(), e); + } + } + + /* Stop Policy Engine owned (unmanaged) sinks */ + for (TopicSink sink: this.sinks) { + try { + if (!sink.stop()) + success = false; + } catch (Exception e) { + logger.error("{}: cannot start topic-sink {} because of {}", this, + sink, e.getMessage(), e); + } + } + + /* stop all managed topics sources and sinks */ + if (!TopicEndpoint.manager.stop()) + success = false; + + /* stop all unmanaged http servers */ + for (HttpServletServer httpServer: this.httpServers) { + try { + if (!httpServer.stop()) + success = false; + } catch (Exception e) { + logger.error("{}: cannot start http-server {} because of {}", this, + httpServer, e.getMessage(), e); + } + } + + /* policy-engine dispatch pre stop hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.afterStop(this)) + return success; + } catch (Exception e) { + logger.error("{}: feature {} after-stop failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized void shutdown() throws IllegalStateException { + + /* policy-engine dispatch pre shutdown hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.beforeShutdown(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} before-shutdown failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + this.alive = false; + + /* Shutdown Policy Engine owned (unmanaged) sources */ + for (TopicSource source: this.sources) { + try { + source.shutdown(); + } catch (Exception e) { + logger.error("{}: cannot shutdown topic-source {} because of {}", this, + source, e.getMessage(), e); + } + } + + /* Shutdown Policy Engine owned (unmanaged) sinks */ + for (TopicSink sink: this.sinks) { + try { + sink.shutdown(); + } catch (Exception e) { + logger.error("{}: cannot shutdown topic-sink {} because of {}", this, + sink, e.getMessage(), e); + } + } + + /* Shutdown managed resources */ + PolicyController.factory.shutdown(); + TopicEndpoint.manager.shutdown(); + HttpServletServer.factory.destroy(); + + // Stop the JMX listener + + PdpJmxListener.stop(); + + /* policy-engine dispatch post shutdown hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.afterShutdown(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} after-shutdown failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(5000L); + } catch (InterruptedException e) { + logger.warn("{}: interrupted-exception while shutting down management server: ", this); + } + + /* shutdown all unmanaged http servers */ + for (HttpServletServer httpServer: getHttpServers()) { + try { + httpServer.shutdown(); + } catch (Exception e) { + logger.error("{}: cannot shutdown http-server {} because of {}", this, + httpServer, e.getMessage(), e); + } + } + + try { + Thread.sleep(5000L); + } catch (InterruptedException e) { + logger.warn("{}: interrupted-exception while shutting down management server: ", this); + } + + System.exit(0); + } + }).start(); + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized boolean isAlive() { + return this.alive; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized boolean lock() { + + /* policy-engine dispatch pre lock hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.beforeLock(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} before-lock failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + if (this.locked) + return true; + + this.locked = true; + + boolean success = true; + List controllers = PolicyController.factory.inventory(); + for (PolicyController controller : controllers) { + try { + success = controller.lock() && success; + } catch (Exception e) { + logger.error("{}: cannot lock policy-controller {} because of {}", this, + controller, e.getMessage(), e); + success = false; + } + } + + success = TopicEndpoint.manager.lock() && success; + + /* policy-engine dispatch post lock hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.afterLock(this)) + return success; + } catch (Exception e) { + logger.error("{}: feature {} after-lock failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized boolean unlock() { + + /* policy-engine dispatch pre unlock hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.beforeUnlock(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} before-unlock failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + if (!this.locked) + return true; + + this.locked = false; + + boolean success = true; + List controllers = PolicyController.factory.inventory(); + for (PolicyController controller : controllers) { + try { + success = controller.unlock() && success; + } catch (Exception e) { + logger.error("{}: cannot unlock policy-controller {} because of {}", this, + controller, e.getMessage(), e); + success = false; + } + } + + success = TopicEndpoint.manager.unlock() && success; + + /* policy-engine dispatch after unlock hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.afterUnlock(this)) + return success; + } catch (Exception e) { + logger.error("{}: feature {} after-unlock failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized boolean isLocked() { + return this.locked; + } + + /** + * {@inheritDoc} + */ + @Override + public void removePolicyController(String name) { + PolicyController.factory.destroy(name); + } + + /** + * {@inheritDoc} + */ + @Override + public void removePolicyController(PolicyController controller) { + PolicyController.factory.destroy(controller); + } + + /** + * {@inheritDoc} + */ + @JsonIgnore + @Override + public List getPolicyControllers() { + return PolicyController.factory.inventory(); + } + + /** + * {@inheritDoc} + */ + @JsonProperty("controllers") + @Override + public List getPolicyControllerIds() { + List controllerNames = new ArrayList(); + for (PolicyController controller: PolicyController.factory.inventory()) { + controllerNames.add(controller.getName()); + } + return controllerNames; + } + + /** + * {@inheritDoc} + */ + @Override + @JsonIgnore + public Properties getProperties() { + return this.properties; + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public List getSources() { + return (List) this.sources; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public List getSinks() { + return (List) this.sinks; + } + + /** + * {@inheritDoc} + */ + @Override + public List getHttpServers() { + return this.httpServers; + } + + + /** + * {@inheritDoc} + */ + @Override + public List getFeatures() { + List features = new ArrayList(); + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + features.add(feature.getName()); + } + return features; + } + + /** + * {@inheritDoc} + */ + @JsonIgnore + @Override + public List getFeatureProviders() { + return PolicyEngineFeatureAPI.providers.getList(); + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyEngineFeatureAPI getFeatureProvider(String featureName) throws IllegalArgumentException { + if (featureName == null || featureName.isEmpty()) + throw new IllegalArgumentException("A feature name must be provided"); + + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + if (feature.getName().equals(featureName)) + return feature; + } + + throw new IllegalArgumentException("Invalid Feature Name: " + featureName); + } + + /** + * {@inheritDoc} + */ + @Override + public void onTopicEvent(CommInfrastructure commType, String topic, String event) { + /* configuration request */ + try { + PdpdConfiguration configuration = this.decoder.fromJson(event, PdpdConfiguration.class); + this.configure(configuration); + } catch (Exception e) { + logger.error("{}: configuration-error due to {} because of {}", + this, event, e.getMessage(), e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(String topic, Object event) + throws IllegalArgumentException, IllegalStateException { + + /* + * Note this entry point is usually from the DRL + */ + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + if (event == null) + throw new IllegalArgumentException("Invalid Event"); + + if (!this.isAlive()) + throw new IllegalStateException("Policy Engine is stopped"); + + if (this.isLocked()) + throw new IllegalStateException("Policy Engine is locked"); + + List sinks = + TopicEndpoint.manager.getTopicSinks(topic); + if (sinks == null || sinks.isEmpty() || sinks.size() > 1) + throw new IllegalStateException + ("Cannot ensure correct delivery on topic " + topic + ": " + sinks); + + return this.deliver(sinks.get(0).getTopicCommInfrastructure(), + topic, event); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(String busType, String topic, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException { + + /* + * Note this entry point is usually from the DRL (one of the reasons + * busType is String. + */ + + if (busType == null || busType.isEmpty()) + throw new IllegalArgumentException + ("Invalid Communication Infrastructure"); + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + if (event == null) + throw new IllegalArgumentException("Invalid Event"); + + boolean valid = false; + for (Topic.CommInfrastructure comm: Topic.CommInfrastructure.values()) { + if (comm.name().equals(busType)) { + valid = true; + } + } + + if (!valid) + throw new IllegalArgumentException + ("Invalid Communication Infrastructure: " + busType); + + + if (!this.isAlive()) + throw new IllegalStateException("Policy Engine is stopped"); + + if (this.isLocked()) + throw new IllegalStateException("Policy Engine is locked"); + + + return this.deliver(Topic.CommInfrastructure.valueOf(busType), + topic, event); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(Topic.CommInfrastructure busType, + String topic, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException { + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + if (event == null) + throw new IllegalArgumentException("Invalid Event"); + + if (!this.isAlive()) + throw new IllegalStateException("Policy Engine is stopped"); + + if (this.isLocked()) + throw new IllegalStateException("Policy Engine is locked"); + + /* Try to send through the controller, this is the + * preferred way, since it may want to apply additional + * processing + */ + try { + DroolsController droolsController = + EventProtocolCoder.manager.getDroolsController(topic, event); + PolicyController controller = PolicyController.factory.get(droolsController); + if (controller != null) + return controller.deliver(busType, topic, event); + } catch (Exception e) { + logger.warn("{}: cannot find policy-controller to deliver {} over {}:{} because of {}", + this, event, busType, topic, e.getMessage(), e); + + /* continue (try without routing through the controller) */ + } + + /* + * cannot route through the controller, send directly through + * the topic sink + */ + try { + String json = EventProtocolCoder.manager.encode(topic, event); + return this.deliver(busType, topic, json); + + } catch (Exception e) { + logger.warn("{}: cannot deliver {} over {}:{} because of {}", + this, event, busType, topic, e.getMessage(), e); + throw e; + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(Topic.CommInfrastructure busType, + String topic, String event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException { + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + if (event == null || event.isEmpty()) + throw new IllegalArgumentException("Invalid Event"); + + if (!this.isAlive()) + throw new IllegalStateException("Policy Engine is stopped"); + + if (this.isLocked()) + throw new IllegalStateException("Policy Engine is locked"); + + try { + TopicSink sink = + TopicEndpoint.manager.getTopicSink + (busType, topic); + + if (sink == null) + throw new IllegalStateException("Inconsistent State: " + this); + + return sink.send(event); + + } catch (Exception e) { + logger.warn("{}: cannot deliver {} over {}:{} because of {}", + this, event, busType, topic, e.getMessage(), e); + throw e; + } + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized void activate() { + + /* policy-engine dispatch pre activate hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.beforeActivate(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} before-activate failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + // activate 'policy-management' + for (PolicyController policyController : getPolicyControllers()) { + try { + policyController.unlock(); + policyController.start(); + } catch (Exception e) { + logger.error("{}: cannot activate of policy-controller {} because of {}", + this, policyController,e.getMessage(), e); + } catch (LinkageError e) { + logger.error("{}: cannot activate (rules compilation) of policy-controller {} because of {}", + this, policyController,e.getMessage(), e); + } + } + + this.unlock(); + + /* policy-engine dispatch post activate hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.afterActivate(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} after-activate failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized void deactivate() { + + /* policy-engine dispatch pre deactivate hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.beforeDeactivate(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} before-deactivate failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + this.lock(); + + for (PolicyController policyController : getPolicyControllers()) { + try { + policyController.stop(); + } catch (Exception e) { + logger.error("{}: cannot deactivate (stop) policy-controller {} because of {}", + this, policyController, e.getMessage(), e); + } catch (LinkageError e) { + logger.error("{}: cannot deactivate (stop) policy-controller {} because of {}", + this, policyController, e.getMessage(), e); + } + } + + /* policy-engine dispatch post deactivate hook */ + for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { + try { + if (feature.afterDeactivate(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} after-deactivate failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("PolicyEngineManager [alive=").append(alive).append(", locked=").append(locked).append("]"); + return builder.toString(); + } + +} + + diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java b/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java new file mode 100644 index 00000000..e67e542f --- /dev/null +++ b/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java @@ -0,0 +1,626 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.system.internal; + +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.event.comm.Topic; +import org.onap.policy.drools.event.comm.TopicEndpoint; +import org.onap.policy.drools.event.comm.TopicListener; +import org.onap.policy.drools.event.comm.TopicSink; +import org.onap.policy.drools.event.comm.TopicSource; +import org.onap.policy.drools.features.PolicyControllerFeatureAPI; +import org.onap.policy.drools.persistence.SystemPersistence; +import org.onap.policy.drools.properties.PolicyProperties; +import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; +import org.onap.policy.drools.system.PolicyController; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * This implementation of the Policy Controller merely aggregates and tracks for + * management purposes all underlying resources that this controller depends upon. + */ +public class AggregatedPolicyController implements PolicyController, + TopicListener { + + /** + * Logger + */ + private static Logger logger = LoggerFactory.getLogger(AggregatedPolicyController.class); + + /** + * identifier for this policy controller + */ + protected final String name; + + /** + * Abstracted Event Sources List regardless communication + * technology + */ + protected final List sources; + + /** + * Abstracted Event Sinks List regardless communication + * technology + */ + protected final List sinks; + + /** + * Mapping topics to sinks + */ + @JsonIgnore + protected final HashMap topic2Sinks = + new HashMap(); + + /** + * Is this Policy Controller running (alive) ? + * reflects invocation of start()/stop() only + */ + protected volatile boolean alive; + + /** + * Is this Policy Controller locked ? + * reflects if i/o controller related operations and start + * are permitted, + * more specifically: start(), deliver() and onTopicEvent(). + * It does not affect the ability to stop the + * underlying drools infrastructure + */ + protected volatile boolean locked; + + /** + * Policy Drools Controller + */ + protected volatile DroolsController droolsController; + + /** + * Properties used to initialize controller + */ + protected final Properties properties; + + /** + * Constructor version mainly used for bootstrapping at initialization time + * a policy engine controller + * + * @param name controller name + * @param properties + * + * @throws IllegalArgumentException when invalid arguments are provided + */ + public AggregatedPolicyController(String name, Properties properties) + throws IllegalArgumentException { + + this.name = name; + + /* + * 1. Register read topics with network infrastructure (ueb, dmaap, rest) + * 2. Register write topics with network infrastructure (ueb, dmaap, rest) + * 3. Register with drools infrastructure + */ + + // Create/Reuse Readers/Writers for all event sources endpoints + + this.sources = TopicEndpoint.manager.addTopicSources(properties); + this.sinks = TopicEndpoint.manager.addTopicSinks(properties); + + initDrools(properties); + initSinks(); + + /* persist new properties */ + SystemPersistence.manager.storeController(name, properties); + this.properties = properties; + } + + /** + * initialize drools layer + * @throws IllegalArgumentException if invalid parameters are passed in + */ + protected void initDrools(Properties properties) throws IllegalArgumentException { + try { + // Register with drools infrastructure + this.droolsController = DroolsController.factory.build(properties, sources, sinks); + } catch (Exception | LinkageError e) { + logger.error("{}: cannot init-drools because of {}", this, e.getMessage(), e); + throw new IllegalArgumentException(e); + } + } + + /** + * initialize sinks + * @throws IllegalArgumentException if invalid parameters are passed in + */ + protected void initSinks() throws IllegalArgumentException { + this.topic2Sinks.clear(); + for (TopicSink sink: sinks) { + this.topic2Sinks.put(sink.getTopic(), sink); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean updateDrools(DroolsConfiguration newDroolsConfiguration) { + + DroolsConfiguration oldDroolsConfiguration = + new DroolsConfiguration(this.droolsController.getArtifactId(), + this.droolsController.getGroupId(), + this.droolsController.getVersion()); + + if (oldDroolsConfiguration.getGroupId().equalsIgnoreCase(newDroolsConfiguration.getGroupId()) && + oldDroolsConfiguration.getArtifactId().equalsIgnoreCase(newDroolsConfiguration.getArtifactId()) && + oldDroolsConfiguration.getVersion().equalsIgnoreCase(newDroolsConfiguration.getVersion())) { + logger.warn("{}: cannot update-drools: identical configuration {} vs {}", + this, oldDroolsConfiguration, newDroolsConfiguration); + return true; + } + + try { + /* Drools Controller created, update initialization properties for restarts */ + + this.properties.setProperty(PolicyProperties.RULES_GROUPID, newDroolsConfiguration.getGroupId()); + this.properties.setProperty(PolicyProperties.RULES_ARTIFACTID, newDroolsConfiguration.getArtifactId()); + this.properties.setProperty(PolicyProperties.RULES_VERSION, newDroolsConfiguration.getVersion()); + + SystemPersistence.manager.storeController(name, this.properties); + + this.initDrools(this.properties); + + /* set drools controller to current locked status */ + + if (this.isLocked()) + this.droolsController.lock(); + else + this.droolsController.unlock(); + + /* set drools controller to current alive status */ + + if (this.isAlive()) + this.droolsController.start(); + else + this.droolsController.stop(); + + } catch (IllegalArgumentException e) { + logger.error("{}: cannot update-drools because of {}", this, e.getMessage(), e); + return false; + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public String getName() { + return this.name; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean start() throws IllegalStateException { + logger.info("{}: start", this); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.beforeStart(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} before-start failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + if (this.isLocked()) + throw new IllegalStateException("Policy Controller " + name + " is locked"); + + synchronized(this) { + if (this.alive) + return true; + + this.alive = true; + } + + boolean success = this.droolsController.start(); + + // register for events + + for (TopicSource source: sources) { + source.register(this); + } + + for (TopicSink sink: sinks) { + try { + sink.start(); + } catch (Exception e) { + logger.error("{}: cannot start {} because of {}", + this, sink, e.getMessage(), e); + } + } + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.afterStart(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} after-start failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() { + logger.info("{}: stop", this); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.beforeStop(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} before-stop failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + /* stop regardless locked state */ + + synchronized(this) { + if (!this.alive) + return true; + + this.alive = false; + } + + // 1. Stop registration + + for (TopicSource source: sources) { + source.unregister(this); + } + + boolean success = this.droolsController.stop(); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.afterStop(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} after-stop failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + logger.info("{}: shutdown", this); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.beforeShutdown(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} before-shutdown failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + this.stop(); + + DroolsController.factory.shutdown(this.droolsController); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.afterShutdown(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} after-shutdown failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void halt() throws IllegalStateException { + logger.info("{}: halt", this); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.beforeHalt(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} before-halt failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + this.stop(); + DroolsController.factory.destroy(this.droolsController); + SystemPersistence.manager.deleteController(this.name); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.afterHalt(this)) + return; + } catch (Exception e) { + logger.error("{}: feature {} after-halt failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void onTopicEvent(Topic.CommInfrastructure commType, + String topic, String event) { + + if (logger.isDebugEnabled()) + logger.debug("{}: event offered from {}:{}: {}", this, commType, topic, event); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.beforeOffer(this, commType, topic, event)) + return; + } catch (Exception e) { + logger.error("{}: feature {} before-offer failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + if (this.locked) + return; + + if (!this.alive) + return; + + boolean success = this.droolsController.offer(topic, event); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.afterOffer(this, commType, topic, event, success)) + return; + } catch (Exception e) { + logger.error("{}: feature {} after-offer failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(Topic.CommInfrastructure commType, + String topic, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException { + + if (logger.isDebugEnabled()) + logger.debug("{}: deliver event to {}:{}: {}", this, commType, topic, event); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.beforeDeliver(this, commType, topic, event)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} before-deliver failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + if (event == null) + throw new IllegalArgumentException("Invalid Event"); + + if (!this.isAlive()) + throw new IllegalStateException("Policy Engine is stopped"); + + if (this.isLocked()) + throw new IllegalStateException("Policy Engine is locked"); + + if (!this.topic2Sinks.containsKey(topic)) { + logger.warn("{}: cannot deliver event because the sink {}:{} is not registered: {}", + this, commType, topic, event); + throw new IllegalArgumentException("Unsuported topic " + topic + " for delivery"); + } + + boolean success = this.droolsController.deliver(this.topic2Sinks.get(topic), event); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.afterDeliver(this, commType, topic, event, success)) + return success; + } catch (Exception e) { + logger.error("{}: feature {} after-deliver failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + return this.alive; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean lock() { + logger.info("{}: lock", this); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.beforeLock(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} before-lock failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + synchronized(this) { + if (this.locked) + return true; + + this.locked = true; + } + + // it does not affect associated sources/sinks, they are + // autonomous entities + + boolean success = this.droolsController.lock(); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.afterLock(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} after-lock failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean unlock() { + + logger.info("{}: unlock", this); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.beforeUnlock(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} before-unlock failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + synchronized(this) { + if (!this.locked) + return true; + + this.locked = false; + } + + boolean success = this.droolsController.unlock(); + + for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { + try { + if (feature.afterUnlock(this)) + return true; + } catch (Exception e) { + logger.error("{}: feature {} after-unlock failure because of {}", + this, feature.getClass().getName(), e.getMessage(), e); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLocked() { + return this.locked; + } + + /** + * {@inheritDoc} + */ + @Override + public List getTopicSources() { + return this.sources; + } + + /** + * {@inheritDoc} + */ + @Override + public List getTopicSinks() { + return this.sinks; + } + + /** + * {@inheritDoc} + */ + @Override + public DroolsController getDrools() { + return this.droolsController; + } + + + /** + * {@inheritDoc} + */ + @Override + @JsonIgnore + public Properties getProperties() { + return this.properties; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("AggregatedPolicyController [name=").append(name).append(", alive=").append(alive).append(", locked=").append(locked) + .append(", droolsController=").append(droolsController).append("]"); + return builder.toString(); + } + +} + diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java b/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java deleted file mode 100644 index 251cef11..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java +++ /dev/null @@ -1,218 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.controller; - -import java.util.List; -import java.util.Map; - -import org.openecomp.policy.drools.core.PolicyContainer; -import org.openecomp.policy.drools.event.comm.TopicSink; -import org.openecomp.policy.drools.properties.Lockable; -import org.openecomp.policy.drools.properties.Startable; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration; - -/** - * Drools Controller is the abstractions that wraps the - * drools layer (policy-core) - */ -public interface DroolsController extends Startable, Lockable { - - /** - * No Group ID identifier - */ - public static final String NO_GROUP_ID = "NO-GROUP-ID"; - - /** - * No Artifact ID identifier - */ - public static final String NO_ARTIFACT_ID = "NO-ARTIFACT-ID"; - - /** - * No version identifier - */ - public static final String NO_VERSION = "NO-VERSION"; - - /** - * get group id - * @return group id - */ - public String getGroupId(); - - /** - * get artifact id - * @return artifact id - */ - public String getArtifactId(); - - /** - * get version - * @return version - */ - public String getVersion(); - - /** - * return the policy session names - * - * @return policy session - */ - public List getSessionNames(); - - /** - * return the policy full session names - * - * @return policy session - */ - public List getCanonicalSessionNames(); - - /** - * offers an event to this controller for processing - * - * @param topic topic associated with the event - * @param event the event - * - * @return true if the operation was successful - */ - public boolean offer(String topic, String event); - - /** - * delivers "event" to "sink" - * - * @param sink destination - * @param 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 permitted (ie. locked or stopped). - * @throws UnsupportedOperationException when the engine cannot deliver due - * to the functionality missing (ie. communication infrastructure - * not supported. - */ - public boolean deliver(TopicSink sink, Object event) - throws IllegalArgumentException, IllegalStateException, - UnsupportedOperationException; - - /** - * - * @return the most recent received events - */ - public Object[] getRecentSourceEvents(); - - /** - * - * @return the most recent delivered events - */ - public String[] getRecentSinkEvents(); - - /** - * @return the underlying policy container - */ - public PolicyContainer getContainer(); - - /** - * Supports this encoder? - * - * @param encodedObject - * @return - */ - public boolean ownsCoder(Class coderClass, int modelHash) throws IllegalStateException; - - /** - * fetches a class from the model - * - * @param className the class to fetch - * @return the actual class object, or null if not found - */ - public Class fetchModelClass(String className) throws IllegalArgumentException; - - /** - * is this controller Smart? - */ - public boolean isBrained(); - - /** - * update the new version of the maven jar rules file - * - * @param newGroupId - new group id - * @param newArtifactId - new artifact id - * @param newVersion - new version - * @param decoderConfigurations - decoder configurations - * @param encoderConfigurations - encoder configurations - * - * @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 decoderConfigurations, - List encoderConfigurations) - throws IllegalArgumentException, LinkageError, Exception; - - /** - * gets the classnames of facts as well as the current count - * @param sessionName the session name - * @return map of class to count - */ - public Map factClassNames(String sessionName) throws IllegalArgumentException; - - /** - * 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) throws IllegalArgumentException; - - /** - * gets all the facts of a given class for a given session - * - * @param sessionName the session identifier - * @param className the class type - * @param delete retract from drools the results of the query? - * @return the list of facts returned by the query - */ - public List facts(String sessionName, String className, boolean delete); - - /** - * 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 - * @param queriedEntity the queried entity - * @param delete retract from drools the results of the query? - * @param queryParams query parameters - * @return list of facts returned by the query - */ - public List factQuery(String sessionName, String queryName, String queriedEntity, - boolean delete, Object... queryParams); - - /** - * halts and permanently releases all resources - * @throws IllegalStateException - */ - public void halt() throws IllegalStateException; - - /** - * Factory to track and manage drools controllers - */ - public static final DroolsControllerFactory factory = - new IndexedDroolsControllerFactory(); -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsControllerFactory.java b/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsControllerFactory.java deleted file mode 100644 index 625eef56..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsControllerFactory.java +++ /dev/null @@ -1,555 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.controller; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Properties; - -import org.openecomp.policy.drools.controller.internal.MavenDroolsController; -import org.openecomp.policy.drools.controller.internal.NullDroolsController; -import org.openecomp.policy.drools.event.comm.Topic; -import org.openecomp.policy.drools.event.comm.Topic.CommInfrastructure; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.openecomp.policy.drools.event.comm.TopicSource; -import org.openecomp.policy.drools.event.comm.TopicSink; -import org.openecomp.policy.drools.properties.PolicyProperties; -import org.openecomp.policy.drools.protocol.coders.JsonProtocolFilter; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter; -import org.openecomp.policy.drools.utils.Pair; - -/** - * Drools Controller Factory to manage controller creation, destruction, - * and retrieval for management interfaces - */ -public interface DroolsControllerFactory { - - /** - * Constructs a Drools Controller based on properties - * - * @param properties properties containing initialization parameters - * @param eventSources list of event sources - * @param eventSinks list of event sinks - * - * @return the instantiated Drools Controller - * @throws IllegalArgumentException with invalid parameters - * @throws LinkageError Failure to link rules and models in Drools Libraries - * @throws Exception Exception from Drools Libraries - */ - public DroolsController build(Properties properties, - List eventSources, - List eventSinks) - throws IllegalArgumentException, LinkageError, Exception; - - /** - * Explicit construction of a Drools Controller - * - * @param groupId maven group id of drools artifact - * @param artifactId maven artifact id of drools artifact - * @param version maven version id of drools artifact - * @param decoderConfigurations list of decoder configurations - * @param encoderConfigurations list of encoder configurations - * - * @return the instantiated Drools Controller - * @throws IllegalArgumentException with invalid parameters - * @throws LinkageError Failure to link rules and models in Drools Libraries - * @throws Exception Exception from Drools Libraries - */ - public DroolsController build(String groupId, - String artifactId, - String version, - List decoderConfigurations, - List encoderConfigurations) - throws IllegalArgumentException, LinkageError, Exception; - - /** - * 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 - */ - public void shutdown(); - - /** - * Destroys and releases resources for a Drools Controller - * - * @param controller the Drools Controller to destroy - */ - public void destroy(DroolsController controller); - - /** - * Destroys all Drools Controllers - */ - public void destroy(); - - /** - * 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 - * @param version maven version id of drools artifact - * - * @return the Drools Controller - * @throws IllegalArgumentException with invalid parameters - */ - public DroolsController get(String groupId, - String artifactId, - String version) - throws IllegalArgumentException; - - /** - * returns the current inventory of Drools Controllers - * - * @return a list of Drools Controllers - */ - public List inventory(); -} - -/* ---------------- implementation -----------------*/ - -/** - * Factory of Drools Controllers indexed by the Maven coordinates - */ -class IndexedDroolsControllerFactory implements DroolsControllerFactory { - - /** - * logger - */ - private static Logger logger = LoggerFactory.getLogger(MavenDroolsController.class); - - /** - * Policy Controller Name Index - */ - protected HashMap droolsControllers = - new HashMap(); - - /** - * Null Drools Controller - */ - protected NullDroolsController nullDroolsController = new NullDroolsController(); - - - public IndexedDroolsControllerFactory() { - - /* Add a NULL controller which will always be present in the hash */ - - DroolsController controller = new NullDroolsController(); - String controllerId = controller.getGroupId() + ":" + controller.getArtifactId(); - - synchronized(this) { - droolsControllers.put(controllerId, controller); - } - } - - /** - * {@inheritDoc} - */ - @Override - public DroolsController build(Properties properties, - List eventSources, - List eventSinks) - throws IllegalArgumentException, LinkageError, Exception { - - String groupId = properties.getProperty(PolicyProperties.RULES_GROUPID); - if (groupId == null || groupId.isEmpty()) - groupId = DroolsController.NO_GROUP_ID; - - String artifactId = properties.getProperty(PolicyProperties.RULES_ARTIFACTID); - if (artifactId == null || artifactId.isEmpty()) - artifactId = DroolsController.NO_ARTIFACT_ID; - - String version = properties.getProperty(PolicyProperties.RULES_VERSION); - if (version == null || version.isEmpty()) - version = DroolsController.NO_VERSION; - - List - topics2DecodedClasses2Filters = codersAndFilters(properties, eventSources); - - List - topics2EncodedClasses2Filters = codersAndFilters(properties, eventSinks); - - return this.build(groupId, artifactId, version, - topics2DecodedClasses2Filters, - topics2EncodedClasses2Filters); - } - - /** - * find out decoder classes and filters - * - * @param properties properties with information about decoders - * @param topicEntities topic sources - * @return list of topics, each with associated decoder classes, each - * with a list of associated filters - * @throws IllegalArgumentException invalid input data - */ - protected List codersAndFilters - (Properties properties, List topicEntities) - throws IllegalArgumentException { - - String PROPERTY_TOPIC_ENTITY_PREFIX; - - List - topics2DecodedClasses2Filters = - new ArrayList(); - - if (topicEntities.isEmpty()) - return topics2DecodedClasses2Filters; - - for (Topic topic: topicEntities) { - - /* source or sink ? ueb or dmaap? */ - boolean isSource = (topic instanceof TopicSource); - CommInfrastructure commInfra = topic.getTopicCommInfrastructure(); - if (commInfra == CommInfrastructure.UEB) { - if (isSource) { - PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + "."; - } else { - PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_UEB_SINK_TOPICS + "."; - } - } else if (commInfra == CommInfrastructure.DMAAP) { - if (isSource) { - PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + "."; - } else { - PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_DMAAP_SINK_TOPICS + "."; - } - } else if (commInfra == CommInfrastructure.NOOP) { - if (!isSource) - PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_NOOP_SINK_TOPICS + "."; - else - continue; - } else { - throw new IllegalArgumentException("Invalid Communication Infrastructure: " + commInfra); - } - - // 1. first the topic - - String aTopic = 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 - (PROPERTY_TOPIC_ENTITY_PREFIX + - aTopic + - PolicyProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_GSON_SUFFIX); - - CustomGsonCoder customGsonCoder = null; - if (customGson != null && !customGson.isEmpty()) { - try { - customGsonCoder = new CustomGsonCoder(customGson); - } catch (IllegalArgumentException e) { - logger.warn("{}: cannot create custom-gson-coder {} because of {}", - this, customGson, e.getMessage(), e); - } - } - - String customJackson = properties.getProperty - (PROPERTY_TOPIC_ENTITY_PREFIX + - aTopic + - PolicyProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_JACKSON_SUFFIX); - - CustomJacksonCoder customJacksonCoder = null; - if (customJackson != null && !customJackson.isEmpty()) { - try { - customJacksonCoder = new CustomJacksonCoder(customJackson); - } catch (IllegalArgumentException e) { - logger.warn("{}: cannot create custom-jackson-coder {} because of {}", - this, customJackson, e.getMessage(), e); - } - } - - // 3. second the list of classes associated with each topic - - String eventClasses = - properties.getProperty(PROPERTY_TOPIC_ENTITY_PREFIX + aTopic + PolicyProperties.PROPERTY_TOPIC_EVENTS_SUFFIX); - - if (eventClasses == null || eventClasses.isEmpty()) { - // TODO warn - continue; - } - - List classes2Filters = new ArrayList(); - - List aTopicClasses = - new ArrayList(Arrays.asList(eventClasses.split("\\s*,\\s*"))); - - for (String aClass: aTopicClasses) { - - - // 4. third, for each coder class, get the list of field filters - - String filter = properties.getProperty - (PROPERTY_TOPIC_ENTITY_PREFIX + - aTopic + - PolicyProperties.PROPERTY_TOPIC_EVENTS_SUFFIX + - "." + aClass + - PolicyProperties.PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX); - - List> filters = new ArrayList>(); - - if (filter == null || filter.isEmpty()) { - // 4. topic -> class -> with no filters - - JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters); - PotentialCoderFilter class2Filters = - new PotentialCoderFilter(aClass, protocolFilter); - classes2Filters.add(class2Filters); - continue; - } - - // There are filters associated with the applicability of - // this class for decoding. - List listOfFilters = - new ArrayList(Arrays.asList(filter.split("\\s*,\\s*"))); - - for (String nameValue: listOfFilters) { - String fieldName; - String regexValue; - - String[] nameValueSplit = nameValue.split("\\s*=\\s*"); - if (nameValueSplit.length <= 0 || nameValueSplit.length > 2) { - // TODO warn - // skip - continue; - } - - if (nameValueSplit.length == 2) { - fieldName = nameValueSplit[0]; - regexValue = nameValueSplit[1]; - } else if (nameValueSplit.length == 1) { - fieldName = nameValueSplit[0]; - regexValue = null; - } else { - // unreachable - continue; - } - - filters.add(new Pair(fieldName, regexValue)); - } - - JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters); - PotentialCoderFilter class2Filters = - new PotentialCoderFilter(aClass, protocolFilter); - classes2Filters.add(class2Filters); - } - - TopicCoderFilterConfiguration topic2Classes2Filters = - new TopicCoderFilterConfiguration(aTopic,classes2Filters, customGsonCoder, customJacksonCoder); - topics2DecodedClasses2Filters.add(topic2Classes2Filters); - } - - return topics2DecodedClasses2Filters; - } - - /** - * {@inheritDoc} - * @param decoderConfiguration - */ - @Override - public DroolsController build(String newGroupId, - String newArtifactId, - String newVersion, - List decoderConfigurations, - List encoderConfigurations) - throws IllegalArgumentException, LinkageError, Exception { - - if (newGroupId == null || newArtifactId == null || newVersion == null || - newGroupId.isEmpty() || newArtifactId.isEmpty() || newVersion.isEmpty()) { - throw new IllegalArgumentException("Missing maven coordinates: " + - newGroupId + ":" + newArtifactId + ":" + - newVersion); - } - - 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; - } - - /** - * {@inheritDoc} - */ - @Override - public void destroy(DroolsController controller) throws IllegalArgumentException { - unmanage(controller); - controller.halt(); - } - - /** - * {@inheritDoc} - */ - @Override - public void destroy() { - List controllers = this.inventory(); - for (DroolsController controller: controllers) { - controller.halt(); - } - - synchronized(this) { - this.droolsControllers.clear(); - } - } - - /** - * unmanage the drools controller - * - * @param controller - * @return - * @throws IllegalArgumentException - */ - protected void unmanage(DroolsController controller) throws IllegalArgumentException { - if (controller == null) { - throw new IllegalArgumentException("No controller provided"); - } - - if (!controller.isBrained()) { - logger.info("Drools Controller is NOT OPERATIONAL - nothing to destroy"); - return; - } - - String controllerId = controller.getGroupId() + ":" + controller.getArtifactId(); - synchronized(this) { - if (!this.droolsControllers.containsKey(controllerId)) { - return; - } - - droolsControllers.remove(controllerId); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void shutdown(DroolsController controller) throws IllegalArgumentException { - this.unmanage(controller); - controller.shutdown(); - } - - /** - * {@inheritDoc} - */ - @Override - public void shutdown() { - List controllers = this.inventory(); - for (DroolsController controller: controllers) { - controller.shutdown(); - } - - synchronized(this) { - this.droolsControllers.clear(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public DroolsController get(String groupId, - String artifactId, - String version) - throws IllegalArgumentException, IllegalStateException { - - if (groupId == null || artifactId == null || - groupId.isEmpty() || artifactId.isEmpty()) { - throw new IllegalArgumentException("Missing maven coordinates: " + - groupId + ":" + artifactId); - } - - String controllerId = groupId + ":" + artifactId; - - synchronized(this) { - if (this.droolsControllers.containsKey(controllerId)) { - return droolsControllers.get(controllerId); - } else { - throw new IllegalStateException("DroolController for " + - controllerId + " not found"); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public List inventory() { - List controllers = - new ArrayList(this.droolsControllers.values()); - return controllers; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("IndexedDroolsControllerFactory [#droolsControllers=").append(droolsControllers.size()) - .append("]"); - return builder.toString(); - } - -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java b/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java deleted file mode 100644 index 4eacbd1c..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java +++ /dev/null @@ -1,910 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.controller.internal; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.collections4.queue.CircularFifoQueue; -import org.drools.core.ClassObjectFilter; -import org.kie.api.definition.KiePackage; -import org.kie.api.definition.rule.Query; -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.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.openecomp.policy.drools.controller.DroolsController; -import org.openecomp.policy.drools.core.PolicyContainer; -import org.openecomp.policy.drools.core.PolicySession; -import org.openecomp.policy.drools.core.jmx.PdpJmx; -import org.openecomp.policy.drools.event.comm.TopicSink; -import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder; -import org.openecomp.policy.drools.protocol.coders.JsonProtocolFilter; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter; -import org.openecomp.policy.drools.utils.ReflectionUtil; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Maven-based Drools Controller that interacts with the - * policy-core PolicyContainer and PolicySession to manage - * 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 decoderConfigurations; - - /** - * list of topics, each with associated encoder classes, each - * with a list of associated filters. - */ - protected List encoderConfigurations; - - /** - * recent source events processed - */ - protected final CircularFifoQueue recentSourceEvents = new CircularFifoQueue(10); - - /** - * recent sink events processed - */ - protected final CircularFifoQueue 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 decoderConfiguration list of topic -> decoders -> filters mapping - * @param encoderConfiguration list of topic -> encoders -> filters mapping - * - * @throws IllegalArgumentException invalid arguments passed in - */ - public MavenDroolsController(String groupId, - String artifactId, - String version, - List decoderConfigurations, - List encoderConfigurations) - throws IllegalArgumentException { - - if (logger.isInfoEnabled()) - logger.info("DROOLS CONTROLLER: instantiation " + this + - " -> {" + groupId + ":" + artifactId + ":" + version + "}"); - - if (groupId == null || artifactId == null || version == null || - groupId.isEmpty() || artifactId.isEmpty() || version.isEmpty()) { - throw new IllegalArgumentException("Missing maven coordinates: " + - groupId + ":" + artifactId + ":" + - version); - } - - this.policyContainer= new PolicyContainer(groupId, artifactId, version); - this.init(decoderConfigurations, encoderConfigurations); - - if (logger.isInfoEnabled()) - logger.info("DROOLS CONTROLLER: instantiation completed " + this); - } - - /** - * init encoding/decoding configuration - * @param decoderConfiguration list of topic -> decoders -> filters mapping - * @param encoderConfiguration list of topic -> encoders -> filters mapping - */ - protected void init(List decoderConfigurations, - List encoderConfigurations) { - - this.decoderConfigurations = decoderConfigurations; - this.encoderConfigurations = encoderConfigurations; - - this.initCoders(decoderConfigurations, true); - this.initCoders(encoderConfigurations, false); - - this.modelClassLoaderHash = this.policyContainer.getClassLoader().hashCode(); - } - - /** - * {@inheritDoc} - */ - @Override - public void updateToVersion(String newGroupId, String newArtifactId, String newVersion, - List decoderConfigurations, - List encoderConfigurations) - throws IllegalArgumentException, LinkageError, Exception { - - if (logger.isInfoEnabled()) - logger.info("UPDATE-TO-VERSION: " + this + " -> {" + newGroupId + ":" + newArtifactId + ":" + newVersion + "}"); - - if (newGroupId == null || newArtifactId == null || newVersion == null || - newGroupId.isEmpty() || newArtifactId.isEmpty() || newVersion.isEmpty()) { - throw new IllegalArgumentException("Missing maven coordinates: " + - newGroupId + ":" + newArtifactId + ":" + - newVersion); - } - - 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 decoderConfiguration list of topic -> decoders -> filters mapping - */ - protected void initCoders(List coderConfigurations, - boolean decoder) - throws IllegalArgumentException { - - 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)) { - logger.error(customGsonCoderClass + " cannot be retrieved"); - throw new IllegalArgumentException(customGsonCoderClass + " cannot be retrieved"); - } else { - if (logger.isInfoEnabled()) - logger.info("CLASS FETCHED " + 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)) { - logger.error(customJacksonCoderClass + " cannot be retrieved"); - throw new IllegalArgumentException(customJacksonCoderClass + " cannot be retrieved"); - } else { - if (logger.isInfoEnabled()) - logger.info("CLASS FETCHED " + customJacksonCoderClass); - } - } - - List 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)) { - logger.error(potentialCodedClass + " cannot be retrieved"); - throw new IllegalArgumentException(potentialCodedClass + " cannot be retrieved"); - } else { - if (logger.isInfoEnabled()) - logger.info("CLASS FETCHED " + 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()); - } - } - } - - - /** - * remove decoders. - */ - protected void removeDecoders() - throws IllegalArgumentException { - 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() - throws IllegalArgumentException { - - 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); - } - } - - - /** - * {@inheritDoc} - */ - @Override - public boolean ownsCoder(Class coderClass, int modelHash) throws IllegalStateException { - 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; - } - } - - /** - * {@inheritDoc} - */ - @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(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean stop() { - - logger.info("STOP: " + this); - - synchronized (this) { - if (!this.alive) - return true; - - this.alive = false; - } - - return this.policyContainer.stop(); - } - - - /** - * {@inheritDoc} - */ - @Override - public void shutdown() throws IllegalStateException { - 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(); - } - - } - - - /** - * {@inheritDoc} - */ - @Override - public void halt() throws IllegalStateException { - 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); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isAlive() { - return this.alive; - } - - /** - * {@inheritDoc} - */ - @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().size() <= 0) { - // 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()); - - if (!this.policyContainer.insertAll(anEvent)) - logger.warn(this + "Failed to inject into PolicyContainer " + this.getSessionNames()); - - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean deliver(TopicSink sink, Object event) - throws IllegalArgumentException, - IllegalStateException, - UnsupportedOperationException { - - 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); - - } - - /** - * {@inheritDoc} - */ - @Override - public String getVersion() { - return this.policyContainer.getVersion(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getArtifactId() { - return this.policyContainer.getArtifactId(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getGroupId() { - return this.policyContainer.getGroupId(); - } - - /** - * @return the modelClassLoaderHash - */ - public int getModelClassLoaderHash() { - return modelClassLoaderHash; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized boolean lock() { - logger.info("LOCK: " + this); - - this.locked = true; - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized boolean unlock() { - logger.info("UNLOCK: " + this); - - this.locked = false; - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isLocked() { - return this.locked; - } - - /** - * {@inheritDoc} - */ - @JsonIgnore - public PolicyContainer getContainer() { - return this.policyContainer; - } - - /** - * {@inheritDoc} - */ - @JsonProperty("sessions") - @Override - public List getSessionNames() { - return getSessionNames(true); - } - - /** - * {@inheritDoc} - */ - @JsonProperty("sessionCoordinates") - @Override - public List getCanonicalSessionNames() { - return getSessionNames(false); - } - - /** - * get session names - * @param abbreviated true for the short form, otherwise the long form - * @return session names - */ - protected List getSessionNames(boolean abbreviated) { - List 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 getSessions() { - List 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 sessions = this.getSessions(); - for (PolicySession session : sessions) { - if (sessionName.equals(session.getName()) || sessionName.equals(session.getName())) - return session; - } - - throw new IllegalArgumentException("Invalid Session Name: " + sessionName); - } - - /** - * {@inheritDoc} - */ - @Override - public Map factClassNames(String sessionName) throws IllegalArgumentException { - if (sessionName == null || sessionName.isEmpty()) - throw new IllegalArgumentException("Invalid Session Name: " + sessionName); - - // List classNames = new ArrayList<>(); - Map classNames = new HashMap<>(); - - PolicySession session = getSession(sessionName); - KieSession kieSession = session.getKieSession(); - - Collection 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) { - if (logger.isInfoEnabled()) - logger.info("Object cannot be retrieved from fact: " + fact); - } - } - - return classNames; - } - - /** - * {@inheritDoc} - */ - @Override - public long factCount(String sessionName) throws IllegalArgumentException { - if (sessionName == null || sessionName.isEmpty()) - throw new IllegalArgumentException("Invalid Session Name: " + sessionName); - - PolicySession session = getSession(sessionName); - return session.getKieSession().getFactCount(); - } - - /** - * {@inheritDoc} - */ - @Override - public List facts(String sessionName, String className, boolean delete) { - if (sessionName == null || sessionName.isEmpty()) - throw new IllegalArgumentException("Invalid Session Name: " + 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 factObjects = new ArrayList<>(); - - Collection factHandles = kieSession.getFactHandles(new ClassObjectFilter(factClass)); - for (FactHandle factHandle : factHandles) { - try { - factObjects.add(kieSession.getObject(factHandle)); - if (delete) - kieSession.delete(factHandle); - } catch (Exception e) { - if (logger.isInfoEnabled()) - logger.info("Object cannot be retrieved from fact: " + factHandle); - } - } - - return factObjects; - } - - /** - * {@inheritDoc} - */ - @Override - public List factQuery(String sessionName, String queryName, String queriedEntity, boolean delete, Object... queryParams) { - if (sessionName == null || sessionName.isEmpty()) - throw new IllegalArgumentException("Invalid Session Name: " + 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 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) { - if (logger.isInfoEnabled()) - logger.info("Object cannot be retrieved from fact: " + row); - } - } - - return factObjects; - } - - /** - * {@inheritDoc} - */ - @Override - public Class fetchModelClass(String className) throws IllegalStateException { - Class modelClass = - ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className); - return modelClass; - } - - /** - * @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); - } - } - - - /** - * {@inheritDoc} - */ - @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/openecomp/policy/drools/controller/internal/NullDroolsController.java b/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/NullDroolsController.java deleted file mode 100644 index 7f5d4665..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/NullDroolsController.java +++ /dev/null @@ -1,262 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.controller.internal; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.openecomp.policy.drools.controller.DroolsController; -import org.openecomp.policy.drools.core.PolicyContainer; -import org.openecomp.policy.drools.event.comm.TopicSink; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration; - -/** - * no-op Drools Controller - */ -public class NullDroolsController implements DroolsController { - - /** - * {@inheritDoc} - */ - @Override - public boolean start() throws IllegalStateException { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean stop() throws IllegalStateException { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public void shutdown() throws IllegalStateException { - return; - } - - /** - * {@inheritDoc} - */ - @Override - public void halt() throws IllegalStateException { - return; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isAlive() { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean lock() { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean unlock() { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isLocked() { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public String getGroupId() { - return NO_GROUP_ID; - } - - /** - * {@inheritDoc} - */ - @Override - public String getArtifactId() { - return NO_ARTIFACT_ID; - } - - /** - * {@inheritDoc} - */ - @Override - public String getVersion() { - return NO_VERSION; - } - - /** - * {@inheritDoc} - */ - @Override - public List getSessionNames() { - return new ArrayList(); - } - - /** - * {@inheritDoc} - */ - @Override - public List getCanonicalSessionNames() { - return new ArrayList(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean offer(String topic, String event) { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean deliver(TopicSink sink, Object event) - throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { - throw new IllegalStateException(this.getClass().getCanonicalName() + " invoked"); - } - - /** - * {@inheritDoc} - */ - @Override - public Object[] getRecentSourceEvents() { - return new String[0]; - } - - /** - * {@inheritDoc} - */ - @Override - public PolicyContainer getContainer() { - return null; - } - - /** - * {@inheritDoc} - */ - @Override - public String[] getRecentSinkEvents() { - return new String[0]; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean ownsCoder(Class coderClass, int modelHash) throws IllegalStateException { - throw new IllegalStateException(this.getClass().getCanonicalName() + " invoked"); - } - - /** - * {@inheritDoc} - */ - @Override - public Class fetchModelClass(String className) throws IllegalArgumentException { - throw new IllegalArgumentException(this.getClass().getCanonicalName() + " invoked"); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isBrained() { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("NullDroolsController []"); - return builder.toString(); - } - - /** - * {@inheritDoc} - */ - @Override - public void updateToVersion(String newGroupId, String newArtifactId, String newVersion, - List decoderConfigurations, - List encoderConfigurations) - throws IllegalArgumentException, LinkageError, Exception { - throw new IllegalArgumentException(this.getClass().getCanonicalName() + " invoked"); - } - - /** - * {@inheritDoc} - */ - @Override - public Map factClassNames(String sessionName) - throws IllegalArgumentException { - return new HashMap(); - } - - /** - * {@inheritDoc} - */ - @Override - public long factCount(String sessionName) throws IllegalArgumentException { - return 0; - } - - /** - * {@inheritDoc} - */ - @Override - public List facts(String sessionName, String className, boolean delete) { - return new ArrayList(); - } - - /** - * {@inheritDoc} - */ - @Override - public List factQuery(String sessionName, String queryName, - String queriedEntity, - boolean delete, Object... queryParams) { - return new ArrayList(); - } -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/features/PolicyControllerFeatureAPI.java b/policy-management/src/main/java/org/openecomp/policy/drools/features/PolicyControllerFeatureAPI.java deleted file mode 100644 index 66f64a82..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/features/PolicyControllerFeatureAPI.java +++ /dev/null @@ -1,222 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.features; - -import java.util.Properties; - -import org.openecomp.policy.drools.event.comm.Topic.CommInfrastructure; -import org.openecomp.policy.drools.system.PolicyController; -import org.openecomp.policy.drools.utils.OrderedService; -import org.openecomp.policy.drools.utils.OrderedServiceImpl; - -public interface PolicyControllerFeatureAPI extends OrderedService { - - /** - * 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 providers = - new OrderedServiceImpl(PolicyControllerFeatureAPI.class); -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/features/PolicyEngineFeatureAPI.java b/policy-management/src/main/java/org/openecomp/policy/drools/features/PolicyEngineFeatureAPI.java deleted file mode 100644 index df2ddd6f..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/features/PolicyEngineFeatureAPI.java +++ /dev/null @@ -1,202 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-engine - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.features; - -import java.util.Properties; - -import org.openecomp.policy.drools.system.PolicyEngine; -import org.openecomp.policy.drools.utils.OrderedService; -import org.openecomp.policy.drools.utils.OrderedServiceImpl; - -/** - * Policy Engine Feature API. - * Provides Interception Points during the Policy Engine lifecycle. - */ -public interface PolicyEngineFeatureAPI extends OrderedService { - - /** - * 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;}; - - /** - * Feature providers implementing this interface - */ - public static final OrderedServiceImpl providers = - new OrderedServiceImpl<>(PolicyEngineFeatureAPI.class); -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/persistence/SystemPersistence.java b/policy-management/src/main/java/org/openecomp/policy/drools/persistence/SystemPersistence.java deleted file mode 100644 index dda20a08..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/persistence/SystemPersistence.java +++ /dev/null @@ -1,248 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.persistence; - -import java.io.File; -import java.io.FileWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.Properties; - -import org.openecomp.policy.drools.utils.PropertyUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public interface SystemPersistence { - - /** - * configuration directory - */ - public static String CONFIG_DIR_NAME = "config"; - - /** - * policy controllers suffix - */ - public final static String CONTROLLER_SUFFIX_IDENTIFIER = "-controller"; - - /** - * policy controller properties file suffix - */ - public final static String PROPERTIES_FILE_CONTROLLER_SUFFIX = - CONTROLLER_SUFFIX_IDENTIFIER + ".properties"; - - /** - * policy engine properties file name - */ - public final static String PROPERTIES_FILE_ENGINE = "policy-engine.properties"; - - - /** - * 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) - throws IllegalArgumentException; - - /** - * 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) - throws IllegalArgumentException; - - /** - * 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) throws IllegalArgumentException; - - /** - * 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 SystemPropertiesPersistence(); -} - -/** - * Properties based Persistence - */ -class SystemPropertiesPersistence implements SystemPersistence { - - /** - * logger - */ - private static Logger logger = LoggerFactory.getLogger(SystemPropertiesPersistence.class); - - /** - * backs up the properties-based controller configuration - * @param controllerName the controller name - * @return true if the configuration is backed up in disk or back up does not apply, false otherwise. - */ - @Override - public boolean backupController(String controllerName) { - Path controllerPropertiesPath = - Paths.get(CONFIG_DIR_NAME, controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX); - - if (Files.exists(controllerPropertiesPath)) { - try { - logger.warn("There is an existing configuration file at " + - controllerPropertiesPath.toString() + - " with contents: " + Files.readAllBytes(controllerPropertiesPath)); - Path controllerPropertiesBakPath = - Paths.get(CONFIG_DIR_NAME, controllerName + - PROPERTIES_FILE_CONTROLLER_SUFFIX + ".bak"); - Files.copy(controllerPropertiesPath, - controllerPropertiesBakPath, StandardCopyOption.REPLACE_EXISTING); - } catch (Exception e) { - logger.warn("{}: cannot be backed up", controllerName, e); - return false; - } - } - - return true; - } - - /** - * persists properties-based controller configuration and makes a backup if necessary - * @param controllerName the controller name - * @return true if the properties has been stored in disk, false otherwise - */ - @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"); - } - - Properties properties = (Properties) configuration; - - Path controllerPropertiesPath = - Paths.get(CONFIG_DIR_NAME, controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX); - if (Files.exists(controllerPropertiesPath)) { - try { - Properties oldProperties = PropertyUtil.getProperties(controllerPropertiesPath.toFile()); - if (oldProperties.equals(properties)) { - logger.info("A properties file with the same contents already exists for controller " + - controllerName + - ". No action is taken"); - return true; - } else { - this.backupController(controllerName); - } - } catch (Exception e) { - logger.info("{}: no existing Properties", controllerName); - // continue - } - } - - try { - File controllerPropertiesFile = controllerPropertiesPath.toFile(); - FileWriter writer = new FileWriter(controllerPropertiesFile); - properties.store(writer, "Machine created Policy Controller Configuration"); - } catch (Exception e) { - logger.warn("{}: cannot be STORED", controllerName, e); - return false; - } - - return true; - } - - /** - * deletes properties-based controller configuration - * @param controllerName the controller name - * @return true if the properties has been deleted from disk, false otherwise - */ - @Override - public boolean deleteController(String controllerName) { - - Path controllerPropertiesPath = - Paths.get(CONFIG_DIR_NAME, - controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX); - - if (Files.exists(controllerPropertiesPath)) { - try { - Path controllerPropertiesBakPath = - Paths.get(CONFIG_DIR_NAME, controllerName + - PROPERTIES_FILE_CONTROLLER_SUFFIX + ".bak"); - Files.move(controllerPropertiesPath, - controllerPropertiesBakPath, - StandardCopyOption.REPLACE_EXISTING); - } catch (Exception e) { - logger.warn("{}: cannot be DELETED", controllerName, e); - return false; - } - } - - return true; - } - - @Override - public Properties getControllerProperties(String controllerName) throws IllegalArgumentException { - return this.getProperties(controllerName + CONTROLLER_SUFFIX_IDENTIFIER); - } - - @Override - public Properties getProperties(String name) throws IllegalArgumentException { - Path propertiesPath = - Paths.get(CONFIG_DIR_NAME, name + ".properties"); - - if (!Files.exists(propertiesPath)) { - throw new IllegalArgumentException("properties for " + name + " are not persisted."); - } - - try { - return PropertyUtil.getProperties(propertiesPath.toFile()); - } catch (Exception e) { - logger.warn("{}: can't read properties @ {}", name, propertiesPath); - throw new IllegalArgumentException("can't read properties for " + - name + " @ " + - propertiesPath); - } - } -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java deleted file mode 100644 index 819ee812..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java +++ /dev/null @@ -1,1393 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.protocol.coders; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.openecomp.policy.drools.controller.DroolsController; -import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; -import org.openecomp.policy.drools.utils.Pair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Coder (Encoder/Decoder) of Events. - */ -public interface EventProtocolCoder { - - 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 synchronized JsonProtocolFilter getFilter() { - return filter; - } - - /** - * @param filter the filter to set - */ - public synchronized 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) - throws IllegalArgumentException; - - /** - * 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) throws IllegalArgumentException; - - /** - * 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) throws IllegalArgumentException; - - /** - * 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 getDecoderFilters(String groupId, String artifactId, String topic) - throws IllegalArgumentException; - - - /** - * 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) - throws IllegalArgumentException; - - /** - * 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 getDecoders(String groupId, String artifactId) - throws IllegalArgumentException; - - - /** - * 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 getDecoderFilters(String groupId, String artifactId) throws IllegalArgumentException; - - - /** - * 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 getEncoderFilters(String groupId, String artifactId, String topic) - throws IllegalArgumentException; - - /** - * 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 getEncoderFilters(String groupId, String artifactId) throws IllegalArgumentException; - - /** - * 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) - throws IllegalArgumentException; - - /** - * 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) - throws IllegalArgumentException; - - /** - * 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) - throws IllegalArgumentException; - - /** - * get encoder based on topic and encoded class - * - * @param topic topic - * @param encodedClass encoded class - * @return - * @throws IllegalArgumentException invalid arguments passed in - */ - public List getReverseEncoderFilters(String topic, String encodedClass) - throws IllegalArgumentException; - - /** - * 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) - throws IllegalArgumentException; - - /** - * 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 getDroolsControllers(String topic, Object encodedClass) - throws IllegalArgumentException; - - /** - * 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) - throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException; - - /** - * 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) - throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; - - /** - * 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) - throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; - - /** - * 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) - throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; - - /** - * singleton reference to the global event protocol coder - */ - public static EventProtocolCoder manager = new MultiplexorEventProtocolCoder(); -} - -/** - * Protocol Coder that does its best attempt to decode/encode, selecting the best - * class and best fitted json parsing tools. - */ -class MultiplexorEventProtocolCoder implements EventProtocolCoder { - /** - * Logger - */ - private static Logger logger = LoggerFactory.getLogger(MultiplexorEventProtocolCoder.class); - - /** - * Decoders - */ - protected EventProtocolDecoder decoders = new EventProtocolDecoder(); - - /** - * Encoders - */ - protected EventProtocolEncoder encoders = new EventProtocolEncoder(); - - - /** - * {@inheritDoc} - */ - @Override - public void addDecoder(String groupId, String artifactId, String topic, - String eventClass, - JsonProtocolFilter protocolFilter, - CustomGsonCoder customGsonCoder, - CustomJacksonCoder customJacksonCoder, - int modelClassLoaderHash) - throws IllegalArgumentException { - 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) - throws IllegalArgumentException { - 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) - throws IllegalArgumentException { - 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) - throws IllegalArgumentException { - 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) - throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { - 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) - throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { - 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) - throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { - logger.debug("{}: encode {}:{}", this, topic, event); - return this.encoders.encode(topic, event); - } - - /** - * {@inheritDoc} - */ - @Override - public String encode(String topic, Object event, DroolsController droolsController) - throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { - logger.debug("{}: encode {}:{}:{}", this, topic, event, droolsController); - return this.encoders.encode(topic, event, droolsController); - } - - /** - * {@inheritDoc} - */ - @Override - public List getDecoderFilters(String groupId, String artifactId, String topic) - throws IllegalArgumentException { - return this.decoders.getFilters(groupId, artifactId, topic); - } - - /** - * {@inheritDoc} - */ - @Override - public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) - throws IllegalArgumentException { - Pair 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 getEncoderFilters(String groupId, String artifactId, String topic) - throws IllegalArgumentException { - return this.encoders.getFilters(groupId, artifactId, topic); - } - - /** - * {@inheritDoc} - */ - @Override - public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname) - throws IllegalArgumentException { - return this.decoders.getFilters(groupId, artifactId, topic, classname); - } - - /** - * {@inheritDoc} - */ - @Override - public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname) - throws IllegalArgumentException { - return this.encoders.getFilters(groupId, artifactId, topic, classname); - } - - /** - * {@inheritDoc} - */ - @Override - public List getReverseEncoderFilters(String topic, String encodedClass) throws IllegalArgumentException { - 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 getDecoders(String groupId, String artifactId) - throws IllegalArgumentException { - - List> decoderToolsets = this.decoders.getCoders(groupId, artifactId); - if (decoderToolsets == null) - throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId); - - List parser1CoderToolset = new ArrayList<>(); - for (Pair coderToolsetPair : decoderToolsets) { - parser1CoderToolset.add(coderToolsetPair.first()); - } - - return parser1CoderToolset; - } - - /** - * {@inheritDoc} - */ - @Override - public List getDecoderFilters(String groupId, String artifactId) throws IllegalArgumentException { - return this.decoders.getFilters(groupId, artifactId); - - } - - /** - * {@inheritDoc} - */ - @Override - public List getEncoderFilters(String groupId, String artifactId) throws IllegalArgumentException { - return this.encoders.getFilters(groupId, artifactId); - } - - /** - * {@inheritDoc} - */ - @Override - public DroolsController getDroolsController(String topic, Object encodedClass) throws IllegalArgumentException { - return this.encoders.getDroolsController(topic, encodedClass); - } - - /** - * {@inheritDoc} - */ - @Override - public List getDroolsControllers(String topic, Object encodedClass) throws IllegalArgumentException { - 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(); - } -} - -/** - * This protocol Coder that does its best attempt to decode/encode, selecting the best - * class and best fitted json parsing tools. - */ -abstract class GenericEventProtocolCoder { - private static Logger logger = LoggerFactory.getLogger(GenericEventProtocolCoder.class); - - /** - * Mapping topic:controller-id -> - * 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> coders = - new HashMap>(); - - /** - * Mapping topic + classname -> Protocol Set - */ - protected final HashMap>> 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) - throws IllegalArgumentException { - if (groupId == null || groupId.isEmpty()) { - throw new IllegalArgumentException("Invalid group id"); - } - - if (artifactId == null || artifactId.isEmpty()) - throw new IllegalArgumentException("Invalid artifact id"); - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Invalid Topic"); - - 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 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> 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 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> toolsets = - reverseCoders.get(reverseKey); - boolean present = false; - for (Pair 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> 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) - throws IllegalArgumentException { - - if (groupId == null || groupId.isEmpty()) - throw new IllegalArgumentException("Invalid group id"); - - if (artifactId == null || artifactId.isEmpty()) - throw new IllegalArgumentException("Invalid artifact id"); - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Invalid Topic"); - - String key = this.codersKey(groupId, artifactId, topic); - - synchronized(this) { - if (coders.containsKey(key)) { - Pair 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> toolsets = - this.reverseCoders.get(reverseKey); - Iterator> toolsetsIter = - toolsets.iterator(); - while (toolsetsIter.hasNext()) { - Pair 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"); - - if (artifactId == null || artifactId.isEmpty()) - throw new IllegalArgumentException("Invalid artifact id"); - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Invalid Topic"); - - 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) - throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { - - if (!isCodingSupported(groupId, artifactId, topic)) - throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic) + " for encoding"); - - String key = this.codersKey(groupId, artifactId, topic); - Pair 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) - throws IllegalArgumentException, UnsupportedOperationException { - - 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) - throws IllegalArgumentException, UnsupportedOperationException { - - logger.debug("{}: encode for {}: {}", this, key, event); - - Pair 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) - throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { - - if (event == null) - throw new IllegalArgumentException("Invalid encoded class"); - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Invalid topic"); - - List droolsControllers = droolsCreators(topic, event); - - if (droolsControllers.isEmpty()) - throw new IllegalArgumentException("no drools controller has been found"); - - if (droolsControllers.size() > 1) { - logger.warn("{}: multiple drools-controller {} for {}:{} ", this, topic, - droolsControllers, event.getClass().getCanonicalName()); - // continue - } - - String key = codersKey(droolsControllers.get(0).getGroupId(), droolsControllers.get(0).getArtifactId(), topic); - return this.encodeInternal(key, event); - } - - /** - * encode an object into a json string - * - * @param topic topic - * @param encodedClass object to convert to string - * @return the json string - * @throws IllegalArgumentException if invalid argument is provided - * @throws UnsupportedOperationException if the operation cannot be performed - */ - public String encode(String topic, Object encodedClass, DroolsController droolsController) - throws IllegalArgumentException, IllegalArgumentException, UnsupportedOperationException { - - 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 droolsCreators(String topic, Object encodedClass) - throws IllegalStateException, IllegalArgumentException { - - List 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> - toolsets = this.reverseCoders.get(reverseKey); - - // There must be multiple toolset pairs associated with 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 encoderSet : toolsets) { - // figure out the right toolset - String groupId = encoderSet.first().getGroupId(); - String artifactId = encoderSet.first().getArtifactId(); - List coders = encoderSet.first().getCoders(); - for (CoderFilters coder : coders) { - 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 getFilters(String groupId, String artifactId, String topic) - throws IllegalArgumentException { - - if (!isCodingSupported(groupId, artifactId, topic)) - throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic)); - - String key = this.codersKey(groupId, artifactId, topic); - Pair 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 getCoders(String groupId, String artifactId, String topic) - throws IllegalArgumentException { - - if (!isCodingSupported(groupId, artifactId, topic)) - throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic)); - - String key = this.codersKey(groupId, artifactId, topic); - Pair coderTools = coders.get(key); - return coderTools; - } - - /** - * 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 getFilters(String groupId, String artifactId) - throws IllegalArgumentException { - - if (groupId == null || groupId.isEmpty()) - throw new IllegalArgumentException("Invalid group id"); - - if (artifactId == null || artifactId.isEmpty()) - throw new IllegalArgumentException("Invalid artifact id"); - - String key = this.codersKey(groupId, artifactId, ""); - - List codersFilters = new ArrayList(); - for (Map.Entry> 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> getCoders(String groupId, String artifactId) - throws IllegalArgumentException { - - if (groupId == null || groupId.isEmpty()) - throw new IllegalArgumentException("Invalid group id"); - - if (artifactId == null || artifactId.isEmpty()) - throw new IllegalArgumentException("Invalid artifact id"); - - String key = this.codersKey(groupId, artifactId, ""); - - List> coderToolset = new ArrayList>(); - for (Map.Entry> 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) - throws IllegalArgumentException { - - 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 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 getReverseFilters(String topic, String codedClass) - throws IllegalArgumentException { - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Unsupported"); - - if (codedClass == null) - throw new IllegalArgumentException("class must be provided"); - - String key = this.reverseCodersKey(topic, codedClass); - List> toolsets = this.reverseCoders.get(key); - if (toolsets == null) - throw new IllegalArgumentException("No Coder found for " + key); - - - List coders = new ArrayList(); - for (Pair toolset: toolsets) { - coders.addAll(toolset.first().getCoders()); - } - - return coders; - } - - /** - * returns group and artifact id of the creator of the encoder - * - * @param topic - * @param fact - * @return - * @throws IllegalArgumentException - */ - DroolsController getDroolsController(String topic, Object fact) - throws IllegalArgumentException { - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Unsupported"); - - if (fact == null) - throw new IllegalArgumentException("class must be provided"); - - List 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 getDroolsControllers(String topic, Object fact) - throws IllegalArgumentException { - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Unsupported"); - - if (fact == null) - throw new IllegalArgumentException("class must be provided"); - - List 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(); - } - -} - -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(); - } -} \ No newline at end of file diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/JsonProtocolFilter.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/JsonProtocolFilter.java deleted file mode 100644 index 7831e7b8..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/JsonProtocolFilter.java +++ /dev/null @@ -1,308 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.protocol.coders; - -import java.util.ArrayList; -import java.util.List; - -import org.openecomp.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. Evaluates an JSON string and evaluates if it - * passes its filters. - */ -public class JsonProtocolFilter { - - /** - * Logger - */ - private static Logger logger = LoggerFactory.getLogger(JsonProtocolFilter.class); - - /** - * Helper class to collect Filter information - */ - public static class FilterRule { - /** - * Field name - */ - protected String name; - - /** - * Field Value regex - */ - protected String regex; - - /** - * Filter Constructor - * - * @param name field name - * @param regex field regex value - */ - public FilterRule(String name, String regex) { - this.name = name; - this.regex = 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) { - this.name = name; - } - - /** - * sets regex name - * @param regex - */ - public void setRegex(String 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 rules = new ArrayList(); - - /** - * - * @param rawFilters raw filter initialization - * - * @throws IllegalArgumentException an invalid input has been provided - */ - public static JsonProtocolFilter fromRawFilters(List> rawFilters) - throws IllegalArgumentException { - - if (rawFilters == null) { - throw new IllegalArgumentException("No raw filters provided"); - } - - List filters = new ArrayList(); - for (Pair filterPair: rawFilters) { - if (filterPair.first() == null || filterPair.first().isEmpty()) { - continue; - } - - filters.add(new FilterRule(filterPair.first(), filterPair.second())); - } - return new JsonProtocolFilter(filters); - } - - /** - * Create a Protocol Filter - * - * @throws IllegalArgumentException an invalid input has been provided - */ - public JsonProtocolFilter() throws IllegalArgumentException {} - - /** - * - * @param rawFilters raw filter initialization - * - * @throws IllegalArgumentException an invalid input has been provided - */ - public JsonProtocolFilter(List filters) throws IllegalArgumentException { - this.rules = 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 synchronized boolean accept(JsonElement json) throws IllegalArgumentException { - if (json == null) { - throw new IllegalArgumentException("no JSON provided"); - } - - if (rules.isEmpty()) { - return true; - } - - try { - if (!json.isJsonObject()) { - return false; - } - - JsonObject event = json.getAsJsonObject(); - for (FilterRule filter: rules) { - if (filter.regex == null || - filter.regex.isEmpty() || - filter.regex.equals(".*")) { - - // Only check for presence - if (!event.has(filter.name)) { - return false; - } - } else { - JsonElement field = event.get(filter.name); - if (field == null) { - return false; - } - - String fieldValue = field.getAsString(); - if (!fieldValue.matches(filter.regex)) { - 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 synchronized boolean accept(String json) throws IllegalArgumentException { - 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 getRules() { - return rules; - } - - public synchronized void setRules(List rulesFilters) { - this.rules = rulesFilters; - } - - public synchronized void deleteRules(String name) { - for (FilterRule rule : new ArrayList<>(this.rules)) { - if (rule.name.equals(name)) { - this.rules.remove(rule); - } - } - } - - public List getRules(String name) { - ArrayList temp = new ArrayList<>(); - for (FilterRule rule : new ArrayList<>(this.rules)) { - if (rule.name.equals(name)) { - temp.add(rule); - } - } - return temp; - } - - public synchronized void deleteRule(String name, String regex) { - for (FilterRule rule : new ArrayList<>(this.rules)) { - if (rule.name.equals(name) && rule.regex.equals(regex)) { - this.rules.remove(rule); - } - } - } - - public synchronized void addRule(String name, String regex) { - for (FilterRule rule : new ArrayList<>(this.rules)) { - if (rule.name.equals(name) && rule.regex.equals(regex)) { - return; - } - } - - this.rules.add(new FilterRule(name,regex)); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("JsonProtocolFilter [rules=").append(rules).append("]"); - return builder.toString(); - } - -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/ProtocolCoderToolset.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/ProtocolCoderToolset.java deleted file mode 100644 index bf7a43f3..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/ProtocolCoderToolset.java +++ /dev/null @@ -1,683 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.protocol.coders; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.time.Instant; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.openecomp.policy.drools.controller.DroolsController; -import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomCoder; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; -import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -/** - * Protocol Coding/Decoding Toolset - */ -public abstract class ProtocolCoderToolset { - - /** - * Logger - */ - private static Logger logger = LoggerFactory.getLogger(ProtocolCoderToolset.class); - - /** - * topic - */ - protected final String topic; - - /** - * controller id - */ - protected final String controllerId; - - /** - * group id - */ - protected final String groupId; - - /** - * artifact id - */ - protected final String artifactId; - - /** - * Protocols and associated Filters - */ - protected final List coders = new ArrayList(); - - /** - * Tree model (instead of class model) generic parsing to be able to inspect elements - */ - protected JsonParser filteringParser = new JsonParser(); - - /** - * custom coder - */ - protected CustomCoder customCoder; - - /** - * Constructor - * - * @param topic the topic - * @param controllerId the controller id - * @param codedClass the decoded class - * @param filters list of filters that apply to the - * selection of this decodedClass in case of multiplicity - * @throws IllegalArgumentException if invalid data has been passed in - */ - public ProtocolCoderToolset(String topic, - String controllerId, - String groupId, - String artifactId, - String codedClass, - JsonProtocolFilter filters, - CustomCoder customCoder, - int modelClassLoaderHash) - throws IllegalArgumentException { - - if (topic == null || controllerId == null || - groupId == null || artifactId == null || - codedClass == null || filters == null || - topic.isEmpty() || controllerId.isEmpty()) { - // TODO - throw new IllegalArgumentException("Invalid input"); - } - - this.topic = topic; - this.controllerId = controllerId; - this.groupId = groupId; - this.artifactId = artifactId; - this.coders.add(new CoderFilters(codedClass, filters, modelClassLoaderHash)); - this.customCoder = customCoder; - } - - /** - * gets the coder + filters associated with this class name - * - * @param classname class name - * @return the decoder filters or null if not found - */ - public CoderFilters getCoder(String classname) { - for (CoderFilters decoder: this.coders) { - if (decoder.factClass.equals(classname)) { - return decoder; - } - } - return null; - } - - /** - * get all coder filters in use - * - * @return coder filters - */ - public List getCoders() { - return this.coders; - } - - /** - * add coder or replace it exists - * - * @param eventClass decoder - * @param filter filter - */ - public void addCoder(String eventClass, JsonProtocolFilter filter, int modelClassLoaderHash) { - synchronized(this) { - for (CoderFilters coder: this.coders) { - if (coder.factClass.equals(eventClass)) { - // this is a better check than checking pointers, just - // in case classloader is different and this is just an update - coder.factClass = eventClass; - coder.filter = filter; - coder.modelClassLoaderHash = modelClassLoaderHash; - return; - } - } - } - - this.coders.add(new CoderFilters(eventClass, filter, modelClassLoaderHash)); - } - - /** - * remove coder - * - * @param eventClass decoder - * @param filter filter - */ - public void removeCoders(String eventClass) { - synchronized(this) { - Iterator codersIt = this.coders.iterator(); - while (codersIt.hasNext()) { - CoderFilters coder = codersIt.next(); - if (coder.factClass.equals(eventClass)) { - codersIt.remove(); - } - } - } - } - - /** - * gets the topic - * - * @return the topic - */ - public String getTopic() {return topic;} - - /** - * gets the controller id - * - * @return the controller id - */ - public String getControllerId() {return controllerId;} - - /** - * @return the groupId - */ - public String getGroupId() { - return groupId; - } - - /** - * @return the artifactId - */ - public String getArtifactId() { - return artifactId; - } - - /** - * @return the customCoder - */ - public CustomCoder getCustomCoder() { - return customCoder; - } - - /** - * @param customCoder the customCoder to set - */ - public void setCustomCoder(CustomCoder customCoder) { - this.customCoder = customCoder; - } - - /** - * performs filtering on a json string - * - * @param json json string - * @return the decoder that passes the filter, otherwise null - * @throws UnsupportedOperationException can't filter - * @throws IllegalArgumentException invalid input - */ - protected CoderFilters filter(String json) - throws UnsupportedOperationException, IllegalArgumentException, IllegalStateException { - - - // 1. Get list of decoding classes for this controller Id and topic - // 2. If there are no classes, return error - // 3. Otherwise, from the available classes for decoding, pick the first one that - // passes the filters - - // Don't parse if it is not necessary - - if (this.coders.isEmpty()) { - // TODO this is an error - throw new IllegalStateException("No coders available"); - } - - if (this.coders.size() == 1) { - JsonProtocolFilter filter = this.coders.get(0).getFilter(); - if (!filter.isRules()) { - return this.coders.get(0); - } - } - - JsonElement event; - try { - event = this.filteringParser.parse(json); - } catch (Exception e) { - throw new UnsupportedOperationException(e); - } - - for (CoderFilters decoder: this.coders) { - try { - boolean accepted = decoder.getFilter().accept(event); - if (accepted) { - return decoder; - } - } catch (Exception e) { - logger.info("{}: unexpected failure accepting {} because of {}", - this, event, e.getMessage(), e); - // continue - } - } - - return null; - } - - /** - * Decode json into a POJO object - * @param json json string - * - * @return a POJO object for the json string - * @throws IllegalArgumentException if an invalid parameter has been received - * @throws UnsupportedOperationException if parsing into POJO is not possible - */ - public abstract Object decode(String json) - throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException; - - /** - * Encodes a POJO object into a JSON String - * - * @param event JSON POJO event to be converted to String - * @return JSON string version of POJO object - * @throws IllegalArgumentException if an invalid parameter has been received - * @throws UnsupportedOperationException if parsing into POJO is not possible - */ - public abstract String encode(Object event) - throws IllegalArgumentException, UnsupportedOperationException; - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("ProtocolCoderToolset [topic=").append(topic).append(", controllerId=").append(controllerId) - .append(", groupId=").append(groupId).append(", artifactId=").append(artifactId).append(", coders=") - .append(coders).append(", filteringParser=").append(filteringParser).append(", customCoder=") - .append(customCoder).append("]"); - return builder.toString(); - } -} - -/** - * Tools used for encoding/decoding using Jackson - */ -class JacksonProtocolCoderToolset extends ProtocolCoderToolset { - private static Logger logger = LoggerFactory.getLogger(JacksonProtocolCoderToolset.class); - /** - * decoder - */ - @JsonIgnore - protected final ObjectMapper decoder = new ObjectMapper(); - - /** - * encoder - */ - @JsonIgnore - protected final ObjectMapper encoder = new ObjectMapper(); - - /** - * Toolset to encode/decode tools associated with a topic - * - * @param topic topic - * @param decodedClass decoded class of an event - * @param filter - */ - public JacksonProtocolCoderToolset(String topic, String controllerId, - String groupId, String artifactId, - String decodedClass, - JsonProtocolFilter filter, - CustomJacksonCoder customJacksonCoder, - int modelClassLoaderHash) { - super(topic, controllerId, groupId, artifactId, decodedClass, filter, customJacksonCoder, modelClassLoaderHash); - decoder.registerModule(new JavaTimeModule()); - decoder.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, - false); - } - - /** - * gets the Jackson decoder - * - * @return the Jackson decoder - */ - @JsonIgnore - protected ObjectMapper getDecoder() {return decoder;} - - /** - * gets the Jackson encoder - * - * @return the Jackson encoder - */ - @JsonIgnore - protected ObjectMapper getEncoder() {return encoder;} - - /** - * {@inheritDoc} - */ - @Override - public Object decode(String json) - throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { - - // 0. Use custom coder if available - - if (this.customCoder != null) { - throw new UnsupportedOperationException - ("Jackon Custom Decoder is not supported at this time"); - } - - DroolsController droolsController = - DroolsController.factory.get(groupId, artifactId, ""); - if (droolsController == null) { - logger.warn("{}: no drools-controller to process {}", this, json); - throw new IllegalStateException("no drools-controller to process event"); - } - - CoderFilters decoderFilter = filter(json); - if (decoderFilter == null) { - logger.debug("{}: no decoder to process {}", this, json); - throw new UnsupportedOperationException("no decoder to process event"); - } - - Class decoderClass; - try { - decoderClass = - droolsController.fetchModelClass(decoderFilter.getCodedClass()); - if (decoderClass == null) { - logger.warn("{}: cannot fetch application class {}", this, decoderFilter.getCodedClass()); - throw new IllegalStateException("cannot fetch application class " + decoderFilter.getCodedClass()); - } - } catch (Exception e) { - logger.warn("{}: cannot fetch application class {} because of {}", this, - decoderFilter.getCodedClass(), e.getMessage()); - throw new UnsupportedOperationException("cannot fetch application class " + decoderFilter.getCodedClass(), e); - } - - - try { - Object fact = this.decoder.readValue(json, decoderClass); - return fact; - } catch (Exception e) { - logger.warn("{} cannot decode {} into {} because of {}", - this, json, decoderClass.getName(), e.getMessage(), e); - throw new UnsupportedOperationException("cannont decode into " + decoderFilter.getCodedClass(), e); - } - } - - /** - * {@inheritDoc} - */ - @Override - public String encode(Object event) - throws IllegalArgumentException, UnsupportedOperationException { - - // 0. Use custom coder if available - - if (this.customCoder != null) { - throw new UnsupportedOperationException - ("Jackon Custom Encoder is not supported at this time"); - } - - try { - String encodedEvent = this.encoder.writeValueAsString(event); - return encodedEvent; - } catch (JsonProcessingException e) { - logger.error("{} cannot encode {} because of {}", this, event, e.getMessage(), e); - throw new UnsupportedOperationException("event cannot be encoded"); - } - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("JacksonProtocolCoderToolset [toString()=").append(super.toString()).append("]"); - return builder.toString(); - } - -} - -/** - * Tools used for encoding/decoding using Jackson - */ -class GsonProtocolCoderToolset extends ProtocolCoderToolset { - - /** - * Logger - */ - private static Logger logger = LoggerFactory.getLogger(GsonProtocolCoderToolset.class); - - /** - * Formatter for JSON encoding/decoding - */ - @JsonIgnore - public static DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSxxx"); - - @JsonIgnore - public static DateTimeFormatter zuluFormat = DateTimeFormatter.ISO_INSTANT; - - /** - * Adapter for ZonedDateTime - */ - - public static class GsonUTCAdapter implements JsonSerializer, JsonDeserializer { - - public ZonedDateTime deserialize(JsonElement element, Type type, JsonDeserializationContext context) - throws JsonParseException { - try { - return ZonedDateTime.parse(element.getAsString(), format); - } catch (Exception e) { - logger.info("GsonUTCAdapter: cannot parse {} because of {}", - element, e.getMessage(), e); - } - return null; - } - - public JsonElement serialize(ZonedDateTime datetime, Type type, JsonSerializationContext context) { - return new JsonPrimitive(datetime.format(format)); - } - } - - public static class GsonInstantAdapter implements JsonSerializer, JsonDeserializer { - - @Override - public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - return Instant.ofEpochMilli(json.getAsLong()); - } - - @Override - public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) { - return new JsonPrimitive(src.toEpochMilli()); - } - - } - - - /** - * decoder - */ - @JsonIgnore - protected final Gson decoder = new GsonBuilder().disableHtmlEscaping(). - registerTypeAdapter(ZonedDateTime.class, new GsonUTCAdapter()). - create(); - - /** - * encoder - */ - @JsonIgnore - protected final Gson encoder = new GsonBuilder().disableHtmlEscaping(). - registerTypeAdapter(ZonedDateTime.class, new GsonUTCAdapter()). - create(); - - /** - * Toolset to encode/decode tools associated with a topic - * - * @param topic topic - * @param decodedClass decoded class of an event - * @param filter - */ - public GsonProtocolCoderToolset(String topic, String controllerId, - String groupId, String artifactId, - String decodedClass, - JsonProtocolFilter filter, - CustomGsonCoder customGsonCoder, - int modelClassLoaderHash) { - super(topic, controllerId, groupId, artifactId, decodedClass, filter, customGsonCoder, modelClassLoaderHash); - } - - /** - * gets the Gson decoder - * - * @return the Gson decoder - */ - @JsonIgnore - protected Gson getDecoder() {return decoder;} - - /** - * gets the Gson encoder - * - * @return the Gson encoder - */ - @JsonIgnore - protected Gson getEncoder() {return encoder;} - - /** - * {@inheritDoc} - */ - @Override - public Object decode(String json) - throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { - - DroolsController droolsController = - DroolsController.factory.get(groupId, artifactId, ""); - if (droolsController == null) { - logger.warn("{}: no drools-controller to process {}", this, json); - throw new IllegalStateException("no drools-controller to process event"); - } - - CoderFilters decoderFilter = filter(json); - if (decoderFilter == null) { - logger.debug("{}: no decoder to process {}", this, json); - throw new UnsupportedOperationException("no decoder to process event"); - } - - Class decoderClass; - try { - decoderClass = - droolsController.fetchModelClass(decoderFilter.getCodedClass()); - if (decoderClass == null) { - logger.warn("{}: cannot fetch application class {}", this, decoderFilter.getCodedClass()); - throw new IllegalStateException("cannot fetch application class " + decoderFilter.getCodedClass()); - } - } catch (Exception e) { - logger.warn("{}: cannot fetch application class {} because of {}", this, - decoderFilter.getCodedClass(), e.getMessage()); - throw new UnsupportedOperationException("cannot fetch application class " + decoderFilter.getCodedClass(), e); - } - - if (this.customCoder != null) { - try { - Class gsonClassContainer = - droolsController.fetchModelClass(this.customCoder.getClassContainer()); - Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField); - Object gsonObject = gsonField.get(null); - Method fromJsonMethod = gsonObject.getClass(). - getDeclaredMethod - ("fromJson", new Class[]{String.class, Class.class}); - Object fact = fromJsonMethod.invoke(gsonObject, json, decoderClass); - return fact; - } catch (Exception e) { - logger.warn("{}: cannot fetch application class {} because of {}", this, - decoderFilter.getCodedClass(), e.getMessage()); - throw new UnsupportedOperationException("cannot fetch application class " + decoderFilter.getCodedClass(), e); - } - } else { - try { - Object fact = this.decoder.fromJson(json, decoderClass); - return fact; - } catch (Exception e) { - logger.warn("{} cannot decode {} into {} because of {}", - this, json, decoderClass.getName(), e.getMessage(), e); - throw new UnsupportedOperationException("cannont decode into " + decoderFilter.getCodedClass(), e); - } - } - } - - - - /** - * {@inheritDoc} - */ - @Override - public String encode(Object event) - throws IllegalArgumentException, UnsupportedOperationException { - - DroolsController droolsController = - DroolsController.factory.get(groupId, artifactId, null); - if (droolsController == null) { - logger.info("{}: no drools-controller to process {} (continue)", this, event); - throw new IllegalStateException("custom-coder but no drools-controller"); - } - - if (this.customCoder != null) { - try { - Class gsonClassContainer = - droolsController.fetchModelClass(this.customCoder.getClassContainer()); - Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField); - Object gsonObject = gsonField.get(null); - Method toJsonMethod = gsonObject.getClass(). - getDeclaredMethod - ("toJson", new Class[]{Object.class}); - String encodedJson = (String) toJsonMethod.invoke(gsonObject, event); - return encodedJson; - } catch (Exception e) { - logger.warn("{} cannot custom-encode {} because of {}", this, event, e.getMessage(), e); - throw new UnsupportedOperationException("event cannot be encoded", e); - } - } else { - try { - String encodedEvent = this.encoder.toJson(event); - return encodedEvent; - } catch (Exception e) { - logger.warn("{} cannot encode {} because of {}", this, event, e.getMessage(), e); - throw new UnsupportedOperationException("event cannot be encoded", e); - } - } - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("GsonProtocolCoderToolset [toString()=").append(super.toString()).append("]"); - return builder.toString(); - } -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java deleted file mode 100644 index 3c112573..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java +++ /dev/null @@ -1,309 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.protocol.coders; - -import java.util.List; - -public class TopicCoderFilterConfiguration { - - /** - * Custom coder, contains class and static field to access parser that the controller - * desires to use instead of the framework provided parser - */ - public static abstract class CustomCoder { - protected String className; - protected String staticCoderField; - - /** - * create custom coder from raw string in the following format - * (typically embedded in a property file): - * - * Note this is to support decoding/encoding of partial structures that are - * only known by the model. - * - * @param rawCustomCoder with format: , - */ - public CustomCoder(String rawCustomCoder) throws IllegalArgumentException { - if (rawCustomCoder != null && !rawCustomCoder.isEmpty()) { - - this.className = rawCustomCoder.substring(0,rawCustomCoder.indexOf(",")); - if (this.className == null || this.className.isEmpty()) { - throw new IllegalArgumentException("No classname to create CustomCoder cannot be created"); - } - - this.staticCoderField = rawCustomCoder.substring(rawCustomCoder.indexOf(",")+1); - if (this.staticCoderField == null || this.staticCoderField.isEmpty()) { - throw new IllegalArgumentException - ("No staticCoderField to create CustomCoder cannot be created for class " + - className); - } - - } - } - /** - * @param classContainer - * @param staticCoderField - */ - public CustomCoder(String className, String staticCoderField) throws IllegalArgumentException { - if (className == null || className.isEmpty()) { - throw new IllegalArgumentException("No classname to create CustomCoder cannot be created"); - } - - if (staticCoderField == null || staticCoderField.isEmpty()) { - throw new IllegalArgumentException - ("No staticCoderField to create CustomCoder cannot be created for class " + - className); - } - - this.className = className; - this.staticCoderField = staticCoderField; - } - - /** - * @return the className - */ - public String getClassContainer() { - return className; - } - - /** - * @param className the className to set - */ - public void setClassContainer(String className) { - this.className = className; - } - - /** - * @return the staticCoderField - */ - public String getStaticCoderField() { - return staticCoderField; - } - - /** - * @param staticCoderField the staticGson to set - */ - public void setStaticCoderField(String staticCoderField) { - this.staticCoderField = staticCoderField; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("CustomCoder [className=").append(className).append(", staticCoderField=") - .append(staticCoderField).append("]"); - return builder.toString(); - } - } - - public static class CustomGsonCoder extends CustomCoder { - - public CustomGsonCoder(String className, String staticCoderField) { - super(className, staticCoderField); - } - - public CustomGsonCoder(String customGson) throws IllegalArgumentException { - super(customGson); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("CustomGsonCoder [toString()=").append(super.toString()).append("]"); - return builder.toString(); - } - - } - - public static class CustomJacksonCoder extends CustomCoder { - - public CustomJacksonCoder(String className, String staticCoderField) { - super(className, staticCoderField); - } - - public CustomJacksonCoder(String customJackson) throws IllegalArgumentException { - super(customJackson); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("CustomJacksonCoder [toString()=").append(super.toString()).append("]"); - return builder.toString(); - } - - } - - /** - * Coder/Decoder class and Filter container. The decoder class is potential, - * in order to be operational needs to be fetched from an available - * class loader. - * - */ - public static class PotentialCoderFilter { - - /** - * decoder class (pending from being able to be fetched and found - * in some class loader) - */ - protected String codedClass; - - /** - * filters to apply to the selection of the decodedClass; - */ - protected JsonProtocolFilter filter; - - /** - * constructor - * - * @param codedClass decoder class - * @param filter filters to apply - */ - public PotentialCoderFilter(String codedClass, JsonProtocolFilter filter) { - this.codedClass = codedClass; - this.filter = filter; - } - - /** - * @return the decodedClass - */ - public String getCodedClass() { - return codedClass; - } - - /** - * @param decodedClass the decodedClass to set - */ - public void setCodedClass(String decodedClass) { - this.codedClass = decodedClass; - } - - /** - * @return the filter - */ - public JsonProtocolFilter getFilter() { - return filter; - } - - /** - * @param filter the filter to set - */ - public void setFilter(JsonProtocolFilter filter) { - this.filter = filter; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("PotentialCoderFilter [codedClass=").append(codedClass).append(", filter=").append(filter) - .append("]"); - return builder.toString(); - } - } - - /** - * the source topic - */ - protected final String topic; - - /** - * List of decoder -> filters - */ - protected final List coderFilters; - - /** - * custom gson coder that this controller prefers to use instead of the framework ones - */ - protected CustomGsonCoder customGsonCoder; - - /** - * custom jackson coder that this controller prefers to use instead of the framework ones - */ - protected CustomJacksonCoder customJacksonCoder; - - /** - * Constructor - * - * @param decoderFilters list of decoders and associated filters - * @param topic the topic - */ - public TopicCoderFilterConfiguration(String topic, List decoderFilters, - CustomGsonCoder customGsonCoder, - CustomJacksonCoder customJacksonCoder) { - this.coderFilters = decoderFilters; - this.topic = topic; - this.customGsonCoder = customGsonCoder; - this.customJacksonCoder = customJacksonCoder; - } - - /** - * @return the topic - */ - public String getTopic() { - return topic; - } - - /** - * @return the decoderFilters - */ - public List getCoderFilters() { - return coderFilters; - } - - /** - * @return the customGsonCoder - */ - public CustomGsonCoder getCustomGsonCoder() { - return customGsonCoder; - } - - /** - * @param customGsonCoder the customGsonCoder to set - */ - public void setCustomGsonCoder(CustomGsonCoder customGsonCoder) { - this.customGsonCoder = customGsonCoder; - } - - /** - * @return the customJacksonCoder - */ - public CustomJacksonCoder getCustomJacksonCoder() { - return customJacksonCoder; - } - - /** - * @param customJacksonCoder the customJacksonCoder to set - */ - public void setCustomJacksonCoder(CustomJacksonCoder customJacksonCoder) { - this.customJacksonCoder = customJacksonCoder; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("TopicCoderFilterConfiguration [topic=").append(topic).append(", coderFilters=") - .append(coderFilters).append(", customGsonCoder=").append(customGsonCoder) - .append(", customJacksonCoder=").append(customJacksonCoder).append("]"); - return builder.toString(); - } - - -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/ControllerConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/ControllerConfiguration.java deleted file mode 100644 index 98af02ee..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/ControllerConfiguration.java +++ /dev/null @@ -1,280 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.protocol.configuration; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.commons.lang3.builder.ToStringBuilder; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; - - -/** - * Drools Related Information - * - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ControllerConfiguration { - - public static final String CONFIG_CONTROLLER_OPERATION_CREATE = "create"; - public static final String CONFIG_CONTROLLER_OPERATION_UPDATE = "update"; - public static final String CONFIG_CONTROLLER_OPERATION_LOCK = "lock"; - public static final String CONFIG_CONTROLLER_OPERATION_UNLOCK = "unlock"; - - /** - * - * (Required) - * - */ - @JsonProperty("name") - private String name; - /** - * Set of operations that can be applied to a controller: create, lock - * (Required) - * - */ - @JsonProperty("operation") - private String operation; - /** - * Maven Related Information - * - */ - @JsonProperty("drools") - private DroolsConfiguration drools; - @JsonIgnore - private Map additionalProperties = new HashMap(); - protected final static Object NOT_FOUND_VALUE = new Object(); - - /** - * No args constructor for use in serialization - * - */ - public ControllerConfiguration() { - } - - /** - * - * @param name - * @param drools - * @param operation - */ - public ControllerConfiguration(String name, String operation, DroolsConfiguration drools) { - this.name = name; - this.operation = operation; - this.drools = drools; - } - - /** - * - * (Required) - * - * @return - * The name - */ - @JsonProperty("name") - public String getName() { - return name; - } - - /** - * - * (Required) - * - * @param name - * The name - */ - @JsonProperty("name") - public void setName(String name) { - this.name = name; - } - - public ControllerConfiguration withName(String name) { - this.name = name; - return this; - } - - /** - * Set of operations that can be applied to a controller: create, lock - * (Required) - * - * @return - * The operation - */ - @JsonProperty("operation") - public String getOperation() { - return operation; - } - - /** - * Set of operations that can be applied to a controller: create, lock - * (Required) - * - * @param operation - * The operation - */ - @JsonProperty("operation") - public void setOperation(String operation) { - this.operation = operation; - } - - public ControllerConfiguration withOperation(String operation) { - this.operation = operation; - return this; - } - - /** - * Maven Related Information - * - * @return - * The drools - */ - @JsonProperty("drools") - public DroolsConfiguration getDrools() { - return drools; - } - - /** - * Maven Related Information - * - * @param drools - * The drools - */ - @JsonProperty("drools") - public void setDrools(DroolsConfiguration drools) { - this.drools = drools; - } - - public ControllerConfiguration withDrools(DroolsConfiguration drools) { - this.drools = drools; - return this; - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this); - } - - @JsonAnyGetter - public Map getAdditionalProperties() { - return this.additionalProperties; - } - - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - - public ControllerConfiguration withAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - return this; - } - - protected boolean declaredProperty(String name, Object value) { - switch (name) { - case "name": - if (value instanceof String) { - setName(((String) value)); - } else { - throw new IllegalArgumentException(("property \"name\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); - } - return true; - case "operation": - if (value instanceof String) { - setOperation(((String) value)); - } else { - throw new IllegalArgumentException(("property \"operation\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); - } - return true; - case "drools": - if (value instanceof DroolsConfiguration) { - setDrools(((DroolsConfiguration) value)); - } else { - throw new IllegalArgumentException(("property \"drools\" is of type \"org.openecomp.policy.drools.protocol.configuration.Drools\", but got "+ value.getClass().toString())); - } - return true; - default: - return false; - } - } - - protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { - switch (name) { - case "name": - return getName(); - case "operation": - return getOperation(); - case "drools": - return getDrools(); - default: - return notFoundValue; - } - } - - @SuppressWarnings({ - "unchecked" - }) - publicT get(String name) { - Object value = declaredPropertyOrNotFound(name, ControllerConfiguration.NOT_FOUND_VALUE); - if (ControllerConfiguration.NOT_FOUND_VALUE!= value) { - return ((T) value); - } else { - return ((T) getAdditionalProperties().get(name)); - } - } - - public void set(String name, Object value) { - if (!declaredProperty(name, value)) { - getAdditionalProperties().put(name, ((Object) value)); - } - } - - public ControllerConfiguration with(String name, Object value) { - if (!declaredProperty(name, value)) { - getAdditionalProperties().put(name, ((Object) value)); - } - return this; - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(name).append(operation).append(drools).append(additionalProperties).toHashCode(); - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - if ((other instanceof ControllerConfiguration) == false) { - return false; - } - ControllerConfiguration rhs = ((ControllerConfiguration) other); - return new EqualsBuilder().append(name, rhs.name).append(operation, rhs.operation).append(drools, rhs.drools).append(additionalProperties, rhs.additionalProperties).isEquals(); - } - -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/DroolsConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/DroolsConfiguration.java deleted file mode 100644 index 87cf2348..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/DroolsConfiguration.java +++ /dev/null @@ -1,278 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.protocol.configuration; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.commons.lang3.builder.ToStringBuilder; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; - - -/** - * Maven Related Information - * - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class DroolsConfiguration { - - /** - * Maven Artifact ID - * (Required) - * - */ - @JsonProperty("artifactId") - private String artifactId; - /** - * Maven Group ID - * (Required) - * - */ - @JsonProperty("groupId") - private String groupId; - /** - * Maven Version - * (Required) - * - */ - @JsonProperty("version") - private String version; - @JsonIgnore - private Map additionalProperties = new HashMap(); - protected final static Object NOT_FOUND_VALUE = new Object(); - - /** - * No args constructor for use in serialization - * - */ - public DroolsConfiguration() { - } - - /** - * - * @param groupId - * @param artifactId - * @param version - */ - public DroolsConfiguration(String artifactId, String groupId, String version) { - this.artifactId = artifactId; - this.groupId = groupId; - this.version = version; - } - - /** - * Maven Artifact ID - * (Required) - * - * @return - * The artifactId - */ - @JsonProperty("artifactId") - public String getArtifactId() { - return artifactId; - } - - /** - * Maven Artifact ID - * (Required) - * - * @param artifactId - * The artifactId - */ - @JsonProperty("artifactId") - public void setArtifactId(String artifactId) { - this.artifactId = artifactId; - } - - public DroolsConfiguration withArtifactId(String artifactId) { - this.artifactId = artifactId; - return this; - } - - /** - * Maven Group ID - * (Required) - * - * @return - * The groupId - */ - @JsonProperty("groupId") - public String getGroupId() { - return groupId; - } - - /** - * Maven Group ID - * (Required) - * - * @param groupId - * The groupId - */ - @JsonProperty("groupId") - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public DroolsConfiguration withGroupId(String groupId) { - this.groupId = groupId; - return this; - } - - /** - * Maven Version - * (Required) - * - * @return - * The version - */ - @JsonProperty("version") - public String getVersion() { - return version; - } - - /** - * Maven Version - * (Required) - * - * @param version - * The version - */ - @JsonProperty("version") - public void setVersion(String version) { - this.version = version; - } - - public DroolsConfiguration withVersion(String version) { - this.version = version; - return this; - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this); - } - - @JsonAnyGetter - public Map getAdditionalProperties() { - return this.additionalProperties; - } - - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - - public DroolsConfiguration withAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - return this; - } - - protected boolean declaredProperty(String name, Object value) { - switch (name) { - case "artifactId": - if (value instanceof String) { - setArtifactId(((String) value)); - } else { - throw new IllegalArgumentException(("property \"artifactId\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); - } - return true; - case "groupId": - if (value instanceof String) { - setGroupId(((String) value)); - } else { - throw new IllegalArgumentException(("property \"groupId\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); - } - return true; - case "version": - if (value instanceof String) { - setVersion(((String) value)); - } else { - throw new IllegalArgumentException(("property \"version\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); - } - return true; - default: - return false; - } - } - - protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { - switch (name) { - case "artifactId": - return getArtifactId(); - case "groupId": - return getGroupId(); - case "version": - return getVersion(); - default: - return notFoundValue; - } - } - - @SuppressWarnings({ - "unchecked" - }) - publicT get(String name) { - Object value = declaredPropertyOrNotFound(name, DroolsConfiguration.NOT_FOUND_VALUE); - if (DroolsConfiguration.NOT_FOUND_VALUE!= value) { - return ((T) value); - } else { - return ((T) getAdditionalProperties().get(name)); - } - } - - public void set(String name, Object value) { - if (!declaredProperty(name, value)) { - getAdditionalProperties().put(name, ((Object) value)); - } - } - - public DroolsConfiguration with(String name, Object value) { - if (!declaredProperty(name, value)) { - getAdditionalProperties().put(name, ((Object) value)); - } - return this; - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(artifactId).append(groupId).append(version).append(additionalProperties).toHashCode(); - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - if ((other instanceof DroolsConfiguration) == false) { - return false; - } - DroolsConfiguration rhs = ((DroolsConfiguration) other); - return new EqualsBuilder().append(artifactId, rhs.artifactId).append(groupId, rhs.groupId).append(version, rhs.version).append(additionalProperties, rhs.additionalProperties).isEquals(); - } - -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/PdpdConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/PdpdConfiguration.java deleted file mode 100644 index 65de6656..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/PdpdConfiguration.java +++ /dev/null @@ -1,283 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.protocol.configuration; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.commons.lang3.builder.ToStringBuilder; - - -/** - * ENGINE-CONFIGURATION - *

- * - * - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class PdpdConfiguration { - - /** - * Controller Entity ID - */ - public static final String CONFIG_ENTITY_CONTROLLER = "controller"; - - /** - * Unique Transaction ID. This is an UUID. - * (Required) - * - */ - @JsonProperty("requestID") - private String requestID; - /** - * Set of entities on which configuration can be performed: controller - * (Required) - * - */ - @JsonProperty("entity") - private String entity; - /** - * Controller Information, only applicable when the entity is set to controller - * - */ - @JsonProperty("controllers") - private List controllers = new ArrayList(); - @JsonIgnore - private Map additionalProperties = new HashMap(); - protected final static Object NOT_FOUND_VALUE = new Object(); - - /** - * No args constructor for use in serialization - * - */ - public PdpdConfiguration() { - } - - /** - * - * @param controller - * @param requestID - * @param entity - */ - public PdpdConfiguration(String requestID, String entity, List controllers) { - this.requestID = requestID; - this.entity = entity; - this.controllers = controllers; - } - - /** - * Unique Transaction ID. This is an UUID. - * (Required) - * - * @return - * The requestID - */ - @JsonProperty("requestID") - public String getRequestID() { - return requestID; - } - - /** - * Unique Transaction ID. This is an UUID. - * (Required) - * - * @param requestID - * The requestID - */ - @JsonProperty("requestID") - public void setRequestID(String requestID) { - this.requestID = requestID; - } - - public PdpdConfiguration withRequestID(String requestID) { - this.requestID = requestID; - return this; - } - - /** - * Set of entities on which configuration can be performed: controller - * (Required) - * - * @return - * The entity - */ - @JsonProperty("entity") - public String getEntity() { - return entity; - } - - /** - * Set of entities on which configuration can be performed: controller - * (Required) - * - * @param entity - * The entity - */ - @JsonProperty("entity") - public void setEntity(String entity) { - this.entity = entity; - } - - public PdpdConfiguration withEntity(String entity) { - this.entity = entity; - return this; - } - - /** - * Controller Information, only applicable when the entity is set to controller - * - * @return - * The controller - */ - @JsonProperty("controller") - public List getControllers() { - return controllers; - } - - /** - * Controller Information, only applicable when the entity is set to controller - * - * @param controller - * The controller - */ - @JsonProperty("controller") - public void setControllers(List controllers) { - this.controllers = controllers; - } - - public PdpdConfiguration withController(List controllers) { - this.controllers = controllers; - return this; - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this); - } - - @JsonAnyGetter - public Map getAdditionalProperties() { - return this.additionalProperties; - } - - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - - public PdpdConfiguration withAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - return this; - } - - @SuppressWarnings("unchecked") - protected boolean declaredProperty(String name, Object value) { - switch (name) { - case "requestID": - if (value instanceof String) { - setRequestID(((String) value)); - } else { - throw new IllegalArgumentException(("property \"requestID\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); - } - return true; - case "entity": - if (value instanceof String) { - setEntity(((String) value)); - } else { - throw new IllegalArgumentException(("property \"entity\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); - } - return true; - case "controllers": - if (value instanceof List) { - setControllers(((List ) value)); - } else { - throw new IllegalArgumentException(("property \"controllers\" is of type \"java.util.List\", but got "+ value.getClass().toString())); - } - return true; - default: - return false; - } - } - - protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { - switch (name) { - case "requestID": - return getRequestID(); - case "entity": - return getEntity(); - case "controllers": - return getControllers(); - default: - return notFoundValue; - } - } - - @SuppressWarnings({ - "unchecked" - }) - publicT get(String name) { - Object value = declaredPropertyOrNotFound(name, PdpdConfiguration.NOT_FOUND_VALUE); - if (PdpdConfiguration.NOT_FOUND_VALUE!= value) { - return ((T) value); - } else { - return ((T) getAdditionalProperties().get(name)); - } - } - - public void set(String name, Object value) { - if (!declaredProperty(name, value)) { - getAdditionalProperties().put(name, ((Object) value)); - } - } - - public PdpdConfiguration with(String name, Object value) { - if (!declaredProperty(name, value)) { - getAdditionalProperties().put(name, ((Object) value)); - } - return this; - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(requestID).append(entity).append(controllers).append(additionalProperties).toHashCode(); - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - if ((other instanceof PdpdConfiguration) == false) { - return false; - } - PdpdConfiguration rhs = ((PdpdConfiguration) other); - return new EqualsBuilder().append(requestID, rhs.requestID).append(entity, rhs.entity).append(controllers, rhs.controllers).append(additionalProperties, rhs.additionalProperties).isEquals(); - } - -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java b/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java deleted file mode 100644 index be6c4962..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java +++ /dev/null @@ -1,2335 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.server.restful; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.UUID; -import java.util.regex.Pattern; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; - -import org.openecomp.policy.drools.controller.DroolsController; -import org.openecomp.policy.drools.event.comm.TopicEndpoint; -import org.openecomp.policy.drools.event.comm.TopicSink; -import org.openecomp.policy.drools.event.comm.TopicSource; -import org.openecomp.policy.drools.event.comm.bus.DmaapTopicSink; -import org.openecomp.policy.drools.event.comm.bus.DmaapTopicSource; -import org.openecomp.policy.drools.event.comm.bus.UebTopicSink; -import org.openecomp.policy.drools.event.comm.bus.UebTopicSource; -import org.openecomp.policy.drools.features.PolicyControllerFeatureAPI; -import org.openecomp.policy.drools.features.PolicyEngineFeatureAPI; -import org.openecomp.policy.drools.properties.PolicyProperties; -import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder; -import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; -import org.openecomp.policy.drools.protocol.coders.JsonProtocolFilter; -import org.openecomp.policy.drools.protocol.coders.JsonProtocolFilter.FilterRule; -import org.openecomp.policy.drools.protocol.coders.ProtocolCoderToolset; -import org.openecomp.policy.drools.protocol.configuration.ControllerConfiguration; -import org.openecomp.policy.drools.protocol.configuration.PdpdConfiguration; -import org.openecomp.policy.drools.system.PolicyController; -import org.openecomp.policy.drools.system.PolicyEngine; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.LoggerContext; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Info; -import io.swagger.annotations.SwaggerDefinition; -import io.swagger.annotations.Tag; - - -/** - * Telemetry JAX-RS Interface to the PDP-D - */ - -@Path("/policy/pdp") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -@Api -@SwaggerDefinition( - info = @Info( - description = "PDP-D Telemetry Services", - version = "v1.0", - title = "PDP-D Telemetry" - ), - consumes = {MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN}, - produces = {MediaType.APPLICATION_JSON}, - schemes = {SwaggerDefinition.Scheme.HTTP}, - tags = { - @Tag(name = "pdp-d-telemetry", description = "Drools PDP Telemetry Operations") - } -) -public class RestManager { - /** - * Logger - */ - private static Logger logger = LoggerFactory.getLogger(RestManager.class); - - @GET - @Path("engine") - @ApiOperation( - value="Retrieves the Engine Operational Status", - notes="Top-level abstraction. Provides a global view of resources", - response=PolicyEngine.class - ) - public Response engine() { - return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); - } - - @DELETE - @Path("engine") - @ApiOperation( - value="Shuts down the Engine", - notes="Deleting the engine, the top-level abstraction, equivalenty shuts it down", - response=PolicyEngine.class - ) - public Response engineShutdown() { - try { - PolicyEngine.manager.shutdown(); - } catch (IllegalStateException e) { - logger.error("{}: cannot shutdown {} because of {}", this, PolicyEngine.manager, e.getMessage(), e); - return Response.status(Response.Status.BAD_REQUEST). - entity(PolicyEngine.manager). - build(); - } - - return Response.status(Response.Status.OK). - entity(PolicyEngine.manager). - build(); - } - - @GET - @Path("engine/features") - @ApiOperation( - value="Engine Features", - notes="Provides the list of loaded features using the PolicyEngineFeatureAPI", - responseContainer="List" - ) - public Response engineFeatures() { - return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatures()).build(); - } - - @GET - @Path("engine/features/inventory") - @ApiOperation( - value="Engine Detailed Feature Inventory", - notes="Provides detailed list of loaded features using the PolicyEngineFeatureAPI", - responseContainer="List", - response=PolicyEngineFeatureAPI.class - ) - public Response engineFeaturesInventory() { - return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatureProviders()).build(); - } - - @GET - @Path("engine/features/{featureName}") - @ApiOperation( - value="Engine Feature", - notes="Provides Details for a given feature Engine Provider", - response=PolicyEngineFeatureAPI.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message = "The feature cannot be found") - }) - public Response engineFeature(@ApiParam(value="Feature Name", required=true) - @PathParam("featureName") String featureName) { - try { - return Response.status(Response.Status.OK). - entity(PolicyEngine.manager.getFeatureProvider(featureName)).build(); - } catch(IllegalArgumentException iae) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(iae.getMessage())).build(); - } - } - - @GET - @Path("engine/inputs") - @ApiOperation( - value="Engine Input Ports", - notes="List of input ports", - responseContainer="List" - ) - public Response engineInputs() { - return Response.status(Response.Status.OK). - entity(Arrays.asList(Inputs.values())). - build(); - } - - @POST - @Path("engine/inputs/configuration") - @ApiOperation( - value="Engine Input Configuration Requests", - notes="Feeds a configuration request input into the Engine" - ) - @ApiResponses(value={ - @ApiResponse(code=406, message = "The configuration request cannot be honored") - }) - public Response engineUpdate( - @ApiParam(value="Configuration to apply", required=true) PdpdConfiguration configuration) { - PolicyController controller = null; - boolean success = true; - try { - success = PolicyEngine.manager.configure(configuration); - } catch (Exception e) { - success = false; - logger.info("{}: cannot configure {} because of {}", this, PolicyEngine.manager, e.getMessage(), e); - } - - if (!success) - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation")).build(); - else - return Response.status(Response.Status.OK).entity(controller).build(); - } - - @GET - @Path("engine/properties") - @ApiOperation( - value="Engine Configuration Properties", - notes="Used for booststrapping the engine", - response=Properties.class - ) - public Response engineProperties() { - return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getProperties()).build(); - } - - @GET - @Path("engine/switches") - @ApiOperation( - value="Engine Control Switches", - notes="List of the Engine Control Switches", - responseContainer="List" - ) - public Response engineSwitches() { - return Response.status(Response.Status.OK). - entity(Arrays.asList(Switches.values())). - build(); - } - - @PUT - @Path("engine/switches/activation") - @ApiOperation( - value="Switches on the Engine Activation Switch", - notes="Turns on Activation Switch on the Engine. This order entails that the engine " + - "and controllers are unlocked and started", - response=PolicyEngine.class - ) - public Response engineActivation() { - boolean success = true; - try { - PolicyEngine.manager.activate(); - } catch (Exception e) { - success = false; - logger.info("{}: cannot activate {} because of {}", this, PolicyEngine.manager, e.getMessage(), e); - } - - if (!success) - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation")).build(); - else - return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); - } - - @DELETE - @Path("engine/switches/activation") - @ApiOperation( - value="Switches off Engine Activation Switch", - notes="Turns off the Activation Switch on the Engine. This order entails that the engine " + - "and controllers are locked (with the exception of those resources defined as unmanaged)", - response=PolicyEngine.class - ) - public Response engineDeactivation() { - boolean success = true; - try { - PolicyEngine.manager.deactivate(); - } catch (Exception e) { - success = false; - logger.info("{}: cannot deactivate {} because of {}", this, PolicyEngine.manager, e.getMessage(), e); - } - - if (!success) - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation")).build(); - else - return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); - } - - @PUT - @Path("engine/switches/lock") - @ApiOperation( - value="Switches on the Engine Lock Control", - notes="This switch locks all the engine resources as a whole, except those that are defined unmanaged", - response=PolicyEngine.class - ) - @ApiResponses(value = { - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response engineLock() { - boolean success = PolicyEngine.manager.lock(); - if (success) - return Response.status(Status.OK). - entity(PolicyEngine.manager). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation")). - build(); - } - - @DELETE - @Path("engine/switches/lock") - @ApiOperation( - value="Switches off the Lock control", - notes="This switch locks all the engine resources as a whole, except those that are defined unmanaged", - response=PolicyEngine.class - ) - @ApiResponses(value = { - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response engineUnlock() { - boolean success = PolicyEngine.manager.unlock(); - if (success) - return Response.status(Status.OK). - entity(PolicyEngine.manager). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation")). - build(); - } - - @GET - @Path("engine/controllers") - @ApiOperation( - value="Lists the Policy Controllers Names", - notes="Unique Policy Controller Identifiers", - responseContainer="List" - ) - public Response controllers() { - return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getPolicyControllerIds()).build(); - } - - @GET - @Path("engine/controllers/inventory") - @ApiOperation( - value="Lists the Policy Controllers", - notes="Detailed list of Policy Controllers", - responseContainer="List", - response=PolicyController.class - ) - public Response controllerInventory() { - return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getPolicyControllers()).build(); - } - - @POST - @Path("engine/controllers") - @ApiOperation( - value="Creates and starts a new Policy Controller", - notes="Controller creation based on properties", - response=PolicyController.class - ) - @ApiResponses(value = { - @ApiResponse(code=400, message = "Invalid configuration information has been provided"), - @ApiResponse(code=304, message = "The controller already exists"), - @ApiResponse(code=406, message = "The administrative state of the system prevents it " + - "from processing this request"), - @ApiResponse(code=206, message = "The controller has been created " + - "but cannot be started"), - @ApiResponse(code=201, message = "The controller has been succesfully created and started") - }) - public Response controllerAdd(@ApiParam(value="Configuration Properties to apply", required = true) - Properties config) { - if (config == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error("A configuration must be provided")). - build(); - - String controllerName = config.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME); - if (controllerName == null || controllerName.isEmpty()) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error - ("Configuration must have an entry for " + - PolicyProperties.PROPERTY_CONTROLLER_NAME)). - build(); - - PolicyController controller; - try { - controller = PolicyController.factory.get(controllerName); - if (controller != null) - return Response.status(Response.Status.NOT_MODIFIED). - entity(controller). - build(); - } catch (IllegalArgumentException e) { - // This is OK - } catch (IllegalStateException e) { - logger.info("{}: cannot get policy-controller because of {}", this, e.getMessage(), e); - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " not found")).build(); - } - - try { - controller = PolicyEngine.manager.createPolicyController - (config.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME), config); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.warn("{}: cannot create policy-controller because of {}", this, e.getMessage(), e); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); - } - - try { - boolean success = controller.start(); - if (!success) { - logger.info("{}: cannot start {}", this, controller); - return Response.status(Response.Status.PARTIAL_CONTENT). - entity(new Error(controllerName + " can't be started")).build(); - } - } catch (IllegalStateException e) { - logger.info("{}: cannot start {} because of {}", this, controller, e.getMessage(), e);; - return Response.status(Response.Status.PARTIAL_CONTENT). - entity(controller).build(); - } - - return Response.status(Response.Status.CREATED). - entity(controller). - build(); - } - - @GET - @Path("engine/controllers/features") - @ApiOperation( - value="Lists of Feature Providers Identifiers", - notes="Unique Policy Controller Identifiers", - responseContainer="List" - ) - public Response controllerFeatures() { - return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatures()).build(); - } - - @GET - @Path("engine/controllers/features/inventory") - @ApiOperation( - value="Detailed Controllers Feature Inventory", - notes="Provides detailed list of loaded features using the PolicyControllerFeatureAPI", - responseContainer="List", - response=PolicyControllerFeatureAPI.class - ) - public Response controllerFeaturesInventory() { - return Response.status(Response.Status.OK). - entity(PolicyController.factory.getFeatureProviders()). - build(); - } - - @GET - @Path("engine/controllers/features/{featureName}") - @ApiOperation( - value="Controller Feature", - notes="Provides Details for a given Policy Controller feature provider", - response=PolicyControllerFeatureAPI.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message = "The feature cannot be found") - }) - public Response controllerFeature(@ApiParam(value="Feature Name", required=true) - @PathParam("featureName") String featureName) { - try { - return Response.status(Response.Status.OK). - entity(PolicyController.factory.getFeatureProvider(featureName)). - build(); - } catch(IllegalArgumentException iae) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(iae.getMessage())).build(); - } - } - - @GET - @Path("engine/controllers/{controller}") - @ApiOperation( - value="Retrieves a Policy Controller", - notes="A Policy Controller is a concrete drools application abstraction. " + - "It aggregates networking, drools, and other resources," + - "as provides operational controls over drools applications", - response=PolicyController.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response controller(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName) { - try { - return Response.status(Response.Status.OK). - entity(PolicyController.factory.get(controllerName)). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " not acceptable")). - build(); - } - } - - @DELETE - @Path("engine/controllers/{controller}") - @ApiOperation( - value="Deletes a Policy Controller", - notes="A Policy Controller is a concrete drools application abstraction. " + - "It aggregates networking, drools, and other resources," + - "as provides operational controls over drools applications", - response=PolicyController.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled"), - @ApiResponse(code=500, message="A problem has occurred while deleting the Policy Controller") - }) - public Response controllerDelete(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName) { - - PolicyController controller; - try { - controller = - PolicyController.factory.get(controllerName); - if (controller == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + " does not exist")). - build(); - } catch (IllegalArgumentException e) { - logger.info("{}: cannot get policy-controller {} because of {}", this, controllerName, e.getMessage(), e); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + " not found: " + e.getMessage())). - build(); - } catch (IllegalStateException e) { - logger.info("{}: cannot get policy-controller {} because of {}", this, controllerName, e.getMessage(), e); - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " not acceptable")).build(); - } - - try { - PolicyEngine.manager.removePolicyController(controllerName); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.info("{}: cannot remove policy-controller {} because of {}", this, controllerName, e.getMessage(), e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR). - entity(new Error(e.getMessage())). - build(); - } - - return Response.status(Response.Status.OK). - entity(controller). - build(); - } - - @GET - @Path("engine/controllers/{controller}/properties") - @ApiOperation( - value="Retrieves the configuration properties of a Policy Controller", - notes="Configuration resources used by the controller if Properties format", - response=PolicyController.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response controllerProperties(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName) { - try { - PolicyController controller = PolicyController.factory.get(controllerName); - return Response.status(Response.Status.OK). - entity(controller.getProperties()). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " not acceptable")). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/inputs") - @ApiOperation( - value="Policy Controller Input Ports", - notes="List of input ports", - responseContainer="List" - ) - public Response controllerInputs() { - return Response.status(Response.Status.OK). - entity(Arrays.asList(Inputs.values())). - build(); - } - - @POST - @Path("engine/controllers/{controller}/inputs/configuration") - @ApiOperation( - value="Policy Controller Input Configuration Requests", - notes="Feeds a configuration request input into the given Policy Controller" - ) - @ApiResponses(value={ - @ApiResponse(code=400, message = "The configuration request is invalid"), - @ApiResponse(code=406, message = "The configuration request cannot be honored") - }) - public Response controllerUpdate(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Configuration to apply", required=true) - ControllerConfiguration controllerConfiguration) { - - if (controllerName == null || controllerName.isEmpty() || - controllerConfiguration == null || - controllerConfiguration.getName().intern() != controllerName) - return Response.status(Response.Status.BAD_REQUEST). - entity("A valid or matching controller names must be provided"). - build(); - - PolicyController controller; - try { - controller = PolicyEngine.manager.updatePolicyController(controllerConfiguration); - if (controller == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + " does not exist")). - build(); - } catch (IllegalArgumentException e) { - logger.info("{}: cannot update policy-controller {} because of {}", this, controllerName, e.getMessage(), e); - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + " not found: " + e.getMessage())). - build(); - } catch (Exception e) { - logger.info("{}: cannot update policy-controller {} because of {}", this, controllerName, e.getMessage(), e); - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " not acceptable")).build(); - } - - return Response.status(Response.Status.OK). - entity(controller). - build(); - } - - @GET - @Path("engine/controllers/{controller}/switches") - @ApiOperation( - value="Policy Controller Switches", - notes="List of the Policy Controller Switches", - responseContainer="List" - ) - public Response controllerSwitches() { - return Response.status(Response.Status.OK). - entity(Arrays.asList(Switches.values())). - build(); - } - - @PUT - @Path("engine/controllers/{controller}/switches/lock") - @ApiOperation( - value="Switches on the Policy Controller Lock Control", - notes="This action on the switch locks the Policy Controller", - response=PolicyController.class - ) - @ApiResponses(value = { - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response controllerLock(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName) { - PolicyController policyController = PolicyController.factory.get(controllerName); - boolean success = policyController.lock(); - if (success) - return Response.status(Status.OK). - entity(policyController). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("Controller " + controllerName + " cannot be locked")). - build(); - } - - @DELETE - @Path("engine/controllers/{controller}/switches/lock") - @ApiOperation( - value="Switches off the Policy Controller Lock Control", - notes="This action on the switch unlocks the Policy Controller", - response=PolicyController.class - ) - @ApiResponses(value = { - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response controllerUnlock(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName) { - PolicyController policyController = PolicyController.factory.get(controllerName); - boolean success = policyController.unlock(); - if (success) - return Response.status(Status.OK). - entity(policyController). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("Controller " + controllerName + " cannot be unlocked")). - build(); - } - - @GET - @Path("engine/controllers/{controller}/drools") - @ApiOperation( - value="Retrieves the Drools Controller subcomponent of the Policy Controller", - notes="The Drools Controller provides an abstraction over the Drools subsystem", - response=DroolsController.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response drools(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName) { - try { - DroolsController drools = getDroolsController(controllerName); - return Response.status(Response.Status.OK). - entity(drools). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " not acceptable")). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/drools/facts") - @ApiOperation( - value="Retrieves Facts Summary information for a given controller", - notes="Provides the session names, and a count of fact object in the drools working memory", - responseContainer="Map" - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response droolsFacts(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName) { - try { - Map sessionCounts = new HashMap<>(); - DroolsController drools = getDroolsController(controllerName); - for (String session : drools.getSessionNames()) { - sessionCounts.put(session, drools.factCount(session)); - } - return Response.status(Response.Status.OK). - entity(sessionCounts). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " not acceptable")). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/drools/facts/{session}") - @ApiOperation( - value="Retrieves Fact Types (classnames) for a given controller and its count", - notes="The fact types are the classnames of the objects inserted in the drools working memory", - responseContainer="Map" - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller or session cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response droolsFacts(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Drools Session Name", required=true) - @PathParam("session") String sessionName) { - try { - DroolsController drools = getDroolsController(controllerName); - return Response.status(Response.Status.OK). - entity(drools.factClassNames(sessionName)). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error("entity not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + sessionName + " not acceptable")). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/drools/facts/{session}/{factType}") - @ApiOperation( - value="Retrieves fact objects of a given type in the drools working memory" + - "for a given controller and session", - notes="The fact types are the classnames of the objects inserted in the drools working memory", - responseContainer="List" - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, session, or fact type cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response droolsFacts(@ApiParam(value="Fact count", required=false) - @DefaultValue("false") @QueryParam("count") boolean count, - @ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Drools Session Name", required=true) - @PathParam("session") String sessionName, - @ApiParam(value="Drools Fact Type", required=true) - @PathParam("factType") String factType) { - try { - DroolsController drools = getDroolsController(controllerName); - List facts = drools.facts(sessionName, factType, false); - if (!count) - return Response.status(Response.Status.OK).entity(facts).build(); - else - return Response.status(Response.Status.OK).entity(facts.size()).build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + sessionName + ":" + factType + - " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + sessionName + ":" + factType + - " not acceptable")). - build(); - } - } - - @DELETE - @Path("engine/controllers/{controller}/drools/facts/{session}/{factType}") - @ApiOperation( - value="Deletes all the fact objects of a given type from the drools working memory" + - "for a given controller and session. The objects retracted from the working " + - "memory are provided in the response.", - notes="The fact types are the classnames of the objects inserted in the drools working memory", - responseContainer="List" - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, session, or fact type, cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled"), - @ApiResponse(code=500, message="A server error has occurred processing this request") - }) - public Response droolsFactsDelete(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Drools Session Name", required=true) - @PathParam("session") String sessionName, - @ApiParam(value="Drools Fact Type", required=true) - @PathParam("factType") String factType) { - try { - DroolsController drools = getDroolsController(controllerName); - List facts = drools.facts(sessionName, factType, true); - return Response.status(Response.Status.OK).entity(facts).build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + sessionName + ":" + factType + - " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + sessionName + ":" + factType + - " not acceptable")). - build(); - } catch (Exception e) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR). - entity(new Error(e.getMessage())). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}") - @ApiOperation( - value="Gets all the fact objects returned by a DRL query with no parameters from the drools working memory" + - "for a given controller and session", - notes="The DRL query must be defined in the DRL file", - responseContainer="List" - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, session, or query information, cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled"), - @ApiResponse(code=500, message="A server error has occurred processing this request") - }) - public Response droolsFacts(@ApiParam(value="Fact count", required=false) - @DefaultValue("false") @QueryParam("count") boolean count, - @ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Drools Session Name", required=true) - @PathParam("session") String sessionName, - @ApiParam(value="Query Name Present in DRL", required=true) - @PathParam("query") String queryName, - @ApiParam(value="Query Identifier Present in the DRL Query", required=true) - @PathParam("queriedEntity") String queriedEntity) { - try { - DroolsController drools = getDroolsController(controllerName); - List facts = drools.factQuery(sessionName, queryName, queriedEntity, false); - if (!count) - return Response.status(Response.Status.OK).entity(facts).build(); - else - return Response.status(Response.Status.OK).entity(facts.size()).build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + sessionName + ":" + queryName + - queriedEntity + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + sessionName + ":" + queryName + - queriedEntity + " not acceptable")). - build(); - } catch (Exception e) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR). - entity(new Error(e.getMessage())). - build(); - } - } - - @POST - @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}") - @ApiOperation( - value="Gets all the fact objects returned by a DRL query with parameters from the drools working memory" + - "for a given controller and session", - notes="The DRL query with parameters must be defined in the DRL file", - responseContainer="List" - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, session, or query information, cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled"), - @ApiResponse(code=500, message="A server error has occurred processing this request") - }) - public Response droolsFacts(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Drools Session Name", required=true) - @PathParam("session") String sessionName, - @ApiParam(value="Query Name Present in DRL", required=true) - @PathParam("query") String queryName, - @ApiParam(value="Query Identifier Present in the DRL Query", required=true) - @PathParam("queriedEntity") String queriedEntity, - @ApiParam(value="Query Parameter Values to pass in the DRL Query", required=false) - List queryParameters) { - try { - DroolsController drools = getDroolsController(controllerName); - List facts; - if (queryParameters == null || queryParameters.isEmpty()) - facts = drools.factQuery(sessionName, queryName, queriedEntity, false); - else - facts = drools.factQuery(sessionName, queryName, queriedEntity, false, queryParameters.toArray()); - return Response.status(Response.Status.OK).entity(facts).build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + sessionName + ":" + queryName + - queriedEntity + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + sessionName + ":" + queryName + - queriedEntity + " not acceptable")). - build(); - } catch (Exception e) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR). - entity(new Error(e.getMessage())). - build(); - } - } - - @DELETE - @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}") - @ApiOperation( - value="Deletes all the fact objects returned by a DRL query with parameters from the drools working memory" + - "for a given controller and session", - notes="The DRL query with parameters must be defined in the DRL file", - responseContainer="List" - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, session, or query information, cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled"), - @ApiResponse(code=500, message="A server error has occurred processing this request") - }) - public Response droolsFactsDelete(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Drools Session Name", required=true) - @PathParam("session") String sessionName, - @ApiParam(value="Query Name Present in DRL", required=true) - @PathParam("query") String queryName, - @ApiParam(value="Query Identifier Present in the DRL Query", required=true) - @PathParam("queriedEntity") String queriedEntity, - @ApiParam(value="Query Parameter Values to pass in the DRL Query", required=false) - List queryParameters) { - try { - DroolsController drools = getDroolsController(controllerName); - List facts; - if (queryParameters == null || queryParameters.isEmpty()) - facts = drools.factQuery(sessionName, queryName, queriedEntity, true); - else - facts = drools.factQuery(sessionName, queryName, queriedEntity, true, queryParameters.toArray()); - return Response.status(Response.Status.OK).entity(facts).build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + sessionName + ":" + queryName + - queriedEntity + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + sessionName + ":" + queryName + - queriedEntity + " not acceptable")). - build(); - } catch (Exception e) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR). - entity(new Error(e.getMessage())). - build(); - } - } - - @POST - @Path("engine/controllers/tools/coders/decoders/filters/rules/{ruleName}") - @ApiOperation( - value="Produces a Decoder Rule Filter in a format that the Policy Controller can understand", - notes="The result can be used with other APIs to attach a filter to a decoder" - ) - public Response rules(@ApiParam(value="Negate regex?", required=true) - @DefaultValue("false") @QueryParam("negate") boolean negate, - @ApiParam(value="Rule Name", required=true) - @PathParam("ruleName") String name, - @ApiParam(value="Regex expression", required=true) - String regex) { - String literalRegex = Pattern.quote(regex); - if (negate) - literalRegex = "^(?!" + literalRegex + "$).*"; - - return Response.status(Status.OK). - entity(new JsonProtocolFilter.FilterRule(name,literalRegex)). - build(); - } - - @GET - @Path("engine/controllers/{controller}/decoders") - @ApiOperation( - value="Gets all the decoders used by a controller", - notes="A Policy Controller uses decoders to deserialize incoming network messages from " + - "subscribed network topics into specific (fact) objects. " + - "The deserialized (fact) object will typically be inserted in the drools working " + - " memory of the controlled drools application.", - responseContainer="List", - response=ProtocolCoderToolset.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decoders(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName) { - try { - DroolsController drools = getDroolsController(controllerName); - List decoders = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId()); - return Response.status(Response.Status.OK). - entity(decoders). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " not acceptable")). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/decoders/filters") - @ApiOperation( - value="Gets all the filters used by a controller", - notes="A Policy Controller uses decoders to deserialize incoming network messages from " + - "subscribed network topics into specific (fact) objects. " + - "The deserialized (fact) object will typically be inserted in the drools working " + - " memory of the controlled drools application." + - "Acceptance filters are used to filter out undesired network messages for the given controller", - responseContainer="List", - response=CoderFilters.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decoderFilters(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName) { - try { - DroolsController drools = getDroolsController(controllerName); - List filters = EventProtocolCoder.manager.getDecoderFilters - (drools.getGroupId(), drools.getArtifactId()); - return Response.status(Response.Status.OK). - entity(filters). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " not acceptable")). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/decoders/{topic}") - @ApiOperation( - value="Gets all the decoders in use by a controller for a networked topic", - notes="A Policy Controller uses decoders to deserialize incoming network messages from " + - "subscribed network topics into specific (fact) objects. " + - "The deserialized (fact) object will typically be inserted in the drools working " + - " memory of the controlled drools application.", - responseContainer="List", - response=ProtocolCoderToolset.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller or topic cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decoder(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Networked Topic Name", required=true) - @PathParam("topic") String topic) { - try { - DroolsController drools = getDroolsController(controllerName); - ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topic); - return Response.status(Response.Status.OK). - entity(decoder). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + topic + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + topic + " not acceptable")). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/decoders/{topic}/filters") - @ApiOperation( - value="Gets all filters attached to decoders for a given networked topic in use by a controller", - notes="A Policy Controller uses decoders to deserialize incoming network messages from " + - "subscribed network topics into specific (fact) objects. " + - "The deserialized (fact) object will typically be inserted in the drools working " + - " memory of the controlled drools application." + - "Acceptance filters are used to filter out undesired network messages for the given controller", - responseContainer="List", - response=CoderFilters.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller or topic cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decoderFilter(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Networked Topic Name", required=true) - @PathParam("topic") String topic) { - try { - DroolsController drools = getDroolsController(controllerName); - ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topic); - if (decoder == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(topic + " does not exist")). - build(); - else - return Response.status(Response.Status.OK). - entity(decoder.getCoders()). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + topic + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + topic + " not acceptable")). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}") - @ApiOperation( - value="Gets all filters attached to decoders for a given subscribed networked topic " + - "and fact type", - notes="Decoders are associated with networked topics. A Policy Controller manages " + - "multiple topics and therefore its attached decoders. " + - "A Policy Controller uses filters to further specify the fact mapping. " + - "Filters are applied on a per fact type (classname).", - responseContainer="List", - response=CoderFilters.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, topic, or fact type cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decoderFilter(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Networked Topic Name", required=true) - @PathParam("topic") String topic, - @ApiParam(value="Fact Type", required=true) - @PathParam("factType") String factClass) { - try { - DroolsController drools = getDroolsController(controllerName); - ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topic); - CoderFilters filters = decoder.getCoder(factClass); - if (filters == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(topic + ":" + factClass + " does not exist")). - build(); - else - return Response.status(Response.Status.OK). - entity(filters). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + " not acceptable")). - build(); - } - } - - @PUT - @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}") - @ApiOperation( - value="Attaches filters to the decoder for a given networked topic " + - "and fact type", - notes="Decoders are associated with networked topics. A Policy Controller manages " + - "multiple topics and therefore its attached decoders. " + - "A Policy Controller uses filters to further specify the fact mapping. " + - "Filters are applied on a per fact type (classname).", - responseContainer="List", - response=CoderFilters.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, topic, fact type, cannot be found, " + - "or a filter has not been provided"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decoderFilter(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic, - @ApiParam(value="Fact Type", required=true) - @PathParam("factType") String factClass, - @ApiParam(value="Configuration Filter", required=true) - JsonProtocolFilter configFilters) { - - if (configFilters == null) { - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error("Configuration Filters not provided")). - build(); - } - - try { - DroolsController drools = getDroolsController(controllerName); - ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topic); - CoderFilters filters = decoder.getCoder(factClass); - if (filters == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(topic + ":" + factClass + " does not exist")). - build(); - filters.setFilter(configFilters); - return Response.status(Response.Status.OK). - entity(filters). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + " not acceptable")). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules") - @ApiOperation( - value="Gets the filter rules attached to a topic decoder of a controller", - notes="Decoders are associated with networked topics. A Policy Controller manages " + - "multiple topics and therefore its attached decoders. " + - "A Policy Controller uses filters to further specify the fact mapping. " + - "Filters are applied on a per fact type and are composed of field matching rules. ", - responseContainer="List", - response=FilterRule.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, topic, or fact type cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decoderFilterRules(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic, - @ApiParam(value="Fact Type", required=true) - @PathParam("factType") String factClass) { - try { - DroolsController drools = getDroolsController(controllerName); - ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topic); - - CoderFilters filters = decoder.getCoder(factClass); - if (filters == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). - build(); - - JsonProtocolFilter filter = filters.getFilter(); - if (filter == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). - build(); - - return Response.status(Response.Status.OK). - entity(filter.getRules()). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + " not acceptable")). - build(); - } - } - - @GET - @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}") - @ApiOperation( - value="Gets a filter rule by name attached to a topic decoder of a controller", - notes="Decoders are associated with networked topics. A Policy Controller manages " + - "multiple topics and therefore its attached decoders. " + - "A Policy Controller uses filters to further specify the fact mapping. " + - "Filters are applied on a per fact type and are composed of field matching rules. ", - responseContainer="List", - response=FilterRule.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, topic, fact type, or rule name cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decoderFilterRules(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic, - @ApiParam(value="Fact Type", required=true) - @PathParam("factType") String factClass, - @ApiParam(value="Rule Name", required=true) - @PathParam("ruleName") String ruleName) { - try { - DroolsController drools = getDroolsController(controllerName); - ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topic); - - CoderFilters filters = decoder.getCoder(factClass); - if (filters == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). - build(); - - JsonProtocolFilter filter = filters.getFilter(); - if (filter == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). - build(); - - return Response.status(Response.Status.OK). - entity(filter.getRules(ruleName)). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + ": " + ruleName + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + ":" + ruleName + " not acceptable")). - build(); - } - } - - @DELETE - @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}") - @ApiOperation( - value="Deletes a filter rule by name attached to a topic decoder of a controller", - notes="Decoders are associated with networked topics. A Policy Controller manages " + - "multiple topics and therefore its attached decoders. " + - "A Policy Controller uses filters to further specify the fact mapping. " + - "Filters are applied on a per fact type and are composed of field matching rules. ", - responseContainer="List", - response=FilterRule.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, topic, fact type, or rule name cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decoderFilterRuleDelete(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic, - @ApiParam(value="Fact Type", required=true) - @PathParam("factType") String factClass, - @ApiParam(value="Rule Name", required=true) - @PathParam("ruleName") String ruleName, - @ApiParam(value="Filter Rule", required=true) - FilterRule rule) { - - try { - DroolsController drools = getDroolsController(controllerName); - ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topic); - - CoderFilters filters = decoder.getCoder(factClass); - if (filters == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). - build(); - - JsonProtocolFilter filter = filters.getFilter(); - if (filter == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). - build(); - - if (rule == null) { - filter.deleteRules(ruleName); - return Response.status(Response.Status.OK). - entity(filter.getRules()). - build(); - } - - if (rule.getName() == null || !rule.getName().equals(ruleName)) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topic + ":" + factClass + ":" + ruleName + - " rule name request inconsistencies (" + rule.getName() + ")")). - build(); - - filter.deleteRule(ruleName, rule.getRegex()); - return Response.status(Response.Status.OK). - entity(filter.getRules()). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + ": " + ruleName + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + ":" + ruleName + " not acceptable")). - build(); - } - } - - @PUT - @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules") - @ApiOperation( - value="Places a new filter rule in a topic decoder", - notes="Decoders are associated with networked topics. A Policy Controller manages " + - "multiple topics and therefore its attached decoders. " + - "A Policy Controller uses filters to further specify the fact mapping. " + - "Filters are applied on a per fact type and are composed of field matching rules. ", - responseContainer="List", - response=FilterRule.class - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The controller, topic, or fact type cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decoderFilterRule(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic, - @ApiParam(value="Fact Type", required=true) - @PathParam("factType") String factClass, - @ApiParam(value="Rule Name", required=true) - @PathParam("ruleName") String ruleName, - @ApiParam(value="Filter Rule", required=true) - FilterRule rule) { - - try { - DroolsController drools = getDroolsController(controllerName); - ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders - (drools.getGroupId(), drools.getArtifactId(), topic); - - CoderFilters filters = decoder.getCoder(factClass); - if (filters == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")). - build(); - - JsonProtocolFilter filter = filters.getFilter(); - if (filter == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")). - build(); - - if (rule.getName() == null) - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + ":" + topic + ":" + factClass + - " rule name request inconsistencies (" + rule.getName() + ")")). - build(); - - filter.addRule(rule.getName(), rule.getRegex()); - return Response.status(Response.Status.OK). - entity(filter.getRules()). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + topic + ":" + - factClass + " not acceptable")). - build(); - } - } - - @POST - @Path("engine/controllers/{controller}/decoders/{topic}") - @Consumes(MediaType.TEXT_PLAIN) - @ApiOperation( - value="Decodes a string into a fact object, and encodes it back into a string", - notes="Tests the decode/encode functions of a controller", - response=CodingResult.class - ) - @ApiResponses(value = { - @ApiResponse(code=400, message="Bad input has been provided"), - @ApiResponse(code=404, message="The controller cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response decode(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName, - @ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic, - @ApiParam(value="JSON String to decode", required=true) - String json) { - - PolicyController policyController; - try { - policyController = PolicyController.factory.get(controllerName); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(controllerName + ":" + topic + ":" + - " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + ":" + topic + ":" + - " not acceptable")). - build(); - } - - CodingResult result = new CodingResult(); - result.decoding = false; - result.encoding = false; - result.jsonEncoding = null; - - Object event; - try { - event = EventProtocolCoder.manager.decode - (policyController.getDrools().getGroupId(), - policyController.getDrools().getArtifactId(), - topic, - json); - result.decoding = true; - } catch (Exception e) { - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(e.getMessage())). - build(); - } - - try { - result.jsonEncoding = EventProtocolCoder.manager.encode(topic, event); - result.encoding = true; - } catch (Exception e) { - // continue so to propagate decoding results .. - } - - return Response.status(Response.Status.OK). - entity(result). - build(); - } - - @GET - @Path("engine/controllers/{controller}/encoders") - @ApiOperation( - value="Retrieves the encoder filters of a controller", - notes="The encoders serializes a fact object, typically for network transmission", - responseContainer="List", - response=CoderFilters.class - ) - @ApiResponses(value = { - @ApiResponse(code=400, message="Bad input has been provided"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response encoderFilters(@ApiParam(value="Policy Controller Name", required=true) - @PathParam("controller") String controllerName) { - List encoders; - try { - PolicyController controller = PolicyController.factory.get(controllerName); - DroolsController drools = controller.getDrools(); - encoders = EventProtocolCoder.manager.getEncoderFilters - (drools.getGroupId(), drools.getArtifactId()); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.BAD_REQUEST). - entity(new Error(controllerName + " not found: " + e.getMessage())). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(controllerName + " is not accepting the request")).build(); - } - - return Response.status(Response.Status.OK). - entity(encoders). - build(); - } - - @GET - @Path("engine/topics") - @ApiOperation( - value="Retrieves the managed topics", - notes="Network Topics Aggregation", - response=TopicEndpoint.class - ) - public Response topics() { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager). - build(); - } - - @GET - @Path("engine/topics/switches") - @ApiOperation( - value="Topics Control Switches", - notes="List of the Topic Control Switches", - responseContainer="List" - ) - public Response topicSwitches() { - return Response.status(Response.Status.OK). - entity(Arrays.asList(Switches.values())). - build(); - } - - @PUT - @Path("engine/topics/switches/lock") - @ApiOperation( - value="Locks all the managed topics", - notes="The operation affects all managed sources and sinks", - response=TopicEndpoint.class - ) - @ApiResponses(value = { - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response topicsLock() { - boolean success = TopicEndpoint.manager.lock(); - if (success) - return Response.status(Status.OK). - entity(TopicEndpoint.manager). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation")). - build(); - } - - @DELETE - @Path("engine/topics/switches/lock") - @ApiOperation( - value="Unlocks all the managed topics", - notes="The operation affects all managed sources and sinks", - response=TopicEndpoint.class - ) - @ApiResponses(value = { - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response topicsUnlock() { - boolean success = TopicEndpoint.manager.unlock(); - if (success) - return Response.status(Status.OK). - entity(TopicEndpoint.manager). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation")). - build(); - } - - @GET - @Path("engine/topics/sources") - @ApiOperation( - value="Retrieves the managed topic sources", - notes="Network Topic Sources Agregation", - responseContainer="List", - response=TopicSource.class - ) - public Response sources() { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager.getTopicSources()). - build(); - } - - @GET - @Path("engine/topics/sinks") - @ApiOperation( - value="Retrieves the managed topic sinks", - notes="Network Topic Sinks Agregation", - responseContainer="List", - response=TopicSink.class - ) - public Response sinks() { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager.getTopicSinks()). - build(); - } - - @GET - @Path("engine/topics/sources/ueb") - @ApiOperation( - value="Retrieves the UEB managed topic sources", - notes="UEB Topic Sources Agregation", - responseContainer="List", - response=UebTopicSource.class - ) - public Response uebSources() { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager.getUebTopicSources()). - build(); - } - - @GET - @Path("engine/topics/sinks/ueb") - @ApiOperation( - value="Retrieves the UEB managed topic sinks", - notes="UEB Topic Sinks Agregation", - responseContainer="List", - response=UebTopicSource.class - ) - public Response uebSinks() { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager.getUebTopicSinks()). - build(); - } - - @GET - @Path("engine/topics/sources/dmaap") - @ApiOperation( - value="Retrieves the DMaaP managed topic sources", - notes="DMaaP Topic Sources Agregation", - responseContainer="List", - response=DmaapTopicSource.class - ) - public Response dmaapSources() { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager.getDmaapTopicSources()). - build(); - } - - @GET - @Path("engine/topics/sinks/dmaap") - @ApiOperation( - value="Retrieves the DMaaP managed topic sinks", - notes="DMaaP Topic Sinks Agregation", - responseContainer="List", - response=DmaapTopicSink.class - ) - public Response dmaapSinks() { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager.getDmaapTopicSinks()). - build(); - } - - @GET - @Path("engine/topics/sources/ueb/{topic}") - @ApiOperation( - value="Retrieves an UEB managed topic source", - notes="This is an UEB Network Communicaton Endpoint source of messages for the Engine", - response=UebTopicSource.class - ) - public Response uebSourceTopic(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager.getUebTopicSource(topic)). - build(); - } - - @GET - @Path("engine/topics/sinks/ueb/{topic}") - @ApiOperation( - value="Retrieves an UEB managed topic sink", - notes="This is an UEB Network Communicaton Endpoint destination of messages from the Engine", - response=UebTopicSink.class - ) - public Response uebSinkTopic(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager.getUebTopicSink(topic)). - build(); - } - - @GET - @Path("engine/topics/sources/dmaap/{topic}") - @ApiOperation( - value="Retrieves a DMaaP managed topic source", - notes="This is a DMaaP Network Communicaton Endpoint source of messages for the Engine", - response=DmaapTopicSource.class - ) - public Response dmaapSourceTopic(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager.getDmaapTopicSource(topic)). - build(); - } - - @GET - @Path("engine/topics/sinks/dmaap/{topic}") - @ApiOperation( - value="Retrieves a DMaaP managed topic sink", - notes="This is a DMaaP Network Communicaton Endpoint destination of messages from the Engine", - response=DmaapTopicSink.class - ) - public Response dmaapSinkTopic(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - return Response.status(Response.Status.OK). - entity(TopicEndpoint.manager.getDmaapTopicSink(topic)). - build(); - } - - @GET - @Path("engine/topics/sources/ueb/{topic}/events") - @ApiOperation( - value="Retrieves the latest events received by an UEB topic", - notes="This is a UEB Network Communicaton Endpoint source of messages for the Engine", - responseContainer="List" - ) - public Response uebSourceEvents(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - return Response.status(Status.OK). - entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSource(topic).getRecentEvents())). - build(); - } - - @GET - @Path("engine/topics/sinks/ueb/{topic}/events") - @ApiOperation( - value="Retrieves the latest events sent from a topic", - notes="This is a UEB Network Communicaton Endpoint sink of messages from the Engine", - responseContainer="List" - ) - public Response uebSinkEvents(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - return Response.status(Status.OK). - entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSink(topic).getRecentEvents())). - build(); - } - - @GET - @Path("engine/topics/sources/dmaap/{topic}/events") - @ApiOperation( - value="Retrieves the latest events received by a DMaaP topic", - notes="This is a DMaaP Network Communicaton Endpoint source of messages for the Engine", - responseContainer="List" - ) - public Response dmaapSourceEvents(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - return Response.status(Status.OK). - entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSource(topic).getRecentEvents())). - build(); - } - - @GET - @Path("engine/topics/sinks/dmaap/{topic}/events") - @ApiOperation( - value="Retrieves the latest events send through a DMaaP topic", - notes="This is a DMaaP Network Communicaton Endpoint destination of messages from the Engine", - responseContainer="List" - ) - public Response dmaapSinkEvents( - @PathParam("topic") String topic) { - return Response.status(Status.OK). - entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSink(topic).getRecentEvents())). - build(); - } - - @GET - @Path("engine/topics/sources/ueb/{topic}/switches") - @ApiOperation( - value="UEB Topic Control Switches", - notes="List of the UEB Topic Control Switches", - responseContainer="List" - ) - public Response uebTopicSwitches() { - return Response.status(Response.Status.OK). - entity(Arrays.asList(Switches.values())). - build(); - } - - @PUT - @Path("engine/topics/sources/ueb/{topic}/switches/lock") - @ApiOperation( - value="Locks an UEB Source topic", - response=UebTopicSource.class - ) - @ApiResponses(value = { - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response uebTopicLock(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - UebTopicSource source = TopicEndpoint.manager.getUebTopicSource(topic); - boolean success = source.lock(); - if (success) - return Response.status(Status.OK). - entity(source). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation on " + topic)). - build(); - } - - @DELETE - @Path("engine/topics/sources/ueb/{topic}/switches/lock") - @ApiOperation( - value="Unlocks an UEB Source topic", - response=UebTopicSource.class - ) - @ApiResponses(value = { - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response uebTopicUnlock(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - UebTopicSource source = TopicEndpoint.manager.getUebTopicSource(topic); - boolean success = source.unlock(); - if (success) - return Response.status(Status.OK). - entity(source). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation on " + topic)). - build(); - } - - @GET - @Path("engine/topics/sources/dmaap/{topic}/switches") - @ApiOperation( - value="DMaaP Topic Control Switches", - notes="List of the DMaaP Topic Control Switches", - responseContainer="List" - ) - public Response dmaapTopicSwitches() { - return Response.status(Response.Status.OK). - entity(Arrays.asList(Switches.values())). - build(); - } - - @PUT - @Path("engine/topics/sources/dmaap/{topic}/switches/lock") - @ApiOperation( - value="Locks an DMaaP Source topic", - response=DmaapTopicSource.class - ) - @ApiResponses(value = { - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response dmmapTopicLock(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - DmaapTopicSource source = TopicEndpoint.manager.getDmaapTopicSource(topic); - boolean success = source.lock(); - if (success) - return Response.status(Status.OK). - entity(source). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("cannot perform operation on " + topic)). - build(); - } - - @DELETE - @Path("engine/topics/sources/dmaap/{topic}/switches/lock") - @ApiOperation( - value="Unlocks an DMaaP Source topic", - response=DmaapTopicSource.class - ) - @ApiResponses(value = { - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled") - }) - public Response dmaapTopicUnlock(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic) { - DmaapTopicSource source = TopicEndpoint.manager.getDmaapTopicSource(topic); - boolean success = source.unlock(); - if (success) - return Response.status(Status.OK). - entity(source). - build(); - else - return Response.status(Status.SERVICE_UNAVAILABLE). - entity(new Error("cannot perform operation on " + topic)). - build(); - } - - @PUT - @Path("engine/topics/sources/ueb/{topic}/events") - @Consumes(MediaType.TEXT_PLAIN) - @ApiOperation( - value="Offers an event to an UEB topic for internal processing by the engine", - notes="The offered event is treated as it was incoming from the network", - responseContainer="List" - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The topic information cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled"), - @ApiResponse(code=500, message="A server error has occurred processing this request") - }) - public Response uebOffer(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic, - @ApiParam(value="Network Message", required=true) - String json) { - try { - UebTopicSource uebReader = TopicEndpoint.manager.getUebTopicSource(topic); - boolean success = uebReader.offer(json); - if (success) - return Response.status(Status.OK). - entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSource(topic).getRecentEvents())). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("Failure to inject event over " + topic)). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(topic + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(topic + " not acceptable due to current state")). - build(); - } catch (Exception e) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR). - entity(new Error(e.getMessage())). - build(); - } - } - - @PUT - @Path("engine/topics/sources/dmaap/{topic}/events") - @Consumes(MediaType.TEXT_PLAIN) - @ApiOperation( - value="Offers an event to a DMaaP topic for internal processing by the engine", - notes="The offered event is treated as it was incoming from the network", - responseContainer="List" - ) - @ApiResponses(value = { - @ApiResponse(code=404, message="The topic information cannot be found"), - @ApiResponse(code=406, message="The system is an administrative state that prevents " + - "this request to be fulfilled"), - @ApiResponse(code=500, message="A server error has occurred processing this request") - }) - public Response dmaapOffer(@ApiParam(value="Topic Name", required=true) - @PathParam("topic") String topic, - @ApiParam(value="Network Message", required=true) - String json) { - try { - DmaapTopicSource dmaapReader = TopicEndpoint.manager.getDmaapTopicSource(topic); - boolean success = dmaapReader.offer(json); - if (success) - return Response.status(Status.OK). - entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSource(topic).getRecentEvents())). - build(); - else - return Response.status(Status.NOT_ACCEPTABLE). - entity(new Error("Failure to inject event over " + topic)). - build(); - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.NOT_FOUND). - entity(new Error(topic + " not found")). - build(); - } catch (IllegalStateException e) { - return Response.status(Response.Status.NOT_ACCEPTABLE). - entity(new Error(topic + " not acceptable due to current state")). - build(); - } catch (Exception e) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR). - entity(new Error(e.getMessage())). - build(); - } - } - - @GET - @Path("engine/tools/uuid") - @ApiOperation( - value="Produces an UUID", - notes="UUID generation utility" - ) - @Produces(MediaType.TEXT_PLAIN) - public Response uuid() { - return Response.status(Status.OK). - entity(UUID.randomUUID().toString()). - build(); - } - - @GET - @Path("engine/tools/loggers") - @ApiOperation( - value="all active loggers", - responseContainer="List" - ) - @ApiResponses(value = { - @ApiResponse(code=500, message="logging misconfiguration") - }) - public Response loggers() { - List names = new ArrayList(); - if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) { - logger.warn("The SLF4J logger factory is not configured for logback"); - return Response.status(Status.INTERNAL_SERVER_ERROR). - entity(names).build(); - } - - LoggerContext context = - (LoggerContext) LoggerFactory.getILoggerFactory(); - for (Logger logger: context.getLoggerList()) { - names.add(logger.getName()); - } - - return Response.status(Status.OK). - entity(names). - build(); - } - - @GET - @Path("engine/tools/loggers/{logger}") - @ApiOperation( - value="logging level of a logger" - ) - @ApiResponses(value = { - @ApiResponse(code=500, message="logging misconfiguration"), - @ApiResponse(code=404, message="logger not found") - }) - public Response loggerName(@ApiParam(value="Logger Name", required=true) - @PathParam("logger") String loggerName) { - if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) { - logger.warn("The SLF4J logger factory is not configured for logback"); - return Response.status(Status.INTERNAL_SERVER_ERROR).build(); - } - - LoggerContext context = - (LoggerContext) LoggerFactory.getILoggerFactory(); - ch.qos.logback.classic.Logger logger = context.getLogger(loggerName); - if (logger == null) { - return Response.status(Status.NOT_FOUND).build(); - } - - String loggerLevel = (logger.getLevel() != null) ? logger.getLevel().toString() : ""; - return Response.status(Status.OK).entity(loggerLevel).build(); - } - - @PUT - @Path("engine/tools/loggers/{logger}/{level}") - @ApiOperation( - value="sets the logger level", - notes="Please use the SLF4J logger levels" - ) - @ApiResponses(value = { - @ApiResponse(code=500, message="logging misconfiguration"), - @ApiResponse(code=404, message="logger not found") - }) - public Response loggerName(@ApiParam(value="Logger Name", required=true) - @PathParam("logger") String loggerName, - @ApiParam(value="Logger Level", required=true) - @PathParam("level") String loggerLevel) { - if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) { - logger.warn("The SLF4J logger factory is not configured for logback"); - return Response.status(Status.INTERNAL_SERVER_ERROR).build(); - } - - LoggerContext context = - (LoggerContext) LoggerFactory.getILoggerFactory(); - ch.qos.logback.classic.Logger logger = context.getLogger(loggerName); - if (logger == null) { - return Response.status(Status.NOT_FOUND).build(); - } - - logger.setLevel(ch.qos.logback.classic.Level.toLevel(loggerLevel)); - return Response.status(Status.OK).entity(logger.getLevel().toString()).build(); - } - - /** - * gets the underlying drools controller from the named policy controller - * @param controllerName the policy controller name - * @return the underlying drools controller - * @throws IllegalArgumentException if an invalid controller name has been passed in - */ - protected DroolsController getDroolsController(String controllerName) throws IllegalArgumentException { - PolicyController controller = PolicyController.factory.get(controllerName); - if (controller == null) - throw new IllegalArgumentException(controllerName + " does not exist"); - - DroolsController drools = controller.getDrools(); - if (drools == null) - throw new IllegalArgumentException(controllerName + " has no drools configuration"); - - return drools; - } - - /* - * Helper classes for aggregation of results - */ - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("rest-telemetry-api []"); - return builder.toString(); - } - - /** - * Coding/Encoding Results Aggregation Helper class - */ - public static class CodingResult { - /** - * serialized output - */ - - public String jsonEncoding; - /** - * encoding result - */ - - public Boolean encoding; - - /** - * decoding result - */ - public Boolean decoding; - } - - /** - * Generic Error Reporting class - */ - public static class Error { - public String error; - - public Error(String error) { - this.error = error; - } - } - - /** - * Feed Ports into Resources - */ - public enum Inputs { - configuration, - } - - /** - * Resource Toggles - */ - public enum Switches { - activation, - lock, - } -} - diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/Main.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/Main.java deleted file mode 100644 index 1bb9a320..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/system/Main.java +++ /dev/null @@ -1,135 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.system; - -import java.io.File; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Properties; - -import org.openecomp.policy.drools.persistence.SystemPersistence; -import org.openecomp.policy.drools.utils.PropertyUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Programmatic entry point to the management layer - */ -public class Main { - - /** - * logback configuration file system property - */ - public static final String LOGBACK_CONFIGURATION_FILE_SYSTEM_PROPERTY = "logback.configurationFile"; - - /** - * logback configuration file system property - */ - public static final String LOGBACK_CONFIGURATION_FILE_DEFAULT = "config/logback.xml"; - - /** - * constructor (hides public default one) - */ - private Main() {} - - /** - * main - * - * @param args program arguments - */ - public static void main(String args[]) { - - /* logging defaults */ - - if (System.getProperty(LOGBACK_CONFIGURATION_FILE_SYSTEM_PROPERTY) == null) - System.setProperty(LOGBACK_CONFIGURATION_FILE_SYSTEM_PROPERTY, LOGBACK_CONFIGURATION_FILE_DEFAULT); - - /* 0. boot */ - - PolicyEngine.manager.boot(args); - - Logger logger = LoggerFactory.getLogger(Main.class); - - File configDir = new File(SystemPersistence.CONFIG_DIR_NAME); - - if (!configDir.isDirectory()) { - throw new IllegalArgumentException - ("config directory: " + configDir.getAbsolutePath() + - " not found"); - } - - /* 1. Configure the Engine */ - - try { - Path policyEnginePath = Paths.get(configDir.toPath().toString(), SystemPersistence.PROPERTIES_FILE_ENGINE); - Properties properties = PropertyUtil.getProperties(policyEnginePath.toFile()); - PolicyEngine.manager.configure(properties); - } catch (Exception e) { - logger.warn("Main: cannot initialize {} because of {}", PolicyEngine.manager, e.getMessage(), e); - } - - /* 2. Start the Engine with the basic services only (no Policy Controllers) */ - - try { - boolean success = PolicyEngine.manager.start(); - if (!success) { - logger.warn("Main: {} has been partially started", PolicyEngine.manager); - } - } catch (IllegalStateException e) { - logger.warn("Main: cannot start {} (bad state) because of {}", PolicyEngine.manager, e.getMessage(), e); - } catch (Exception e) { - logger.warn("Main: cannot start {} because of {}", PolicyEngine.manager, e.getMessage(), e); - System.exit(1); - } - - /* 3. Create and start the controllers */ - - File[] controllerFiles = configDir.listFiles(); - for (File config : controllerFiles) { - - if (config.getName().endsWith(SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX)) { - int idxSuffix = - config.getName().indexOf(SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX); - int lastIdxSuffix = - config.getName().lastIndexOf(SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX); - if (idxSuffix != lastIdxSuffix) { - throw new IllegalArgumentException - ("Improper naming of controller properties file: " + - "Expected " + - SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX); - } - - String name = - config.getName().substring(0, lastIdxSuffix); - try { - Properties properties = PropertyUtil.getProperties(config); - PolicyController controller = PolicyEngine.manager.createPolicyController(name, properties); - controller.start(); - } catch (Exception e) { - logger.error("Main: cannot instantiate policy-controller {} because of {}", name, e.getMessage(), e); - } catch (LinkageError e) { - logger.warn("Main: cannot instantiate policy-controller {} (linkage) because of {}", - name, e.getMessage(), e); - } - } - } - } -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyController.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyController.java deleted file mode 100644 index 15d1acf3..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyController.java +++ /dev/null @@ -1,110 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.system; - -import java.util.List; -import java.util.Properties; - -import org.openecomp.policy.drools.controller.DroolsController; -import org.openecomp.policy.drools.event.comm.TopicSource; -import org.openecomp.policy.drools.event.comm.Topic.CommInfrastructure; -import org.openecomp.policy.drools.event.comm.TopicSink; -import org.openecomp.policy.drools.properties.Lockable; -import org.openecomp.policy.drools.properties.Startable; -import org.openecomp.policy.drools.protocol.configuration.DroolsConfiguration; - -/** - * A Policy Controller is the higher level unit of control. It corresponds to - * the ncomp equivalent of a controller. It provides management of underlying - * resources associated with the policy controller, which is a) communication - * infrastructure, and b) policy-core (drools) session infrastructure - * - */ -public interface PolicyController extends Startable, Lockable { - - /** - * name of this Policy Controller - */ - public String getName(); - - /** - * Get the topic readers of interest for this controller - */ - public List getTopicSources(); - - /** - * Get the topic readers of interest for this controller - */ - public List getTopicSinks(); - - /** - * Get the Drools Controller - */ - public DroolsController getDrools(); - - /** - * update maven configuration - * - * @param newDroolsConfiguration new drools configuration - * @return true if the update was successful, false otherwise - */ - public boolean updateDrools(DroolsConfiguration newDroolsConfiguration); - - /** - * Get the Properties - */ - public Properties getProperties(); - - /** - * Attempts delivering of an String over communication - * infrastructure "busType" - * - * @param eventBus Communication infrastructure identifier - * @param topic topic - * @param event the event object to send - * - * @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 permitted (ie. locked or stopped). - * @throws UnsupportedOperationException when the engine cannot deliver due - * to the functionality missing (ie. communication infrastructure - * not supported. - */ - public boolean deliver(CommInfrastructure busType, String topic, - Object event) - throws IllegalArgumentException, IllegalStateException, - UnsupportedOperationException; - - /** - * halts and permanently releases all resources - * @throws IllegalStateException - */ - public void halt() throws IllegalStateException; - - /** - * Factory that tracks and manages Policy Controllers - */ - public static PolicyControllerFactory factory = - new IndexedPolicyControllerFactory(); - -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyControllerFactory.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyControllerFactory.java deleted file mode 100644 index 12a8acdc..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyControllerFactory.java +++ /dev/null @@ -1,522 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.system; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Properties; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.openecomp.policy.drools.controller.DroolsController; -import org.openecomp.policy.drools.features.PolicyControllerFeatureAPI; -import org.openecomp.policy.drools.protocol.configuration.DroolsConfiguration; -import org.openecomp.policy.drools.system.internal.AggregatedPolicyController; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -/** - * Policy Controller Factory to manage controller creation, destruction, - * and retrieval for management interfaces - */ -public interface PolicyControllerFactory { - /** - * Build a controller from a properties file - * - * @param name the global name of this controller - * @param properties input parameters in form of properties for controller - * initialization. - * - * @return a Policy Controller - * - * @throws IllegalArgumentException invalid values provided in properties - */ - public PolicyController build(String name, Properties properties) - throws IllegalArgumentException; - - /** - * patches (updates) a controller from a critical configuration update. - * - * @param name - * @param configController - * - * @return a Policy Controller - */ - public PolicyController patch(String name, DroolsConfiguration configController); - - /** - * rebuilds (updates) a controller from a configuration update. - * - * @param controller - * @param configController - * - * @return a Policy Controller - */ - public PolicyController patch(PolicyController controller, - DroolsConfiguration configController); - - /** - * get PolicyController from DroolsController - * - * @param droolsController - * @return - * @throws IllegalArgumentException - * @throws IllegalStateException - */ - public PolicyController get(DroolsController droolsController) - throws IllegalArgumentException, IllegalStateException; - - /** - * Makes the Policy Controller identified by controllerName not operational, but - * does not delete its associated data - * - * @param controllerName name of the policy controller - * @throws IllegalArgumentException invalid arguments - */ - public void shutdown(String controllerName) throws IllegalArgumentException;; - - /** - * Makes the Policy Controller identified by controller not operational, but - * does not delete its associated data - * - * @param controller a Policy Controller - * @throws IllegalArgumentException invalid arguments - */ - public void shutdown(PolicyController controller) throws IllegalArgumentException; - - /** - * Releases all Policy Controllers from operation - */ - public void shutdown(); - - /** - * Destroys this Policy Controller - * - * @param controllerName name of the policy controller - * @throws IllegalArgumentException invalid arguments - */ - public void destroy(String controllerName) throws IllegalArgumentException;; - - /** - * Destroys this Policy Controller - * - * @param controller a Policy Controller - * @throws IllegalArgumentException invalid arguments - */ - public void destroy(PolicyController controller) throws IllegalArgumentException; - - /** - * Releases all Policy Controller resources - */ - public void destroy(); - - /** - * gets the Policy Controller identified by its name - * - * @param policyControllerName - * @return - * @throws IllegalArgumentException - * @throws IllegalStateException - */ - public PolicyController get(String policyControllerName) - throws IllegalArgumentException, IllegalStateException; - - /** - * gets the Policy Controller identified by group and artifact ids - * - * @param groupId group id - * @param artifactId artifact id - * @return - * @throws IllegalArgumentException - * @throws IllegalStateException - */ - public PolicyController get(String groupId, String artifactId) - throws IllegalArgumentException, IllegalStateException; - - /** - * get features attached to the Policy Controllers - * @return list of features - */ - public List getFeatureProviders(); - - /** - * get named feature attached to the Policy Controllers - * @return the feature - */ - public PolicyControllerFeatureAPI getFeatureProvider(String featureName) - throws IllegalArgumentException; - - /** - * get features attached to the Policy Controllers - * @return list of features - */ - public List getFeatures(); - - /** - * returns the current inventory of Policy Controllers - * - * @return a list of Policy Controllers - */ - public List inventory(); -} - -/** - * Factory of Policy Controllers indexed by the name of the Policy Controller - */ -class IndexedPolicyControllerFactory implements PolicyControllerFactory { - // get an instance of logger - private static Logger logger = LoggerFactory.getLogger(PolicyControllerFactory.class); - - /** - * Policy Controller Name Index - */ - protected HashMap policyControllers = - new HashMap(); - - /** - * Group/Artifact Ids Index - */ - protected HashMap coordinates2Controller = - new HashMap(); - - /** - * produces key for indexing controller names - * - * @param group group id - * @param artifactId artifact id - * @return index key - */ - protected String toKey(String groupId, String artifactId) { - return groupId + ":" + artifactId; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized PolicyController build(String name, Properties properties) - throws IllegalArgumentException { - - if (this.policyControllers.containsKey(name)) { - return this.policyControllers.get(name); - } - - /* A PolicyController does not exist */ - - PolicyController controller = - new AggregatedPolicyController(name, properties); - - String coordinates = toKey(controller.getDrools().getGroupId(), - controller.getDrools().getArtifactId()); - - this.policyControllers.put(name, controller); - - - if (controller.getDrools().isBrained()) - this.coordinates2Controller.put(coordinates, controller); - - return controller; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized PolicyController patch(String name, DroolsConfiguration droolsConfig) - throws IllegalArgumentException { - - if (name == null || name.isEmpty() || !this.policyControllers.containsKey(name)) { - throw new IllegalArgumentException("Invalid " + name); - } - - if (droolsConfig == null) - throw new IllegalArgumentException("Invalid Drools Configuration"); - - PolicyController controller = this.get(name); - - if (controller == null) { - logger.warn("A POLICY CONTROLLER of name " + name + - "does not exist for patch operation: " + droolsConfig); - - throw new IllegalArgumentException("Not a valid controller of name " + name); - } - - this.patch(controller, droolsConfig); - - if (logger.isInfoEnabled()) - logger.info("UPDATED drools configuration: " + droolsConfig + " on " + this); - - return controller; - } - - - /** - * {@inheritDoc} - */ - @Override - public PolicyController patch(PolicyController controller, DroolsConfiguration droolsConfig) - throws IllegalArgumentException { - - if (controller == null) - throw new IllegalArgumentException("Not a valid controller: null"); - - if (!controller.updateDrools(droolsConfig)) { - logger.warn("Cannot update drools configuration: " + droolsConfig + " on " + this); - throw new IllegalArgumentException("Cannot update drools configuration Drools Configuration"); - } - - if (logger.isInfoEnabled()) - logger.info("UPDATED drools configuration: " + droolsConfig + " on " + this); - - String coordinates = toKey(controller.getDrools().getGroupId(), - controller.getDrools().getArtifactId()); - - if (controller.getDrools().isBrained()) - this.coordinates2Controller.put(coordinates, controller); - - return controller; - } - - /** - * {@inheritDoc} - */ - @Override - public void shutdown(String controllerName) throws IllegalArgumentException { - - if (controllerName == null || controllerName.isEmpty()) { - throw new IllegalArgumentException("Invalid " + controllerName); - } - - synchronized(this) { - if (!this.policyControllers.containsKey(controllerName)) { - return; - } - - PolicyController controller = this.policyControllers.get(controllerName); - this.shutdown(controller); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void shutdown(PolicyController controller) throws IllegalArgumentException { - this.unmanage(controller); - controller.shutdown(); - } - - /** - * {@inheritDoc} - */ - @Override - public void shutdown() { - List controllers = this.inventory(); - for (PolicyController controller: controllers) { - controller.shutdown(); - } - - synchronized(this) { - this.policyControllers.clear(); - this.coordinates2Controller.clear(); - } - } - - /** - * unmanage the controller - * - * @param controller - * @return - * @throws IllegalArgumentException - */ - protected void unmanage(PolicyController controller) throws IllegalArgumentException { - if (controller == null) { - throw new IllegalArgumentException("Invalid Controller"); - } - - synchronized(this) { - if (!this.policyControllers.containsKey(controller.getName())) { - return; - } - controller = this.policyControllers.remove(controller.getName()); - - String coordinates = toKey(controller.getDrools().getGroupId(), - controller.getDrools().getArtifactId()); - this.coordinates2Controller.remove(coordinates); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void destroy(String controllerName) throws IllegalArgumentException { - - if (controllerName == null || controllerName.isEmpty()) { - throw new IllegalArgumentException("Invalid " + controllerName); - } - - synchronized(this) { - if (!this.policyControllers.containsKey(controllerName)) { - return; - } - - PolicyController controller = this.policyControllers.get(controllerName); - this.destroy(controller); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void destroy(PolicyController controller) throws IllegalArgumentException { - this.unmanage(controller); - controller.halt(); - } - - /** - * {@inheritDoc} - */ - @Override - public void destroy() { - List controllers = this.inventory(); - for (PolicyController controller: controllers) { - controller.halt(); - } - - synchronized(this) { - this.policyControllers.clear(); - this.coordinates2Controller.clear(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public PolicyController get(String name) throws IllegalArgumentException, IllegalStateException { - - if (name == null || name.isEmpty()) { - throw new IllegalArgumentException("Invalid " + name); - } - - synchronized(this) { - if (this.policyControllers.containsKey(name)) { - return this.policyControllers.get(name); - } else { - throw new IllegalArgumentException("Invalid " + name); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public PolicyController get(String groupId, String artifactId) - throws IllegalArgumentException, IllegalStateException { - - if (groupId == null || groupId.isEmpty() || - artifactId == null || artifactId.isEmpty()) { - throw new IllegalArgumentException("Invalid group/artifact ids"); - } - - synchronized(this) { - String key = toKey(groupId,artifactId); - if (this.coordinates2Controller.containsKey(key)) { - return this.coordinates2Controller.get(key); - } else { - throw new IllegalArgumentException("Invalid " + key); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public PolicyController get(DroolsController droolsController) - throws IllegalArgumentException, IllegalStateException { - - if (droolsController == null) { - throw new IllegalArgumentException("No Drools Controller provided"); - } - - synchronized(this) { - String key = toKey(droolsController.getGroupId(), droolsController.getArtifactId()); - if (this.coordinates2Controller.containsKey(key)) { - return this.coordinates2Controller.get(key); - } else { - logger.error("Drools Controller not associated with Policy Controller " + droolsController + ":" + this); - throw new IllegalStateException("Drools Controller not associated with Policy Controller " + droolsController + ":" + this); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public List inventory() { - List controllers = - new ArrayList(this.policyControllers.values()); - return controllers; - } - - /** - * {@inheritDoc} - */ - @Override - public List getFeatures() { - List features = new ArrayList(); - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - features.add(feature.getName()); - } - return features; - } - - /** - * {@inheritDoc} - */ - @JsonIgnore - @Override - public List getFeatureProviders() { - return PolicyControllerFeatureAPI.providers.getList(); - } - - /** - * {@inheritDoc} - */ - @Override - public PolicyControllerFeatureAPI getFeatureProvider(String featureName) throws IllegalArgumentException { - if (featureName == null || featureName.isEmpty()) - throw new IllegalArgumentException("A feature name must be provided"); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - if (feature.getName().equals(featureName)) - return feature; - } - - throw new IllegalArgumentException("Invalid Feature Name: " + featureName); - } -} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java deleted file mode 100644 index 02479ec8..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java +++ /dev/null @@ -1,1461 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.system; - -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.openecomp.policy.drools.controller.DroolsController; -import org.openecomp.policy.drools.core.PolicyContainer; -import org.openecomp.policy.drools.core.jmx.PdpJmxListener; -import org.openecomp.policy.drools.event.comm.Topic; -import org.openecomp.policy.drools.event.comm.Topic.CommInfrastructure; -import org.openecomp.policy.drools.event.comm.TopicEndpoint; -import org.openecomp.policy.drools.event.comm.TopicListener; -import org.openecomp.policy.drools.event.comm.TopicSink; -import org.openecomp.policy.drools.event.comm.TopicSource; -import org.openecomp.policy.drools.features.PolicyControllerFeatureAPI; -import org.openecomp.policy.drools.features.PolicyEngineFeatureAPI; -import org.openecomp.policy.drools.http.server.HttpServletServer; -import org.openecomp.policy.drools.persistence.SystemPersistence; -import org.openecomp.policy.drools.properties.Lockable; -import org.openecomp.policy.drools.properties.PolicyProperties; -import org.openecomp.policy.drools.properties.Startable; -import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder; -import org.openecomp.policy.drools.protocol.configuration.ControllerConfiguration; -import org.openecomp.policy.drools.protocol.configuration.PdpdConfiguration; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -/** - * Policy Engine, the top abstraction for the Drools PDP Policy Engine. - * It abstracts away a Drools PDP Engine from management purposes. - * This is the best place to looking at the code from a top down approach. - * Other managed entities can be obtained from the PolicyEngine, hierarchically. - *
- * PolicyEngine 1 --- * PolicyController 1 --- 1 DroolsController 1 --- 1 PolicyContainer 1 --- * PolicySession - *
- * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicReader 1 --- 1 UebTopicReader - *
- * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicReader 1 --- 1 DmaapTopicReader - *
- * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicWriter 1 --- 1 DmaapTopicWriter - *
- * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicReader 1 --- 1 RestTopicReader - *
- * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicWriter 1 --- 1 RestTopicWriter - *
- * PolicyEngine 1 --- 1 ManagementServer - */ -public interface PolicyEngine extends Startable, Lockable, TopicListener { - - /** - * Default Config Server Port - */ - public static final int CONFIG_SERVER_DEFAULT_PORT = 9696; - - /** - * Default Config Server Hostname - */ - public static final String CONFIG_SERVER_DEFAULT_HOST = "localhost"; - - /** - * Boot the engine - * - * @param cliArgs command line arguments - */ - public void boot(String cliArgs[]); - - /** - * configure the policy engine according to the given properties - * - * @param properties Policy Engine properties - * @throws IllegalArgumentException when invalid or insufficient - * properties are provided - */ - public void configure(Properties properties) throws IllegalArgumentException; - - /** - * registers a new Policy Controller with the Policy Engine - * initialized per properties. - * - * @param controller name - * @param properties properties to initialize the Policy Controller - * @throws IllegalArgumentException when invalid or insufficient - * properties are provided - * @throws IllegalStateException when the engine is in a state where - * this operation is not permitted. - * @return the newly instantiated Policy Controller - */ - public PolicyController createPolicyController(String name, Properties properties) - throws IllegalArgumentException, IllegalStateException; - - /** - * updates the Policy Engine with the given configuration - * - * @param configuration the configuration - * @return success or failure - * @throws IllegalArgumentException if invalid argument provided - * @throws IllegalStateException if the system is in an invalid state - */ - public boolean configure(PdpdConfiguration configuration) - throws IllegalArgumentException, IllegalStateException; - - /** - * updates a set of Policy Controllers with configuration information - * - * @param configuration - * @return - * @throws IllegalArgumentException - * @throws IllegalStateException - */ - public List updatePolicyControllers(List configuration) - throws IllegalArgumentException, IllegalStateException; - - /** - * updates an already existing Policy Controller with configuration information - * - * @param configuration configuration - * - * @return the updated Policy Controller - * @throws IllegalArgumentException in the configuration is invalid - * @throws IllegalStateException if the controller is in a bad state - * @throws Exception any other reason - */ - public PolicyController updatePolicyController(ControllerConfiguration configuration) - throws Exception; - - /** - * removes the Policy Controller identified by its name from the Policy Engine - * - * @param name name of the Policy Controller - * @return the removed Policy Controller - */ - public void removePolicyController(String name); - - /** - * removes a Policy Controller from the Policy Engine - * @param controller the Policy Controller to remove from the Policy Engine - */ - public void removePolicyController(PolicyController controller); - - /** - * returns a list of the available Policy Controllers - * - * @return list of Policy Controllers - */ - public List getPolicyControllers(); - - - /** - * get policy controller names - * - * @return list of controller names - */ - public List getPolicyControllerIds(); - - /** - * get unmanaged sources - * - * @return unmanaged sources - */ - public List getSources(); - - /** - * get unmanaged sinks - * - * @return unmanaged sinks - */ - public List getSinks(); - - /** - * get unmmanaged http servers list - * @return http servers - */ - public List getHttpServers(); - - /** - * get properties configuration - * - * @return properties objects - */ - public Properties getProperties(); - - /** - * get features attached to the Policy Engine - * @return list of features - */ - public List getFeatureProviders(); - - /** - * get named feature attached to the Policy Engine - * @return the feature - */ - public PolicyEngineFeatureAPI getFeatureProvider(String featureName) - throws IllegalArgumentException; - - /** - * get features attached to the Policy Engine - * @return list of features - */ - public List getFeatures(); - - /** - * Attempts the dispatching of an "event" object - * - * @param topic topic - * @param event the event object to send - * - * @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 permitted (ie. locked or stopped). - */ - public boolean deliver(String topic, Object event) - throws IllegalArgumentException, IllegalStateException; - - /** - * Attempts the dispatching of an "event" object over communication - * infrastructure "busType" - * - * @param eventBus Communication infrastructure identifier - * @param topic topic - * @param event the event object to send - * - * @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 permitted (ie. locked or stopped). - * @throws UnsupportedOperationException when the engine cannot deliver due - * to the functionality missing (ie. communication infrastructure - * not supported. - */ - public boolean deliver(String busType, String topic, Object event) - throws IllegalArgumentException, IllegalStateException, - UnsupportedOperationException; - - /** - * Attempts the dispatching of an "event" object over communication - * infrastructure "busType" - * - * @param eventBus Communication infrastructure enum - * @param topic topic - * @param event the event object to send - * - * @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 permitted (ie. locked or stopped). - * @throws UnsupportedOperationException when the engine cannot deliver due - * to the functionality missing (ie. communication infrastructure - * not supported. - */ - public boolean deliver(CommInfrastructure busType, String topic, Object event) - throws IllegalArgumentException, IllegalStateException, - UnsupportedOperationException; - - /** - * Attempts delivering of an String over communication - * infrastructure "busType" - * - * @param eventBus Communication infrastructure identifier - * @param topic topic - * @param event the event object to send - * - * @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 permitted (ie. locked or stopped). - * @throws UnsupportedOperationException when the engine cannot deliver due - * to the functionality missing (ie. communication infrastructure - * not supported. - */ - public boolean deliver(CommInfrastructure busType, String topic, - String event) - throws IllegalArgumentException, IllegalStateException, - UnsupportedOperationException; - - /** - * Invoked when the host goes into the active state. - */ - public void activate(); - - /** - * Invoked when the host goes into the standby state. - */ - public void deactivate(); - - /** - * Policy Engine Manager - */ - public final static PolicyEngine manager = new PolicyEngineManager(); -} - -/** - * Policy Engine Manager Implementation - */ -class PolicyEngineManager implements PolicyEngine { - /** - * logger - */ - private static Logger logger = LoggerFactory.getLogger(PolicyEngineManager.class); - - /** - * Is the Policy Engine running? - */ - protected boolean alive = false; - - /** - * Is the engine locked? - */ - protected boolean locked = false; - - /** - * Properties used to initialize the engine - */ - protected Properties properties; - - /** - * Policy Engine Sources - */ - protected List sources = new ArrayList<>(); - - /** - * Policy Engine Sinks - */ - protected List sinks = new ArrayList<>(); - - /** - * Policy Engine HTTP Servers - */ - protected List httpServers = new ArrayList(); - - /** - * gson parser to decode configuration requests - */ - protected Gson decoder = new GsonBuilder().disableHtmlEscaping().create(); - - - /** - * {@inheritDoc} - */ - @Override - public synchronized void boot(String cliArgs[]) { - - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.beforeBoot(this, cliArgs)) - return; - } catch (Exception e) { - logger.error("{}: feature {} before-boot failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - try { - PolicyContainer.globalInit(cliArgs); - } catch (Exception e) { - logger.error("{}: cannot init policy-container because of {}", this, e.getMessage(), e); - } - - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.afterBoot(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} after-boot failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized void configure(Properties properties) throws IllegalArgumentException { - - if (properties == null) { - logger.warn("No properties provided"); - throw new IllegalArgumentException("No properties provided"); - } - - /* policy-engine dispatch pre configure hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.beforeConfigure(this, properties)) - return; - } catch (Exception e) { - logger.error("{}: feature {} before-configure failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - this.properties = properties; - - try { - this.sources = TopicEndpoint.manager.addTopicSources(properties); - for (TopicSource source: this.sources) { - source.register(this); - } - } catch (Exception e) { - logger.error("{}: add-sources failed", this, e); - } - - try { - this.sinks = TopicEndpoint.manager.addTopicSinks(properties); - } catch (IllegalArgumentException e) { - logger.error("{}: add-sinks failed", this, e); - } - - try { - this.httpServers = HttpServletServer.factory.build(properties); - } catch (IllegalArgumentException e) { - logger.error("{}: add-http-servers failed", this, e); - } - - /* policy-engine dispatch post configure hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.afterConfigure(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} after-configure failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - return; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized PolicyController createPolicyController(String name, Properties properties) - throws IllegalArgumentException, IllegalStateException { - - // check if a PROPERTY_CONTROLLER_NAME property is present - // if so, override the given name - - String propertyControllerName = properties.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME); - if (propertyControllerName != null && !propertyControllerName.isEmpty()) { - if (!propertyControllerName.equals(name)) { - throw new IllegalStateException("Proposed name (" + name + - ") and properties name (" + propertyControllerName + - ") don't match"); - } - name = propertyControllerName; - } - - PolicyController controller; - for (PolicyControllerFeatureAPI controllerFeature : PolicyControllerFeatureAPI.providers.getList()) { - try { - controller = controllerFeature.beforeCreate(name, properties); - if (controller != null) - return controller; - } catch (Exception e) { - logger.error("{}: feature {} before-controller-create failure because of {}", - this, controllerFeature.getClass().getName(), e.getMessage(), e); - } - } - - controller = PolicyController.factory.build(name, properties); - if (this.isLocked()) - controller.lock(); - - // feature hook - for (PolicyControllerFeatureAPI controllerFeature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (controllerFeature.afterCreate(controller)) - return controller; - } catch (Exception e) { - logger.error("{}: feature {} after-controller-create failure because of {}", - this, controllerFeature.getClass().getName(), e.getMessage(), e); - } - } - - return controller; - } - - - /** - * {@inheritDoc} - */ - @Override - public boolean configure(PdpdConfiguration config) throws IllegalArgumentException, IllegalStateException { - - if (config == null) - throw new IllegalArgumentException("No configuration provided"); - - String entity = config.getEntity(); - - switch (entity) { - case PdpdConfiguration.CONFIG_ENTITY_CONTROLLER: - /* only this one supported for now */ - List configControllers = config.getControllers(); - if (configControllers == null || configControllers.isEmpty()) { - if (logger.isInfoEnabled()) - logger.info("No controller configuration provided: " + config); - return false; - } - List policyControllers = this.updatePolicyControllers(config.getControllers()); - if (policyControllers == null || policyControllers.isEmpty()) - return false; - else if (policyControllers.size() == configControllers.size()) - return true; - - return false; - default: - String msg = "Configuration Entity is not supported: " + entity; - logger.warn(msg); - throw new IllegalArgumentException(msg); - } - } - - /** - * {@inheritDoc} - */ - @Override - public List updatePolicyControllers(List configControllers) - throws IllegalArgumentException, IllegalStateException { - - List policyControllers = new ArrayList(); - if (configControllers == null || configControllers.isEmpty()) { - if (logger.isInfoEnabled()) - logger.info("No controller configuration provided: " + configControllers); - return policyControllers; - } - - for (ControllerConfiguration configController: configControllers) { - try { - PolicyController policyController = this.updatePolicyController(configController); - policyControllers.add(policyController); - } catch (Exception e) { - logger.error("{}: cannot update-policy-controllers because of {}", this, e.getMessage(), e); - } - } - - return policyControllers; - } - - /** - * {@inheritDoc} - */ - @Override - public PolicyController updatePolicyController(ControllerConfiguration configController) - throws Exception { - - if (configController == null) - throw new IllegalArgumentException("No controller configuration has been provided"); - - String controllerName = configController.getName(); - if (controllerName == null || controllerName.isEmpty()) { - logger.warn("controller-name must be provided"); - throw new IllegalArgumentException("No controller configuration has been provided"); - } - - PolicyController policyController = null; - try { - String operation = configController.getOperation(); - if (operation == null || operation.isEmpty()) { - logger.warn("operation must be provided"); - throw new IllegalArgumentException("operation must be provided"); - } - - try { - policyController = PolicyController.factory.get(controllerName); - } catch (IllegalArgumentException e) { - // not found - logger.warn("Policy Controller " + controllerName + " not found"); - } - - if (policyController == null) { - - if (operation.equalsIgnoreCase(ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_LOCK) || - operation.equalsIgnoreCase(ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UNLOCK)) { - throw new IllegalArgumentException(controllerName + " is not available for operation " + operation); - } - - /* Recovery case */ - - logger.warn("controller " + controllerName + " does not exist. " + - "Attempting recovery from disk"); - - Properties properties = - SystemPersistence.manager.getControllerProperties(controllerName); - - /* - * returned properties cannot be null (per implementation) - * assert (properties != null) - */ - - if (properties == null) { - throw new IllegalArgumentException(controllerName + " is invalid"); - } - - logger.warn("controller " + controllerName + " being recovered. " + - "Reset controller's bad maven coordinates to brainless"); - - /* - * try to bring up bad controller in brainless mode, - * after having it working, apply the new create/update operation. - */ - properties.setProperty(PolicyProperties.RULES_GROUPID, DroolsController.NO_GROUP_ID); - properties.setProperty(PolicyProperties.RULES_ARTIFACTID, DroolsController.NO_ARTIFACT_ID); - properties.setProperty(PolicyProperties.RULES_VERSION, DroolsController.NO_VERSION); - - policyController = PolicyEngine.manager.createPolicyController(controllerName, properties); - - /* fall through to do brain update operation*/ - } - - switch (operation) { - case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_CREATE: - PolicyController.factory.patch(policyController, configController.getDrools()); - break; - case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UPDATE: - policyController.unlock(); - PolicyController.factory.patch(policyController, configController.getDrools()); - break; - case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_LOCK: - policyController.lock(); - break; - case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UNLOCK: - policyController.unlock(); - break; - default: - String msg = "Controller Operation Configuration is not supported: " + - operation + " for " + controllerName; - logger.warn(msg); - throw new IllegalArgumentException(msg); - } - - return policyController; - } catch (Exception e) { - logger.error("{}: cannot update-policy-controller because of {}", this, e.getMessage(), e); - throw e; - } catch (LinkageError e) { - logger.error("{}: cannot update-policy-controllers (rules) because of {}", this, e.getMessage(), e); - throw new IllegalStateException(e); - } - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized boolean start() throws IllegalStateException { - - /* policy-engine dispatch pre start hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.beforeStart(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} before-start failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - boolean success = true; - if (this.locked) - throw new IllegalStateException("Engine is locked"); - - this.alive = true; - - /* Start Policy Engine exclusively-owned (unmanaged) http servers */ - - for (HttpServletServer httpServer: this.httpServers) { - try { - if (!httpServer.waitedStart(5 * 1000L)) - success = false; - } catch (Exception e) { - logger.error("{}: cannot start http-server {} because of {}", this, - httpServer, e.getMessage(), e); - } - } - - /* Start Policy Engine exclusively-owned (unmanaged) sources */ - - for (TopicSource source: this.sources) { - try { - if (!source.start()) - success = false; - } catch (Exception e) { - logger.error("{}: cannot start topic-source {} because of {}", this, - source, e.getMessage(), e); - } - } - - /* Start Policy Engine owned (unmanaged) sinks */ - - for (TopicSink sink: this.sinks) { - try { - if (!sink.start()) - success = false; - } catch (Exception e) { - logger.error("{}: cannot start topic-sink {} because of {}", this, - sink, e.getMessage(), e); - } - } - - /* Start Policy Controllers */ - - List controllers = PolicyController.factory.inventory(); - for (PolicyController controller : controllers) { - try { - if (!controller.start()) - success = false; - } catch (Exception e) { - logger.error("{}: cannot start policy-controller {} because of {}", this, - controller, e.getMessage(), e); - success = false; - } - } - - /* Start managed Topic Endpoints */ - - try { - if (!TopicEndpoint.manager.start()) - success = false; - } catch (IllegalStateException e) { - logger.warn("{}: Topic Endpoint Manager is in an invalid state because of {}", this, e.getMessage(), e); - } - - - // Start the JMX listener - - PdpJmxListener.start(); - - /* policy-engine dispatch after start hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.afterStart(this)) - return success; - } catch (Exception e) { - logger.error("{}: feature {} after-start failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - return success; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized boolean stop() { - - /* policy-engine dispatch pre stop hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.beforeStop(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} before-stop failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - /* stop regardless of the lock state */ - - boolean success = true; - if (!this.alive) - return true; - - this.alive = false; - - List controllers = PolicyController.factory.inventory(); - for (PolicyController controller : controllers) { - try { - if (!controller.stop()) - success = false; - } catch (Exception e) { - logger.error("{}: cannot stop policy-controller {} because of {}", this, - controller, e.getMessage(), e); - success = false; - } - } - - /* Stop Policy Engine owned (unmanaged) sources */ - for (TopicSource source: this.sources) { - try { - if (!source.stop()) - success = false; - } catch (Exception e) { - logger.error("{}: cannot start topic-source {} because of {}", this, - source, e.getMessage(), e); - } - } - - /* Stop Policy Engine owned (unmanaged) sinks */ - for (TopicSink sink: this.sinks) { - try { - if (!sink.stop()) - success = false; - } catch (Exception e) { - logger.error("{}: cannot start topic-sink {} because of {}", this, - sink, e.getMessage(), e); - } - } - - /* stop all managed topics sources and sinks */ - if (!TopicEndpoint.manager.stop()) - success = false; - - /* stop all unmanaged http servers */ - for (HttpServletServer httpServer: this.httpServers) { - try { - if (!httpServer.stop()) - success = false; - } catch (Exception e) { - logger.error("{}: cannot start http-server {} because of {}", this, - httpServer, e.getMessage(), e); - } - } - - /* policy-engine dispatch pre stop hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.afterStop(this)) - return success; - } catch (Exception e) { - logger.error("{}: feature {} after-stop failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - return success; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized void shutdown() throws IllegalStateException { - - /* policy-engine dispatch pre shutdown hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.beforeShutdown(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} before-shutdown failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - this.alive = false; - - /* Shutdown Policy Engine owned (unmanaged) sources */ - for (TopicSource source: this.sources) { - try { - source.shutdown(); - } catch (Exception e) { - logger.error("{}: cannot shutdown topic-source {} because of {}", this, - source, e.getMessage(), e); - } - } - - /* Shutdown Policy Engine owned (unmanaged) sinks */ - for (TopicSink sink: this.sinks) { - try { - sink.shutdown(); - } catch (Exception e) { - logger.error("{}: cannot shutdown topic-sink {} because of {}", this, - sink, e.getMessage(), e); - } - } - - /* Shutdown managed resources */ - PolicyController.factory.shutdown(); - TopicEndpoint.manager.shutdown(); - HttpServletServer.factory.destroy(); - - // Stop the JMX listener - - PdpJmxListener.stop(); - - /* policy-engine dispatch post shutdown hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.afterShutdown(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} after-shutdown failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - - new Thread(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(5000L); - } catch (InterruptedException e) { - logger.warn("{}: interrupted-exception while shutting down management server: ", this); - } - - /* shutdown all unmanaged http servers */ - for (HttpServletServer httpServer: getHttpServers()) { - try { - httpServer.shutdown(); - } catch (Exception e) { - logger.error("{}: cannot shutdown http-server {} because of {}", this, - httpServer, e.getMessage(), e); - } - } - - try { - Thread.sleep(5000L); - } catch (InterruptedException e) { - logger.warn("{}: interrupted-exception while shutting down management server: ", this); - } - - System.exit(0); - } - }).start(); - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized boolean isAlive() { - return this.alive; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized boolean lock() { - - /* policy-engine dispatch pre lock hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.beforeLock(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} before-lock failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - if (this.locked) - return true; - - this.locked = true; - - boolean success = true; - List controllers = PolicyController.factory.inventory(); - for (PolicyController controller : controllers) { - try { - success = controller.lock() && success; - } catch (Exception e) { - logger.error("{}: cannot lock policy-controller {} because of {}", this, - controller, e.getMessage(), e); - success = false; - } - } - - success = TopicEndpoint.manager.lock() && success; - - /* policy-engine dispatch post lock hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.afterLock(this)) - return success; - } catch (Exception e) { - logger.error("{}: feature {} after-lock failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - return success; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized boolean unlock() { - - /* policy-engine dispatch pre unlock hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.beforeUnlock(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} before-unlock failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - if (!this.locked) - return true; - - this.locked = false; - - boolean success = true; - List controllers = PolicyController.factory.inventory(); - for (PolicyController controller : controllers) { - try { - success = controller.unlock() && success; - } catch (Exception e) { - logger.error("{}: cannot unlock policy-controller {} because of {}", this, - controller, e.getMessage(), e); - success = false; - } - } - - success = TopicEndpoint.manager.unlock() && success; - - /* policy-engine dispatch after unlock hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.afterUnlock(this)) - return success; - } catch (Exception e) { - logger.error("{}: feature {} after-unlock failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - return success; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized boolean isLocked() { - return this.locked; - } - - /** - * {@inheritDoc} - */ - @Override - public void removePolicyController(String name) { - PolicyController.factory.destroy(name); - } - - /** - * {@inheritDoc} - */ - @Override - public void removePolicyController(PolicyController controller) { - PolicyController.factory.destroy(controller); - } - - /** - * {@inheritDoc} - */ - @JsonIgnore - @Override - public List getPolicyControllers() { - return PolicyController.factory.inventory(); - } - - /** - * {@inheritDoc} - */ - @JsonProperty("controllers") - @Override - public List getPolicyControllerIds() { - List controllerNames = new ArrayList(); - for (PolicyController controller: PolicyController.factory.inventory()) { - controllerNames.add(controller.getName()); - } - return controllerNames; - } - - /** - * {@inheritDoc} - */ - @Override - @JsonIgnore - public Properties getProperties() { - return this.properties; - } - - - /** - * {@inheritDoc} - */ - @SuppressWarnings("unchecked") - @Override - public List getSources() { - return (List) this.sources; - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings("unchecked") - @Override - public List getSinks() { - return (List) this.sinks; - } - - /** - * {@inheritDoc} - */ - @Override - public List getHttpServers() { - return this.httpServers; - } - - - /** - * {@inheritDoc} - */ - @Override - public List getFeatures() { - List features = new ArrayList(); - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - features.add(feature.getName()); - } - return features; - } - - /** - * {@inheritDoc} - */ - @JsonIgnore - @Override - public List getFeatureProviders() { - return PolicyEngineFeatureAPI.providers.getList(); - } - - /** - * {@inheritDoc} - */ - @Override - public PolicyEngineFeatureAPI getFeatureProvider(String featureName) throws IllegalArgumentException { - if (featureName == null || featureName.isEmpty()) - throw new IllegalArgumentException("A feature name must be provided"); - - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - if (feature.getName().equals(featureName)) - return feature; - } - - throw new IllegalArgumentException("Invalid Feature Name: " + featureName); - } - - /** - * {@inheritDoc} - */ - @Override - public void onTopicEvent(CommInfrastructure commType, String topic, String event) { - /* configuration request */ - try { - PdpdConfiguration configuration = this.decoder.fromJson(event, PdpdConfiguration.class); - this.configure(configuration); - } catch (Exception e) { - logger.error("{}: configuration-error due to {} because of {}", - this, event, e.getMessage(), e); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean deliver(String topic, Object event) - throws IllegalArgumentException, IllegalStateException { - - /* - * Note this entry point is usually from the DRL - */ - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Invalid Topic"); - - if (event == null) - throw new IllegalArgumentException("Invalid Event"); - - if (!this.isAlive()) - throw new IllegalStateException("Policy Engine is stopped"); - - if (this.isLocked()) - throw new IllegalStateException("Policy Engine is locked"); - - List sinks = - TopicEndpoint.manager.getTopicSinks(topic); - if (sinks == null || sinks.isEmpty() || sinks.size() > 1) - throw new IllegalStateException - ("Cannot ensure correct delivery on topic " + topic + ": " + sinks); - - return this.deliver(sinks.get(0).getTopicCommInfrastructure(), - topic, event); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean deliver(String busType, String topic, Object event) - throws IllegalArgumentException, IllegalStateException, - UnsupportedOperationException { - - /* - * Note this entry point is usually from the DRL (one of the reasons - * busType is String. - */ - - if (busType == null || busType.isEmpty()) - throw new IllegalArgumentException - ("Invalid Communication Infrastructure"); - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Invalid Topic"); - - if (event == null) - throw new IllegalArgumentException("Invalid Event"); - - boolean valid = false; - for (Topic.CommInfrastructure comm: Topic.CommInfrastructure.values()) { - if (comm.name().equals(busType)) { - valid = true; - } - } - - if (!valid) - throw new IllegalArgumentException - ("Invalid Communication Infrastructure: " + busType); - - - if (!this.isAlive()) - throw new IllegalStateException("Policy Engine is stopped"); - - if (this.isLocked()) - throw new IllegalStateException("Policy Engine is locked"); - - - return this.deliver(Topic.CommInfrastructure.valueOf(busType), - topic, event); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean deliver(Topic.CommInfrastructure busType, - String topic, Object event) - throws IllegalArgumentException, IllegalStateException, - UnsupportedOperationException { - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Invalid Topic"); - - if (event == null) - throw new IllegalArgumentException("Invalid Event"); - - if (!this.isAlive()) - throw new IllegalStateException("Policy Engine is stopped"); - - if (this.isLocked()) - throw new IllegalStateException("Policy Engine is locked"); - - /* Try to send through the controller, this is the - * preferred way, since it may want to apply additional - * processing - */ - try { - DroolsController droolsController = - EventProtocolCoder.manager.getDroolsController(topic, event); - PolicyController controller = PolicyController.factory.get(droolsController); - if (controller != null) - return controller.deliver(busType, topic, event); - } catch (Exception e) { - logger.warn("{}: cannot find policy-controller to deliver {} over {}:{} because of {}", - this, event, busType, topic, e.getMessage(), e); - - /* continue (try without routing through the controller) */ - } - - /* - * cannot route through the controller, send directly through - * the topic sink - */ - try { - String json = EventProtocolCoder.manager.encode(topic, event); - return this.deliver(busType, topic, json); - - } catch (Exception e) { - logger.warn("{}: cannot deliver {} over {}:{} because of {}", - this, event, busType, topic, e.getMessage(), e); - throw e; - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean deliver(Topic.CommInfrastructure busType, - String topic, String event) - throws IllegalArgumentException, IllegalStateException, - UnsupportedOperationException { - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Invalid Topic"); - - if (event == null || event.isEmpty()) - throw new IllegalArgumentException("Invalid Event"); - - if (!this.isAlive()) - throw new IllegalStateException("Policy Engine is stopped"); - - if (this.isLocked()) - throw new IllegalStateException("Policy Engine is locked"); - - try { - TopicSink sink = - TopicEndpoint.manager.getTopicSink - (busType, topic); - - if (sink == null) - throw new IllegalStateException("Inconsistent State: " + this); - - return sink.send(event); - - } catch (Exception e) { - logger.warn("{}: cannot deliver {} over {}:{} because of {}", - this, event, busType, topic, e.getMessage(), e); - throw e; - } - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized void activate() { - - /* policy-engine dispatch pre activate hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.beforeActivate(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} before-activate failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - // activate 'policy-management' - for (PolicyController policyController : getPolicyControllers()) { - try { - policyController.unlock(); - policyController.start(); - } catch (Exception e) { - logger.error("{}: cannot activate of policy-controller {} because of {}", - this, policyController,e.getMessage(), e); - } catch (LinkageError e) { - logger.error("{}: cannot activate (rules compilation) of policy-controller {} because of {}", - this, policyController,e.getMessage(), e); - } - } - - this.unlock(); - - /* policy-engine dispatch post activate hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.afterActivate(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} after-activate failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized void deactivate() { - - /* policy-engine dispatch pre deactivate hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.beforeDeactivate(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} before-deactivate failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - this.lock(); - - for (PolicyController policyController : getPolicyControllers()) { - try { - policyController.stop(); - } catch (Exception e) { - logger.error("{}: cannot deactivate (stop) policy-controller {} because of {}", - this, policyController, e.getMessage(), e); - } catch (LinkageError e) { - logger.error("{}: cannot deactivate (stop) policy-controller {} because of {}", - this, policyController, e.getMessage(), e); - } - } - - /* policy-engine dispatch post deactivate hook */ - for (PolicyEngineFeatureAPI feature : PolicyEngineFeatureAPI.providers.getList()) { - try { - if (feature.afterDeactivate(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} after-deactivate failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("PolicyEngineManager [alive=").append(alive).append(", locked=").append(locked).append("]"); - return builder.toString(); - } - -} - - diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/internal/AggregatedPolicyController.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/internal/AggregatedPolicyController.java deleted file mode 100644 index f0491624..00000000 --- a/policy-management/src/main/java/org/openecomp/policy/drools/system/internal/AggregatedPolicyController.java +++ /dev/null @@ -1,626 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.system.internal; - -import java.util.HashMap; -import java.util.List; -import java.util.Properties; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.openecomp.policy.drools.controller.DroolsController; -import org.openecomp.policy.drools.event.comm.Topic; -import org.openecomp.policy.drools.event.comm.TopicEndpoint; -import org.openecomp.policy.drools.event.comm.TopicListener; -import org.openecomp.policy.drools.event.comm.TopicSink; -import org.openecomp.policy.drools.event.comm.TopicSource; -import org.openecomp.policy.drools.features.PolicyControllerFeatureAPI; -import org.openecomp.policy.drools.persistence.SystemPersistence; -import org.openecomp.policy.drools.properties.PolicyProperties; -import org.openecomp.policy.drools.protocol.configuration.DroolsConfiguration; -import org.openecomp.policy.drools.system.PolicyController; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -/** - * This implementation of the Policy Controller merely aggregates and tracks for - * management purposes all underlying resources that this controller depends upon. - */ -public class AggregatedPolicyController implements PolicyController, - TopicListener { - - /** - * Logger - */ - private static Logger logger = LoggerFactory.getLogger(AggregatedPolicyController.class); - - /** - * identifier for this policy controller - */ - protected final String name; - - /** - * Abstracted Event Sources List regardless communication - * technology - */ - protected final List sources; - - /** - * Abstracted Event Sinks List regardless communication - * technology - */ - protected final List sinks; - - /** - * Mapping topics to sinks - */ - @JsonIgnore - protected final HashMap topic2Sinks = - new HashMap(); - - /** - * Is this Policy Controller running (alive) ? - * reflects invocation of start()/stop() only - */ - protected volatile boolean alive; - - /** - * Is this Policy Controller locked ? - * reflects if i/o controller related operations and start - * are permitted, - * more specifically: start(), deliver() and onTopicEvent(). - * It does not affect the ability to stop the - * underlying drools infrastructure - */ - protected volatile boolean locked; - - /** - * Policy Drools Controller - */ - protected volatile DroolsController droolsController; - - /** - * Properties used to initialize controller - */ - protected final Properties properties; - - /** - * Constructor version mainly used for bootstrapping at initialization time - * a policy engine controller - * - * @param name controller name - * @param properties - * - * @throws IllegalArgumentException when invalid arguments are provided - */ - public AggregatedPolicyController(String name, Properties properties) - throws IllegalArgumentException { - - this.name = name; - - /* - * 1. Register read topics with network infrastructure (ueb, dmaap, rest) - * 2. Register write topics with network infrastructure (ueb, dmaap, rest) - * 3. Register with drools infrastructure - */ - - // Create/Reuse Readers/Writers for all event sources endpoints - - this.sources = TopicEndpoint.manager.addTopicSources(properties); - this.sinks = TopicEndpoint.manager.addTopicSinks(properties); - - initDrools(properties); - initSinks(); - - /* persist new properties */ - SystemPersistence.manager.storeController(name, properties); - this.properties = properties; - } - - /** - * initialize drools layer - * @throws IllegalArgumentException if invalid parameters are passed in - */ - protected void initDrools(Properties properties) throws IllegalArgumentException { - try { - // Register with drools infrastructure - this.droolsController = DroolsController.factory.build(properties, sources, sinks); - } catch (Exception | LinkageError e) { - logger.error("{}: cannot init-drools because of {}", this, e.getMessage(), e); - throw new IllegalArgumentException(e); - } - } - - /** - * initialize sinks - * @throws IllegalArgumentException if invalid parameters are passed in - */ - protected void initSinks() throws IllegalArgumentException { - this.topic2Sinks.clear(); - for (TopicSink sink: sinks) { - this.topic2Sinks.put(sink.getTopic(), sink); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean updateDrools(DroolsConfiguration newDroolsConfiguration) { - - DroolsConfiguration oldDroolsConfiguration = - new DroolsConfiguration(this.droolsController.getArtifactId(), - this.droolsController.getGroupId(), - this.droolsController.getVersion()); - - if (oldDroolsConfiguration.getGroupId().equalsIgnoreCase(newDroolsConfiguration.getGroupId()) && - oldDroolsConfiguration.getArtifactId().equalsIgnoreCase(newDroolsConfiguration.getArtifactId()) && - oldDroolsConfiguration.getVersion().equalsIgnoreCase(newDroolsConfiguration.getVersion())) { - logger.warn("{}: cannot update-drools: identical configuration {} vs {}", - this, oldDroolsConfiguration, newDroolsConfiguration); - return true; - } - - try { - /* Drools Controller created, update initialization properties for restarts */ - - this.properties.setProperty(PolicyProperties.RULES_GROUPID, newDroolsConfiguration.getGroupId()); - this.properties.setProperty(PolicyProperties.RULES_ARTIFACTID, newDroolsConfiguration.getArtifactId()); - this.properties.setProperty(PolicyProperties.RULES_VERSION, newDroolsConfiguration.getVersion()); - - SystemPersistence.manager.storeController(name, this.properties); - - this.initDrools(this.properties); - - /* set drools controller to current locked status */ - - if (this.isLocked()) - this.droolsController.lock(); - else - this.droolsController.unlock(); - - /* set drools controller to current alive status */ - - if (this.isAlive()) - this.droolsController.start(); - else - this.droolsController.stop(); - - } catch (IllegalArgumentException e) { - logger.error("{}: cannot update-drools because of {}", this, e.getMessage(), e); - return false; - } - - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public String getName() { - return this.name; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean start() throws IllegalStateException { - logger.info("{}: start", this); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.beforeStart(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} before-start failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - if (this.isLocked()) - throw new IllegalStateException("Policy Controller " + name + " is locked"); - - synchronized(this) { - if (this.alive) - return true; - - this.alive = true; - } - - boolean success = this.droolsController.start(); - - // register for events - - for (TopicSource source: sources) { - source.register(this); - } - - for (TopicSink sink: sinks) { - try { - sink.start(); - } catch (Exception e) { - logger.error("{}: cannot start {} because of {}", - this, sink, e.getMessage(), e); - } - } - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.afterStart(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} after-start failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - return success; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean stop() { - logger.info("{}: stop", this); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.beforeStop(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} before-stop failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - /* stop regardless locked state */ - - synchronized(this) { - if (!this.alive) - return true; - - this.alive = false; - } - - // 1. Stop registration - - for (TopicSource source: sources) { - source.unregister(this); - } - - boolean success = this.droolsController.stop(); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.afterStop(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} after-stop failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - return success; - } - - /** - * {@inheritDoc} - */ - @Override - public void shutdown() throws IllegalStateException { - logger.info("{}: shutdown", this); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.beforeShutdown(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} before-shutdown failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - this.stop(); - - DroolsController.factory.shutdown(this.droolsController); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.afterShutdown(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} after-shutdown failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public void halt() throws IllegalStateException { - logger.info("{}: halt", this); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.beforeHalt(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} before-halt failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - this.stop(); - DroolsController.factory.destroy(this.droolsController); - SystemPersistence.manager.deleteController(this.name); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.afterHalt(this)) - return; - } catch (Exception e) { - logger.error("{}: feature {} after-halt failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public void onTopicEvent(Topic.CommInfrastructure commType, - String topic, String event) { - - if (logger.isDebugEnabled()) - logger.debug("{}: event offered from {}:{}: {}", this, commType, topic, event); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.beforeOffer(this, commType, topic, event)) - return; - } catch (Exception e) { - logger.error("{}: feature {} before-offer failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - if (this.locked) - return; - - if (!this.alive) - return; - - boolean success = this.droolsController.offer(topic, event); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.afterOffer(this, commType, topic, event, success)) - return; - } catch (Exception e) { - logger.error("{}: feature {} after-offer failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean deliver(Topic.CommInfrastructure commType, - String topic, Object event) - throws IllegalArgumentException, IllegalStateException, - UnsupportedOperationException { - - if (logger.isDebugEnabled()) - logger.debug("{}: deliver event to {}:{}: {}", this, commType, topic, event); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.beforeDeliver(this, commType, topic, event)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} before-deliver failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - if (topic == null || topic.isEmpty()) - throw new IllegalArgumentException("Invalid Topic"); - - if (event == null) - throw new IllegalArgumentException("Invalid Event"); - - if (!this.isAlive()) - throw new IllegalStateException("Policy Engine is stopped"); - - if (this.isLocked()) - throw new IllegalStateException("Policy Engine is locked"); - - if (!this.topic2Sinks.containsKey(topic)) { - logger.warn("{}: cannot deliver event because the sink {}:{} is not registered: {}", - this, commType, topic, event); - throw new IllegalArgumentException("Unsuported topic " + topic + " for delivery"); - } - - boolean success = this.droolsController.deliver(this.topic2Sinks.get(topic), event); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.afterDeliver(this, commType, topic, event, success)) - return success; - } catch (Exception e) { - logger.error("{}: feature {} after-deliver failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - return success; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isAlive() { - return this.alive; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean lock() { - logger.info("{}: lock", this); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.beforeLock(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} before-lock failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - synchronized(this) { - if (this.locked) - return true; - - this.locked = true; - } - - // it does not affect associated sources/sinks, they are - // autonomous entities - - boolean success = this.droolsController.lock(); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.afterLock(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} after-lock failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - return success; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean unlock() { - - logger.info("{}: unlock", this); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.beforeUnlock(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} before-unlock failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - synchronized(this) { - if (!this.locked) - return true; - - this.locked = false; - } - - boolean success = this.droolsController.unlock(); - - for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) { - try { - if (feature.afterUnlock(this)) - return true; - } catch (Exception e) { - logger.error("{}: feature {} after-unlock failure because of {}", - this, feature.getClass().getName(), e.getMessage(), e); - } - } - - return success; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isLocked() { - return this.locked; - } - - /** - * {@inheritDoc} - */ - @Override - public List getTopicSources() { - return this.sources; - } - - /** - * {@inheritDoc} - */ - @Override - public List getTopicSinks() { - return this.sinks; - } - - /** - * {@inheritDoc} - */ - @Override - public DroolsController getDrools() { - return this.droolsController; - } - - - /** - * {@inheritDoc} - */ - @Override - @JsonIgnore - public Properties getProperties() { - return this.properties; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("AggregatedPolicyController [name=").append(name).append(", alive=").append(alive).append(", locked=").append(locked) - .append(", droolsController=").append(droolsController).append("]"); - return builder.toString(); - } - -} - -- cgit 1.2.3-korg