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<Removed>();
89 HashSet<Updated> updatedPolicies = new HashSet<Updated>();
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<String, String>();
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<Updated>();
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());