2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 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.onap.policy.drools.system.internal;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Properties;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.onap.policy.drools.controller.DroolsController;
30 import org.onap.policy.drools.event.comm.Topic;
31 import org.onap.policy.drools.event.comm.TopicEndpoint;
32 import org.onap.policy.drools.event.comm.TopicListener;
33 import org.onap.policy.drools.event.comm.TopicSink;
34 import org.onap.policy.drools.event.comm.TopicSource;
35 import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
36 import org.onap.policy.drools.persistence.SystemPersistence;
37 import org.onap.policy.drools.properties.PolicyProperties;
38 import org.onap.policy.drools.protocol.configuration.DroolsConfiguration;
39 import org.onap.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 = LoggerFactory.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 =
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) {
119 * 1. Register read topics with network infrastructure (ueb, dmaap, rest)
120 * 2. Register write topics with network infrastructure (ueb, dmaap, rest)
121 * 3. Register with drools infrastructure
124 // Create/Reuse Readers/Writers for all event sources endpoints
126 this.sources = TopicEndpoint.manager.addTopicSources(properties);
127 this.sinks = TopicEndpoint.manager.addTopicSinks(properties);
129 initDrools(properties);
132 /* persist new properties */
133 SystemPersistence.manager.storeController(name, properties);
134 this.properties = properties;
138 * initialize drools layer
139 * @throws IllegalArgumentException if invalid parameters are passed in
141 protected void initDrools(Properties properties) {
143 // Register with drools infrastructure
144 this.droolsController = DroolsController.factory.build(properties, sources, sinks);
145 } catch (Exception | LinkageError e) {
146 logger.error("{}: cannot init-drools because of {}", this, e.getMessage(), e);
147 throw new IllegalArgumentException(e);
153 * @throws IllegalArgumentException if invalid parameters are passed in
155 protected void initSinks() {
156 this.topic2Sinks.clear();
157 for (TopicSink sink: sinks) {
158 this.topic2Sinks.put(sink.getTopic(), sink);
166 public boolean updateDrools(DroolsConfiguration newDroolsConfiguration) {
168 DroolsConfiguration oldDroolsConfiguration =
169 new DroolsConfiguration(this.droolsController.getArtifactId(),
170 this.droolsController.getGroupId(),
171 this.droolsController.getVersion());
173 if (oldDroolsConfiguration.getGroupId().equalsIgnoreCase(newDroolsConfiguration.getGroupId()) &&
174 oldDroolsConfiguration.getArtifactId().equalsIgnoreCase(newDroolsConfiguration.getArtifactId()) &&
175 oldDroolsConfiguration.getVersion().equalsIgnoreCase(newDroolsConfiguration.getVersion())) {
176 logger.warn("{}: cannot update-drools: identical configuration {} vs {}",
177 this, oldDroolsConfiguration, newDroolsConfiguration);
182 /* Drools Controller created, update initialization properties for restarts */
184 this.properties.setProperty(PolicyProperties.RULES_GROUPID, newDroolsConfiguration.getGroupId());
185 this.properties.setProperty(PolicyProperties.RULES_ARTIFACTID, newDroolsConfiguration.getArtifactId());
186 this.properties.setProperty(PolicyProperties.RULES_VERSION, newDroolsConfiguration.getVersion());
188 SystemPersistence.manager.storeController(name, this.properties);
190 this.initDrools(this.properties);
192 /* set drools controller to current locked status */
195 this.droolsController.lock();
197 this.droolsController.unlock();
199 /* set drools controller to current alive status */
202 this.droolsController.start();
204 this.droolsController.stop();
206 } catch (IllegalArgumentException e) {
207 logger.error("{}: cannot update-drools because of {}", this, e.getMessage(), e);
218 public String getName() {
226 public boolean start() {
227 logger.info("{}: start", this);
229 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
231 if (feature.beforeStart(this))
233 } catch (Exception e) {
234 logger.error("{}: feature {} before-start failure because of {}",
235 this, feature.getClass().getName(), e.getMessage(), e);
240 throw new IllegalStateException("Policy Controller " + name + " is locked");
249 boolean success = this.droolsController.start();
251 // register for events
253 for (TopicSource source: sources) {
254 source.register(this);
257 for (TopicSink sink: sinks) {
260 } catch (Exception e) {
261 logger.error("{}: cannot start {} because of {}",
262 this, sink, e.getMessage(), e);
266 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
268 if (feature.afterStart(this))
270 } catch (Exception e) {
271 logger.error("{}: feature {} after-start failure because of {}",
272 this, feature.getClass().getName(), e.getMessage(), e);
283 public boolean stop() {
284 logger.info("{}: stop", this);
286 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
288 if (feature.beforeStop(this))
290 } catch (Exception e) {
291 logger.error("{}: feature {} before-stop failure because of {}",
292 this, feature.getClass().getName(), e.getMessage(), e);
296 /* stop regardless locked state */
305 // 1. Stop registration
307 for (TopicSource source: sources) {
308 source.unregister(this);
311 boolean success = this.droolsController.stop();
313 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
315 if (feature.afterStop(this))
317 } catch (Exception e) {
318 logger.error("{}: feature {} after-stop failure because of {}",
319 this, feature.getClass().getName(), e.getMessage(), e);
330 public void shutdown() {
331 logger.info("{}: shutdown", this);
333 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
335 if (feature.beforeShutdown(this))
337 } catch (Exception e) {
338 logger.error("{}: feature {} before-shutdown failure because of {}",
339 this, feature.getClass().getName(), e.getMessage(), e);
345 DroolsController.factory.shutdown(this.droolsController);
347 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
349 if (feature.afterShutdown(this))
351 } catch (Exception e) {
352 logger.error("{}: feature {} after-shutdown failure because of {}",
353 this, feature.getClass().getName(), e.getMessage(), e);
363 logger.info("{}: halt", this);
365 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
367 if (feature.beforeHalt(this))
369 } catch (Exception e) {
370 logger.error("{}: feature {} before-halt failure because of {}",
371 this, feature.getClass().getName(), e.getMessage(), e);
376 DroolsController.factory.destroy(this.droolsController);
377 SystemPersistence.manager.deleteController(this.name);
379 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
381 if (feature.afterHalt(this))
383 } catch (Exception e) {
384 logger.error("{}: feature {} after-halt failure because of {}",
385 this, feature.getClass().getName(), e.getMessage(), e);
394 public void onTopicEvent(Topic.CommInfrastructure commType,
395 String topic, String event) {
397 if (logger.isDebugEnabled())
398 logger.debug("{}: event offered from {}:{}: {}", this, commType, topic, event);
400 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
402 if (feature.beforeOffer(this, commType, topic, event))
404 } catch (Exception e) {
405 logger.error("{}: feature {} before-offer failure because of {}",
406 this, feature.getClass().getName(), e.getMessage(), e);
416 boolean success = this.droolsController.offer(topic, event);
418 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
420 if (feature.afterOffer(this, commType, topic, event, success))
422 } catch (Exception e) {
423 logger.error("{}: feature {} after-offer failure because of {}",
424 this, feature.getClass().getName(), e.getMessage(), e);
433 public boolean deliver(Topic.CommInfrastructure commType,
434 String topic, Object event) {
436 if (logger.isDebugEnabled())
437 logger.debug("{}: deliver event to {}:{}: {}", this, commType, topic, event);
439 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
441 if (feature.beforeDeliver(this, commType, topic, event))
443 } catch (Exception e) {
444 logger.error("{}: feature {} before-deliver failure because of {}",
445 this, feature.getClass().getName(), e.getMessage(), e);
449 if (topic == null || topic.isEmpty())
450 throw new IllegalArgumentException("Invalid Topic");
453 throw new IllegalArgumentException("Invalid Event");
456 throw new IllegalStateException("Policy Engine is stopped");
459 throw new IllegalStateException("Policy Engine is locked");
461 if (!this.topic2Sinks.containsKey(topic)) {
462 logger.warn("{}: cannot deliver event because the sink {}:{} is not registered: {}",
463 this, commType, topic, event);
464 throw new IllegalArgumentException("Unsuported topic " + topic + " for delivery");
467 boolean success = this.droolsController.deliver(this.topic2Sinks.get(topic), event);
469 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
471 if (feature.afterDeliver(this, commType, topic, event, success))
473 } catch (Exception e) {
474 logger.error("{}: feature {} after-deliver failure because of {}",
475 this, feature.getClass().getName(), e.getMessage(), e);
486 public boolean isAlive() {
494 public boolean lock() {
495 logger.info("{}: lock", this);
497 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
499 if (feature.beforeLock(this))
501 } catch (Exception e) {
502 logger.error("{}: feature {} before-lock failure because of {}",
503 this, feature.getClass().getName(), e.getMessage(), e);
514 // it does not affect associated sources/sinks, they are
515 // autonomous entities
517 boolean success = this.droolsController.lock();
519 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
521 if (feature.afterLock(this))
523 } catch (Exception e) {
524 logger.error("{}: feature {} after-lock failure because of {}",
525 this, feature.getClass().getName(), e.getMessage(), e);
536 public boolean unlock() {
538 logger.info("{}: unlock", this);
540 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
542 if (feature.beforeUnlock(this))
544 } catch (Exception e) {
545 logger.error("{}: feature {} before-unlock failure because of {}",
546 this, 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.error("{}: feature {} after-unlock failure because of {}",
565 this, feature.getClass().getName(), e.getMessage(), e);
576 public boolean isLocked() {
584 public List<? extends TopicSource> getTopicSources() {
592 public List<? extends TopicSink> getTopicSinks() {
600 public DroolsController getDrools() {
601 return this.droolsController;
610 public Properties getProperties() {
611 return this.properties;
615 public String toString() {
616 StringBuilder builder = new StringBuilder();
617 builder.append("AggregatedPolicyController [name=").append(name).append(", alive=").append(alive).append(", locked=").append(locked)
618 .append(", droolsController=").append(droolsController).append("]");
619 return builder.toString();