2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.policy.drools.system.internal;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Properties;
27 import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
28 import org.openecomp.policy.common.logging.flexlogger.Logger;
29 import org.openecomp.policy.drools.controller.DroolsController;
30 import org.openecomp.policy.drools.event.comm.Topic;
31 import org.openecomp.policy.drools.event.comm.TopicEndpoint;
32 import org.openecomp.policy.drools.event.comm.TopicListener;
33 import org.openecomp.policy.drools.event.comm.TopicSink;
34 import org.openecomp.policy.drools.event.comm.TopicSource;
35 import org.openecomp.policy.drools.features.PolicyControllerFeatureAPI;
36 import org.openecomp.policy.drools.persistence.SystemPersistence;
37 import org.openecomp.policy.drools.properties.PolicyProperties;
38 import org.openecomp.policy.drools.protocol.configuration.DroolsConfiguration;
39 import org.openecomp.policy.drools.system.PolicyController;
41 import com.fasterxml.jackson.annotation.JsonIgnore;
44 * This implementation of the Policy Controller merely aggregates and tracks for
45 * management purposes all underlying resources that this controller depends upon.
47 public class AggregatedPolicyController implements PolicyController,
53 private static Logger logger = FlexLogger.getLogger(AggregatedPolicyController.class);
56 * identifier for this policy controller
58 protected final String name;
61 * Abstracted Event Sources List regardless communication
64 protected final List<? extends TopicSource> sources;
67 * Abstracted Event Sinks List regardless communication
70 protected final List<? extends TopicSink> sinks;
73 * Mapping topics to sinks
76 protected final HashMap<String, TopicSink> topic2Sinks =
77 new HashMap<String, TopicSink>();
80 * Is this Policy Controller running (alive) ?
81 * reflects invocation of start()/stop() only
83 protected volatile boolean alive;
86 * Is this Policy Controller locked ?
87 * reflects if i/o controller related operations and start
89 * more specifically: start(), deliver() and onTopicEvent().
90 * It does not affect the ability to stop the
91 * underlying drools infrastructure
93 protected volatile boolean locked;
96 * Policy Drools Controller
98 protected volatile DroolsController droolsController;
101 * Properties used to initialize controller
103 protected final Properties properties;
106 * Constructor version mainly used for bootstrapping at initialization time
107 * a policy engine controller
109 * @param name controller name
112 * @throws IllegalArgumentException when invalid arguments are provided
114 public AggregatedPolicyController(String name, Properties properties)
115 throws IllegalArgumentException {
120 * 1. Register read topics with network infrastructure (ueb, dmaap, rest)
121 * 2. Register write topics with network infrastructure (ueb, dmaap, rest)
122 * 3. Register with drools infrastructure
125 // Create/Reuse Readers/Writers for all event sources endpoints
127 this.sources = TopicEndpoint.manager.addTopicSources(properties);
128 this.sinks = TopicEndpoint.manager.addTopicSinks(properties);
130 initDrools(properties);
133 /* persist new properties */
134 SystemPersistence.manager.storeController(name, properties);
135 this.properties = properties;
139 * initialize drools layer
140 * @throws IllegalArgumentException if invalid parameters are passed in
142 protected void initDrools(Properties properties) throws IllegalArgumentException {
144 // Register with drools infrastructure
145 this.droolsController = DroolsController.factory.build(properties, sources, sinks);
146 } catch (Exception | LinkageError e) {
147 logger.error("BUILD-INIT-DROOLS: " + e.getMessage());
150 // throw back exception as input properties cause problems
151 throw new IllegalArgumentException(e);
157 * @throws IllegalArgumentException if invalid parameters are passed in
159 protected void initSinks() throws IllegalArgumentException {
160 this.topic2Sinks.clear();
161 for (TopicSink sink: sinks) {
162 this.topic2Sinks.put(sink.getTopic(), sink);
170 public boolean updateDrools(DroolsConfiguration newDroolsConfiguration) {
172 DroolsConfiguration oldDroolsConfiguration =
173 new DroolsConfiguration(this.droolsController.getArtifactId(),
174 this.droolsController.getGroupId(),
175 this.droolsController.getVersion());
177 if (oldDroolsConfiguration.getGroupId().equalsIgnoreCase(newDroolsConfiguration.getGroupId()) &&
178 oldDroolsConfiguration.getArtifactId().equalsIgnoreCase(newDroolsConfiguration.getArtifactId()) &&
179 oldDroolsConfiguration.getVersion().equalsIgnoreCase(newDroolsConfiguration.getVersion())) {
180 logger.warn("UPDATE-DROOLS: nothing to do: identical configuration: " + oldDroolsConfiguration +
181 " <=> " + newDroolsConfiguration);
186 /* Drools Controller created, update initialization properties for restarts */
188 this.properties.setProperty(PolicyProperties.RULES_GROUPID, newDroolsConfiguration.getGroupId());
189 this.properties.setProperty(PolicyProperties.RULES_ARTIFACTID, newDroolsConfiguration.getArtifactId());
190 this.properties.setProperty(PolicyProperties.RULES_VERSION, newDroolsConfiguration.getVersion());
192 SystemPersistence.manager.storeController(name, this.properties);
194 this.initDrools(this.properties);
196 /* set drools controller to current locked status */
199 this.droolsController.lock();
201 this.droolsController.unlock();
203 /* set drools controller to current alive status */
206 this.droolsController.start();
208 this.droolsController.stop();
210 } catch (IllegalArgumentException e) {
211 logger.warn("INIT-DROOLS: " + e.getMessage());
223 public String getName() {
231 public boolean start() throws IllegalStateException {
233 if (logger.isInfoEnabled())
234 logger.info("START: " + this);
236 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
238 if (feature.beforeStart(this))
240 } catch (Exception e) {
241 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
246 throw new IllegalStateException("Policy Controller " + name + " is locked");
255 boolean success = this.droolsController.start();
257 // register for events
259 for (TopicSource source: sources) {
260 source.register(this);
263 for (TopicSink sink: sinks) {
266 } catch (Exception e) {
267 logger.warn("can't start sink: " + sink + " because of " + e.getMessage());
272 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
274 if (feature.afterStart(this))
276 } catch (Exception e) {
277 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
288 public boolean stop() {
290 if (logger.isInfoEnabled())
291 logger.info("STOP: " + this);
293 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
295 if (feature.beforeStop(this))
297 } catch (Exception e) {
298 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
302 /* stop regardless locked state */
311 // 1. Stop registration
313 for (TopicSource source: sources) {
314 source.unregister(this);
317 boolean success = this.droolsController.stop();
319 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
321 if (feature.afterStop(this))
323 } catch (Exception e) {
324 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
335 public void shutdown() throws IllegalStateException {
336 if (logger.isInfoEnabled())
337 logger.info("SHUTDOWN: " + this);
339 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
341 if (feature.beforeShutdown(this))
343 } catch (Exception e) {
344 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
350 DroolsController.factory.shutdown(this.droolsController);
352 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
354 if (feature.afterShutdown(this))
356 } catch (Exception e) {
357 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
366 public void halt() throws IllegalStateException {
367 if (logger.isInfoEnabled())
368 logger.info("HALT: " + this);
370 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
372 if (feature.beforeHalt(this))
374 } catch (Exception e) {
375 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
380 DroolsController.factory.destroy(this.droolsController);
381 SystemPersistence.manager.deleteController(this.name);
383 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
385 if (feature.afterHalt(this))
387 } catch (Exception e) {
388 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
397 public void onTopicEvent(Topic.CommInfrastructure commType,
398 String topic, String event) {
400 if (logger.isDebugEnabled())
401 logger.debug("EVENT NOTIFICATION: " + commType + ":" + topic + ":" + event + " INTO " + this);
403 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
405 if (feature.beforeOffer(this, commType, topic, event))
407 } catch (Exception e) {
408 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
418 boolean success = this.droolsController.offer(topic, event);
420 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
422 if (feature.afterOffer(this, commType, topic, event, success))
424 } catch (Exception e) {
425 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
434 public boolean deliver(Topic.CommInfrastructure commType,
435 String topic, Object event)
436 throws IllegalArgumentException, IllegalStateException,
437 UnsupportedOperationException {
439 if (logger.isDebugEnabled())
440 logger.debug("DELIVER: " + commType + ":" + topic + ":" + event + " FROM " + this);
442 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
444 if (feature.beforeDeliver(this, commType, topic, event))
446 } catch (Exception e) {
447 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
451 if (topic == null || topic.isEmpty())
452 throw new IllegalArgumentException("Invalid Topic");
455 throw new IllegalArgumentException("Invalid Event");
458 throw new IllegalStateException("Policy Engine is stopped");
461 throw new IllegalStateException("Policy Engine is locked");
463 if (!this.topic2Sinks.containsKey(topic)) {
464 logger.error("UNDELIVERED: " + commType + ":" + topic + ":" + event + " FROM " + this);
465 throw new IllegalArgumentException
466 ("Unsuported topic " + topic + " for delivery");
469 boolean success = this.droolsController.deliver(this.topic2Sinks.get(topic), event);
471 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
473 if (feature.afterDeliver(this, commType, topic, event, success))
475 } catch (Exception e) {
476 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
487 public boolean isAlive() {
495 public boolean lock() {
496 if (logger.isInfoEnabled())
497 logger.info("LOCK: " + this);
499 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
501 if (feature.beforeLock(this))
503 } catch (Exception e) {
504 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
515 // it does not affect associated sources/sinks, they are
516 // autonomous entities
518 boolean success = this.droolsController.lock();
520 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
522 if (feature.afterLock(this))
524 } catch (Exception e) {
525 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
536 public boolean unlock() {
538 if (logger.isInfoEnabled())
539 logger.info("UNLOCK: " + this);
541 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
543 if (feature.beforeUnlock(this))
545 } catch (Exception e) {
546 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
557 boolean success = this.droolsController.unlock();
559 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
561 if (feature.afterUnlock(this))
563 } catch (Exception e) {
564 logger.warn("ERROR: Feature API: " + feature.getClass().getName() + e.getMessage(), e);
575 public boolean isLocked() {
583 public List<? extends TopicSource> getTopicSources() {
591 public List<? extends TopicSink> getTopicSinks() {
599 public DroolsController getDrools() {
600 return this.droolsController;
609 public Properties getProperties() {
610 return this.properties;
614 public String toString() {
615 StringBuilder builder = new StringBuilder();
616 builder.append("AggregatedPolicyController [name=").append(name).append(", alive=").append(alive).append(", locked=").append(locked)
617 .append(", droolsController=").append(droolsController).append("]");
618 return builder.toString();