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.slf4j.Logger;
 
  28 import org.slf4j.LoggerFactory;
 
  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 = 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 =
 
  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("{}: cannot init-drools because of {}", this, e.getMessage(), e);
 
 148                         throw new IllegalArgumentException(e);
 
 154          * @throws IllegalArgumentException if invalid parameters are passed in
 
 156         protected void initSinks() throws IllegalArgumentException {
 
 157                 this.topic2Sinks.clear();
 
 158                 for (TopicSink sink: sinks) {
 
 159                         this.topic2Sinks.put(sink.getTopic(), sink);
 
 167         public boolean updateDrools(DroolsConfiguration newDroolsConfiguration) {
 
 169                 DroolsConfiguration oldDroolsConfiguration =
 
 170                                 new DroolsConfiguration(this.droolsController.getArtifactId(),
 
 171                                                                                 this.droolsController.getGroupId(), 
 
 172                                                         this.droolsController.getVersion());
 
 174                 if (oldDroolsConfiguration.getGroupId().equalsIgnoreCase(newDroolsConfiguration.getGroupId()) &&
 
 175                         oldDroolsConfiguration.getArtifactId().equalsIgnoreCase(newDroolsConfiguration.getArtifactId()) &&
 
 176                         oldDroolsConfiguration.getVersion().equalsIgnoreCase(newDroolsConfiguration.getVersion())) {
 
 177                         logger.warn("{}: cannot update-drools: identical configuration {} vs {}", 
 
 178                                             this, oldDroolsConfiguration, newDroolsConfiguration);
 
 183                         /* Drools Controller created, update initialization properties for restarts */
 
 185                         this.properties.setProperty(PolicyProperties.RULES_GROUPID, newDroolsConfiguration.getGroupId());
 
 186                         this.properties.setProperty(PolicyProperties.RULES_ARTIFACTID, newDroolsConfiguration.getArtifactId());
 
 187                         this.properties.setProperty(PolicyProperties.RULES_VERSION, newDroolsConfiguration.getVersion());
 
 189                         SystemPersistence.manager.storeController(name, this.properties);
 
 191                         this.initDrools(this.properties);
 
 193                         /* set drools controller to current locked status */
 
 196                                 this.droolsController.lock();
 
 198                                 this.droolsController.unlock();
 
 200                         /* set drools controller to current alive status */
 
 203                                 this.droolsController.start();
 
 205                                 this.droolsController.stop();
 
 207                 } catch (IllegalArgumentException e) {
 
 208                         logger.error("{}: cannot update-drools because of {}", this, e.getMessage(), e);
 
 219         public String getName() {
 
 227         public boolean start() throws IllegalStateException {           
 
 228                 logger.info("{}: start", this);
 
 230                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 232                                 if (feature.beforeStart(this))
 
 234                         } catch (Exception e) {
 
 235                                 logger.error("{}: feature {} before-start failure because of {}",  
 
 236                                          this, feature.getClass().getName(), e.getMessage(), e);
 
 241                         throw new IllegalStateException("Policy Controller " + name  + " is locked");
 
 250                 boolean success = this.droolsController.start();
 
 252                 // register for events
 
 254                 for (TopicSource source: sources) {
 
 255                         source.register(this);
 
 258                 for (TopicSink sink: sinks) {
 
 261                         } catch (Exception e) {
 
 262                                 logger.error("{}: cannot start {} because of {}",  
 
 263                                      this, sink, e.getMessage(), e);
 
 267                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 269                                 if (feature.afterStart(this))
 
 271                         } catch (Exception e) {
 
 272                                 logger.error("{}: feature {} after-start failure because of {}",  
 
 273                                      this, feature.getClass().getName(), e.getMessage(), e);
 
 284         public boolean stop() {
 
 285                 logger.info("{}: stop", this);
 
 287                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 289                                 if (feature.beforeStop(this))
 
 291                         } catch (Exception e) {
 
 292                                 logger.error("{}: feature {} before-stop failure because of {}",  
 
 293                                      this, feature.getClass().getName(), e.getMessage(), e);
 
 297                 /* stop regardless locked state */
 
 306                 // 1. Stop registration
 
 308                 for (TopicSource source: sources) {
 
 309                         source.unregister(this);
 
 312                 boolean success = this.droolsController.stop();
 
 314                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 316                                 if (feature.afterStop(this))
 
 318                         } catch (Exception e) {
 
 319                                 logger.error("{}: feature {} after-stop failure because of {}",  
 
 320                                  this, feature.getClass().getName(), e.getMessage(), e);
 
 331         public void shutdown() throws IllegalStateException {
 
 332                 logger.info("{}: shutdown", this);
 
 334                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 336                                 if (feature.beforeShutdown(this))
 
 338                         } catch (Exception e) {
 
 339                                 logger.error("{}: feature {} before-shutdown failure because of {}",  
 
 340                                  this, feature.getClass().getName(), e.getMessage(), e);
 
 346                 DroolsController.factory.shutdown(this.droolsController);
 
 348                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 350                                 if (feature.afterShutdown(this))
 
 352                         } catch (Exception e) {
 
 353                                 logger.error("{}: feature {} after-shutdown failure because of {}",  
 
 354                              this, feature.getClass().getName(), e.getMessage(), e);
 
 363         public void halt() throws IllegalStateException {
 
 364                 logger.info("{}: halt", this);
 
 366                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 368                                 if (feature.beforeHalt(this))
 
 370                         } catch (Exception e) {
 
 371                                 logger.error("{}: feature {} before-halt failure because of {}",  
 
 372                              this, feature.getClass().getName(), e.getMessage(), e);
 
 377                 DroolsController.factory.destroy(this.droolsController);
 
 378                 SystemPersistence.manager.deleteController(this.name);
 
 380                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 382                                 if (feature.afterHalt(this))
 
 384                         } catch (Exception e) {
 
 385                                 logger.error("{}: feature {} after-halt failure because of {}",  
 
 386                              this, feature.getClass().getName(), e.getMessage(), e);
 
 395         public void onTopicEvent(Topic.CommInfrastructure commType, 
 
 396                                             String topic, String event) {
 
 398                 if (logger.isDebugEnabled())
 
 399                         logger.debug("{}: event offered from {}:{}: {}", this, commType, topic, event);
 
 401                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 403                                 if (feature.beforeOffer(this, commType, topic, event))
 
 405                         } catch (Exception e) {
 
 406                                 logger.error("{}: feature {} before-offer failure because of {}",  
 
 407                              this, feature.getClass().getName(), e.getMessage(), e);
 
 417                 boolean success = this.droolsController.offer(topic, event);
 
 419                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 421                                 if (feature.afterOffer(this, commType, topic, event, success))
 
 423                         } catch (Exception e) {
 
 424                                 logger.error("{}: feature {} after-offer failure because of {}",  
 
 425                              this, 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 event to {}:{}: {}", this, commType, topic, event);
 
 442                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 444                                 if (feature.beforeDeliver(this, commType, topic, event))
 
 446                         } catch (Exception e) {
 
 447                                 logger.error("{}: feature {} before-deliver failure because of {}",  
 
 448                              this, feature.getClass().getName(), e.getMessage(), e);
 
 452                 if (topic == null || topic.isEmpty())
 
 453                         throw new IllegalArgumentException("Invalid Topic");
 
 456                         throw new IllegalArgumentException("Invalid Event");
 
 459                         throw new IllegalStateException("Policy Engine is stopped");
 
 462                         throw new IllegalStateException("Policy Engine is locked");
 
 464                 if (!this.topic2Sinks.containsKey(topic)) {
 
 465                         logger.warn("{}: cannot deliver event because the sink {}:{} is not registered: {}", 
 
 466                                              this, commType, topic, event);
 
 467                         throw new IllegalArgumentException("Unsuported topic " + topic + " for delivery");
 
 470                 boolean success = this.droolsController.deliver(this.topic2Sinks.get(topic), event);
 
 472                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 474                                 if (feature.afterDeliver(this, commType, topic, event, success))
 
 476                         } catch (Exception e) {
 
 477                                 logger.error("{}: feature {} after-deliver failure because of {}",  
 
 478                              this, feature.getClass().getName(), e.getMessage(), e);
 
 489         public boolean isAlive() {
 
 497         public boolean lock() {
 
 498                 logger.info("{}: lock", this);
 
 500                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 502                                 if (feature.beforeLock(this))
 
 504                         } catch (Exception e) {
 
 505                                 logger.error("{}: feature {} before-lock failure because of {}",  
 
 506                              this, feature.getClass().getName(), e.getMessage(), e);
 
 517                 // it does not affect associated sources/sinks, they are
 
 518                 // autonomous entities
 
 520                 boolean success = this.droolsController.lock();
 
 522                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 524                                 if (feature.afterLock(this))
 
 526                         } catch (Exception e) {
 
 527                                 logger.error("{}: feature {} after-lock failure because of {}",  
 
 528                              this, feature.getClass().getName(), e.getMessage(), e);
 
 539         public boolean unlock() {
 
 541                 logger.info("{}: unlock", this);
 
 543                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 545                                 if (feature.beforeUnlock(this))
 
 547                         } catch (Exception e) {
 
 548                                 logger.error("{}: feature {} before-unlock failure because of {}",  
 
 549                              this, feature.getClass().getName(), e.getMessage(), e);
 
 560                 boolean success = this.droolsController.unlock();
 
 562                 for (PolicyControllerFeatureAPI feature : PolicyControllerFeatureAPI.providers.getList()) {
 
 564                                 if (feature.afterUnlock(this))
 
 566                         } catch (Exception e) {
 
 567                                 logger.error("{}: feature {} after-unlock failure because of {}",  
 
 568                              this, feature.getClass().getName(), e.getMessage(), e);
 
 579         public boolean isLocked() {
 
 587         public List<? extends TopicSource> getTopicSources() {
 
 595         public List<? extends TopicSink> getTopicSinks() {
 
 603         public DroolsController getDrools() {
 
 604                 return this.droolsController;
 
 613         public Properties getProperties() {
 
 614                 return this.properties;
 
 618         public String toString() {
 
 619                 StringBuilder builder = new StringBuilder();
 
 620                 builder.append("AggregatedPolicyController [name=").append(name).append(", alive=").append(alive).append(", locked=").append(locked)
 
 621                                 .append(", droolsController=").append(droolsController).append("]");
 
 622                 return builder.toString();