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.pdp.rest.notifications;
 
  24 import java.io.FileFilter;
 
  25 import java.io.FileNotFoundException;
 
  26 import java.io.FileOutputStream;
 
  27 import java.io.IOException;
 
  28 import java.io.InputStream;
 
  29 import java.io.OutputStream;
 
  30 import java.net.MalformedURLException;
 
  32 import java.net.URLConnection;
 
  33 import java.nio.file.Files;
 
  34 import java.nio.file.Path;
 
  35 import java.nio.file.Paths;
 
  36 import java.util.HashMap;
 
  37 import java.util.HashSet;
 
  38 import java.util.Iterator;
 
  40 import org.apache.commons.io.IOUtils;
 
  41 import org.apache.commons.io.filefilter.WildcardFileFilter;
 
  42 import org.openecomp.policy.api.NotificationType;
 
  43 import org.openecomp.policy.api.RemovedPolicy;
 
  44 import org.openecomp.policy.api.UpdateType;
 
  45 import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
 
  46 import org.openecomp.policy.common.logging.flexlogger.Logger;
 
  47 import org.openecomp.policy.pdp.rest.PapUrlResolver;
 
  48 import org.openecomp.policy.rest.XACMLRestProperties;
 
  49 import org.openecomp.policy.xacml.api.XACMLErrorConstants;
 
  51 import com.att.research.xacml.api.pap.PDPPolicy;
 
  52 import com.att.research.xacml.api.pap.PDPStatus;
 
  53 import com.att.research.xacml.util.XACMLProperties;
 
  54 import com.att.research.xacmlatt.pdp.policy.AllOf;
 
  55 import com.att.research.xacmlatt.pdp.policy.AnyOf;
 
  56 import com.att.research.xacmlatt.pdp.policy.Match;
 
  57 import com.att.research.xacmlatt.pdp.policy.PolicyDef;
 
  58 import com.fasterxml.jackson.core.JsonProcessingException;
 
  59 import com.fasterxml.jackson.databind.ObjectMapper;
 
  60 import com.fasterxml.jackson.databind.ObjectWriter;
 
  63  * NotificationController Checks for the Updated and Removed policies. It
 
  64  * notifies the Server to send Notifications to the Client.
 
  69 public class NotificationController {
 
  70         private static final Logger LOGGER = FlexLogger.getLogger(NotificationController.class);
 
  71         private static Notification record = new Notification();
 
  72         private PDPStatus oldStatus = null;
 
  73         private Removed removed = null;
 
  74         private Updated updated = null;
 
  75         private ManualNotificationUpdateThread registerMaunualNotificationRunnable = null;
 
  76         private Thread manualNotificationThread = null;
 
  77         private boolean manualThreadStarted = false;
 
  79         private static String notificationJSON = null;
 
  80         private static String propNotificationType = null;
 
  81         private static String pdpURL = null;
 
  82         private static Boolean notificationFlag = false; 
 
  84         public void check(PDPStatus newStatus,HashMap<String, PolicyDef> policyContainer) {
 
  85                 boolean updated = false;
 
  86                 boolean removed = false;
 
  87                 Notification notification = new Notification();
 
  88                 HashSet<Removed> removedPolicies = new HashSet<>();
 
  89                 HashSet<Updated> updatedPolicies = new HashSet<>();
 
  91                 if (oldStatus == null) {
 
  92                         oldStatus = newStatus;
 
  94                 // Debugging purpose only.
 
  95                 LOGGER.debug("old config Status :" + oldStatus.getStatus());
 
  96                 LOGGER.debug("new config Status :" + newStatus.getStatus());
 
  98                 // Depending on the above condition taking the Change as an Update.
 
  99                 if (oldStatus.getStatus().toString() != newStatus.getStatus().toString()) {
 
 100                         LOGGER.info("There is an Update to the PDP");
 
 101                         LOGGER.debug(oldStatus.getLoadedPolicies());
 
 102                         LOGGER.debug(newStatus.getLoadedPolicies());
 
 103                         // Check if there is an Update/additions in the policy.
 
 104                         for (PDPPolicy newPolicy : newStatus.getLoadedPolicies()) {
 
 105                                 boolean change = true;
 
 106                                 for (PDPPolicy oldPolicy : oldStatus.getLoadedPolicies()) {
 
 107                                         // Check if there are same policies.
 
 108                                         if (oldPolicy.getId().equals(newPolicy.getId())) {
 
 109                                                 // Check if they have same version.
 
 110                                                 if (oldPolicy.getVersion().equals(newPolicy.getVersion())) {
 
 115                                 // if there is a change Send the notifications to the Client.
 
 117                                         sendUpdate(newPolicy, policyContainer);
 
 119                                         updatedPolicies.add(this.updated);
 
 122                         // Check if there is any removal of policy.
 
 123                         for (PDPPolicy oldPolicy : oldStatus.getLoadedPolicies()) {
 
 124                                 boolean change = true;
 
 125                                 for (PDPPolicy newPolicy : newStatus.getLoadedPolicies()) {
 
 126                                         // Check if there are same policies.
 
 127                                         if (oldPolicy.getId().equals(newPolicy.getId())) {
 
 128                                                 // Check if they have same version.
 
 129                                                 if (oldPolicy.getVersion().equals(newPolicy.getVersion())) {
 
 134                                 // if there is a change Send the notifications to the Client.
 
 136                                         sendremove(oldPolicy);
 
 138                                         removedPolicies.add(this.removed);
 
 142                 // At the end the oldStatus must be updated with the newStatus.
 
 143                 oldStatus = newStatus;
 
 144                 // Sending Notification to the Server to pass over to the clients
 
 145                 if (updated || removed) {
 
 146                         // Call the Notification Server..
 
 147                         notification.setRemovedPolicies(removedPolicies);
 
 148                         notification.setLoadedPolicies(updatedPolicies);
 
 149                         notification = setUpdateTypes(updated, removed, notification);
 
 150                         ObjectWriter om = new ObjectMapper().writer();
 
 152                                 notificationJSON = om.writeValueAsString(notification);
 
 153                                 LOGGER.info(notificationJSON);
 
 154                                 // NotificationServer Method here.
 
 155                                 propNotificationType = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_TYPE);
 
 156                                 pdpURL = XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_ID);
 
 157                                 if (("ueb".equals(propNotificationType)||"dmaap".equals(propNotificationType)) && !manualThreadStarted) {
 
 158                                         LOGGER.debug("Starting  Thread to accept UEB or DMAAP notfications.");
 
 159                                         this.registerMaunualNotificationRunnable = new ManualNotificationUpdateThread();
 
 160                                         this.manualNotificationThread = new Thread(this.registerMaunualNotificationRunnable);
 
 161                                         this.manualNotificationThread.start();
 
 162                                         manualThreadStarted = true;
 
 164                                 String notificationJSON= null;
 
 165                                 notificationFlag = true;
 
 167                                         notificationJSON= record(notification);
 
 170                                         // TODO:EELF Cleanup - Remove LOGGER
 
 171                                         //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "");
 
 173                                 NotificationServer.setUpdate(notificationJSON);
 
 174                                 ManualNotificationUpdateThread.setUpdate(notificationJSON);
 
 175                         } catch (JsonProcessingException e) {
 
 176                                 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e.getMessage());
 
 177                                 // TODO:EELF Cleanup - Remove LOGGER
 
 178                                 //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "");
 
 183         public static void sendNotification(){
 
 184                 if(notificationFlag){
 
 186                                 NotificationServer.sendNotification(notificationJSON, propNotificationType, pdpURL);
 
 187                         } catch (Exception e) {
 
 188                                 LOGGER.info(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error in sending the Event Notification: "+ e.getMessage());
 
 190                         notificationFlag = false;
 
 194         private void sendremove(PDPPolicy oldPolicy) {
 
 195                 removed = new Removed();
 
 196                 // Want to know what is removed ?
 
 197                 // LOGGER.info("The Policy removed is: " + oldPolicy.getId());
 
 198                 // LOGGER.info("The version no. is: " + oldPolicy.getVersion());
 
 199                 LOGGER.info("Policy removed: " + oldPolicy.getId()+ " with version number: " + oldPolicy.getVersion());
 
 200                 removed.setPolicyName(oldPolicy.getId());
 
 201                 removed.setVersionNo(oldPolicy.getVersion());
 
 202                 removeFile(oldPolicy);
 
 205         private void sendUpdate(PDPPolicy newPolicy,HashMap<String, PolicyDef> policyContainer) {
 
 206                 updated = new Updated();
 
 207                 // Want to know what is new ?
 
 208                 LOGGER.info("The new Policy is: " + newPolicy.getId());
 
 209                 LOGGER.info("The version no. is: " + newPolicy.getVersion());
 
 210                 updated.setPolicyName(newPolicy.getId());
 
 211                 updated.setVersionNo(newPolicy.getVersion());
 
 212                 updated.setUpdateType(UpdateType.NEW);
 
 213                 // If the policy is of Config type then retrieve its matches.
 
 214                 if (newPolicy.getName().contains(".Config_")) {
 
 215                         // Take a Configuration copy to PDP webapps. 
 
 216                         final String urlStart = "attributeId=URLID,expression";
 
 217                         final String urlEnd = "}}},{";
 
 218                         String policy = policyContainer.get(newPolicy.getId()).toString(); 
 
 219                         if(policy.contains(urlStart)){
 
 220                                 String urlFinePartOne = policy.substring(policy.indexOf(urlStart)+urlStart.length());
 
 221                                 String urlFinePart = urlFinePartOne.substring(0,urlFinePartOne.indexOf(urlEnd));
 
 222                                 String urlString = urlFinePart.substring(urlFinePart.indexOf("value=$URL")+6); 
 
 223                                 callPap(urlString, "Config");
 
 225                         Iterator<AnyOf> anyOfs = policyContainer.get(newPolicy.getId()).getTarget().getAnyOfs();
 
 226                         while (anyOfs.hasNext()) {
 
 227                                 AnyOf anyOf = anyOfs.next();
 
 228                                 Iterator<AllOf> allOfs = anyOf.getAllOfs();
 
 229                                 while (allOfs.hasNext()) {
 
 230                                         AllOf allOf = allOfs.next();
 
 231                                         Iterator<Match> matches = allOf.getMatches();
 
 232                                         HashMap<String, String> matchValues = new HashMap<>();
 
 233                                         while (matches.hasNext()) {
 
 234                                                 Match match = matches.next();
 
 235                                                 LOGGER.info("Attribute Value is: "+ match.getAttributeValue().getValue().toString());
 
 236                                                 String[] result = match.getAttributeRetrievalBase().toString().split("attributeId=");
 
 237                                                 result[1] = result[1].replaceAll("}", "");
 
 238                                                 if (!result[1].equals("urn:oasis:names:tc:xacml:1.0:subject:subject-id")) {
 
 239                                                         LOGGER.info("Attribute id is: " + result[1]);
 
 241                                                 matchValues.put(result[1], match.getAttributeValue().getValue().toString());
 
 242                                                 LOGGER.info("Match is : "+ result[1]+ " , "     + match.getAttributeValue().getValue().toString());
 
 244                                         updated.setMatches(matchValues);
 
 247                 }else if(newPolicy.getName().contains(".Action_")){
 
 248                         // Take Configuration copy to PDP Webapps.
 
 249                         // Action policies have .json as extension. 
 
 250                         String urlString = "$URL/Action/" + newPolicy.getId().substring(0, newPolicy.getId().lastIndexOf(".")) + ".json";
 
 251                         callPap(urlString, "Action");
 
 255         // Adding this for Recording the changes to serve Polling requests..
 
 256         private static String record(Notification notification) throws Exception {
 
 257                 // Initialization with updates.
 
 258                 if (record.getRemovedPolicies() == null || record.getLoadedPolicies() == null) {
 
 259                         record.setRemovedPolicies(notification.getRemovedPolicies());
 
 260                         record.setLoadedPolicies(notification.getLoadedPolicies());
 
 262                         // Check if there is anything new and update the record..
 
 263                         if (record.getLoadedPolicies() != null  || record.getRemovedPolicies() != null) {
 
 264                                 HashSet<Removed> removedPolicies = (HashSet<Removed>) record.getRemovedPolicies();
 
 265                                 HashSet<Updated> updatedPolicies = (HashSet<Updated>) record.getLoadedPolicies();
 
 267                                 // Checking with New updated policies.
 
 268                                 if (notification.getLoadedPolicies() != null && !notification.getLoadedPolicies().isEmpty()) {
 
 269                                         for (Updated newUpdatedPolicy : notification.getLoadedPolicies()) {
 
 270                                                 // If it was removed earlier then we need to remove from our record
 
 271                                                 Iterator<Removed> oldRemovedPolicy = removedPolicies.iterator();
 
 272                                                 while (oldRemovedPolicy.hasNext()) {
 
 273                                                         Removed policy = oldRemovedPolicy.next();
 
 274                                                         if (newUpdatedPolicy.getPolicyName().equals(policy.getPolicyName())) {
 
 275                                                                 if (newUpdatedPolicy.getVersionNo().equals(policy.getVersionNo())) {
 
 276                                                                         oldRemovedPolicy.remove();
 
 280                                                 // If it was previously updated need to Overwrite it to the record.
 
 281                                                 Iterator<Updated> oldUpdatedPolicy = updatedPolicies.iterator();
 
 282                                                 while (oldUpdatedPolicy.hasNext()) {
 
 283                                                         Updated policy = oldUpdatedPolicy.next();
 
 284                                                         if (newUpdatedPolicy.getPolicyName().equals(policy.getPolicyName())) {
 
 285                                                                 if (newUpdatedPolicy.getVersionNo().equals(policy.getVersionNo())) {
 
 286                                                                         oldUpdatedPolicy.remove();
 
 290                                                 updatedPolicies.add(newUpdatedPolicy);
 
 293                                 // Checking with New Removed policies.
 
 294                                 if (notification.getRemovedPolicies() != null && !notification.getRemovedPolicies().isEmpty()) {
 
 295                                         for (Removed newRemovedPolicy : notification.getRemovedPolicies()) {
 
 296                                                 // If it was previously removed Overwrite it to the record.
 
 297                                                 Iterator<Removed> oldRemovedPolicy = removedPolicies.iterator();
 
 298                                                 while (oldRemovedPolicy.hasNext()) {
 
 299                                                         Removed policy = oldRemovedPolicy.next();
 
 300                                                         if (newRemovedPolicy.getPolicyName().equals(policy.getPolicyName())) {
 
 301                                                                 if (newRemovedPolicy.getVersionNo().equals(policy.getVersionNo())) {
 
 302                                                                         oldRemovedPolicy.remove();
 
 306                                                 // If it was added earlier then we need to remove from our record.
 
 307                                                 Iterator<Updated> oldUpdatedPolicy = updatedPolicies.iterator();
 
 308                                                 while (oldUpdatedPolicy.hasNext()) {
 
 309                                                         Updated policy = oldUpdatedPolicy.next();
 
 310                                                         if (newRemovedPolicy.getPolicyName().equals(policy.getPolicyName())) {
 
 311                                                                 if (newRemovedPolicy.getVersionNo().equals(policy.getVersionNo())) {
 
 312                                                                         oldUpdatedPolicy.remove();
 
 316                                                 removedPolicies.add(newRemovedPolicy);
 
 319                                 record.setRemovedPolicies(removedPolicies);
 
 320                                 record.setLoadedPolicies(updatedPolicies);
 
 323                 // Send the Result to the caller.
 
 324                 ObjectWriter om = new ObjectMapper().writer();
 
 327                         json = om.writeValueAsString(record);
 
 328                 } catch (JsonProcessingException e) {
 
 329                         LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e.getMessage());
 
 330                         // TODO:EELF Cleanup - Remove LOGGER
 
 331                         //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "");
 
 337         private static Notification setUpdateTypes(boolean updated, boolean removed, Notification notification) {
 
 338         if(notification!=null){
 
 339             if(updated && removed){
 
 340                 notification.setNotificationType(NotificationType.BOTH);
 
 341                 if(notification.getLoadedPolicies()!=null){
 
 342                     HashSet<Updated> updatedPolicies = new HashSet<>(); 
 
 343                     for(Updated oldUpdatedPolicy: notification.getLoadedPolicies()){
 
 344                         Updated updatePolicy = oldUpdatedPolicy;
 
 345                         if(notification.getRemovedPolicies()!=null){
 
 346                             for(RemovedPolicy removedPolicy: notification.getRemovedPolicies()){
 
 347                                 String regex = ".(\\d)*.xml";
 
 348                                 if(removedPolicy.getPolicyName().replaceAll(regex, "").equals(oldUpdatedPolicy.getPolicyName().replaceAll(regex, ""))){
 
 349                                     updatePolicy.setUpdateType(UpdateType.UPDATE);
 
 354                         updatedPolicies.add(updatePolicy);
 
 356                     notification.setLoadedPolicies(updatedPolicies);
 
 359                 notification.setNotificationType(NotificationType.UPDATE);
 
 361                 notification.setNotificationType(NotificationType.REMOVE);
 
 367         private void removeFile(PDPPolicy oldPolicy) {
 
 369                         Path removedPolicyFile = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_CONFIG)+File.separator+oldPolicy.getId());
 
 370                         Files.deleteIfExists(removedPolicyFile);
 
 371                         boolean delete=false;
 
 373                         if(oldPolicy.getName().startsWith("Config")){
 
 375                                 dir = new File(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)+File.separator+"Config");
 
 376                         }else if(oldPolicy.getName().startsWith("Action")){
 
 378                                 dir = new File(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)+File.separator+"Action");
 
 380                         if(delete && dir!=null){
 
 381                                 FileFilter fileFilter = new WildcardFileFilter(oldPolicy.getId().substring(0, oldPolicy.getId().lastIndexOf("."))+".*");
 
 382                                 File[] configFile = dir.listFiles(fileFilter);
 
 383                                 if(configFile.length==1){
 
 384                                         Files.deleteIfExists(configFile[0].toPath());
 
 388                         LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Couldn't remove the policy/config file " + oldPolicy.getName());
 
 389                         // TODO:EELF Cleanup - Remove LOGGER
 
 390                         //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "Couldn't remove the policy file " + oldPolicy.getName());
 
 394         private void callPap(String urlString, String type) {
 
 395                 Path configLocation = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)+File.separator+type);
 
 396                 if(Files.notExists(configLocation)){
 
 398                                 Files.createDirectories(configLocation);
 
 399                         } catch (IOException e) {
 
 400                                 LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW +"Failed to create config directory: " + configLocation.toAbsolutePath().toString(), e);
 
 403                 PapUrlResolver papUrls = PapUrlResolver.getInstance();
 
 404                 while(papUrls.hasMoreUrls()){
 
 405                         String papPath = papUrls.getUrl();
 
 406                         papPath = papPath.substring(0, papPath.lastIndexOf("/pap"));
 
 407                         String papAddress= urlString.replace("$URL", papPath);
 
 408                         String fileName = papAddress.substring(papAddress.lastIndexOf("/")+1);
 
 409                         String fileLocation = configLocation.toString() + File.separator + fileName;
 
 411                                 URL papURL = new URL(papAddress);
 
 412                                 LOGGER.info("Calling " +papAddress + " for Configuration Copy.");
 
 413                                 URLConnection urlConnection = papURL.openConnection();
 
 414                                 File file= new File(fileLocation);
 
 415                                 try (InputStream is = urlConnection.getInputStream();
 
 416                                                 OutputStream os = new FileOutputStream(file)) {
 
 417                                         IOUtils.copy(is, os);
 
 420                         } catch (MalformedURLException e) {
 
 421                                 LOGGER.error(e + e.getMessage());
 
 422                         } catch(FileNotFoundException e){
 
 423                                 LOGGER.error(e + e.getMessage());
 
 424                         } catch (IOException e) {
 
 425                                 LOGGER.error(e + e.getMessage());