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.pdp.rest.PapUrlResolver;
43 import org.openecomp.policy.rest.XACMLRestProperties;
44 import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
45 import org.openecomp.policy.common.logging.flexlogger.Logger;
47 import org.openecomp.policy.xacml.api.XACMLErrorConstants;
48 import com.att.research.xacml.api.pap.PDPPolicy;
49 import com.att.research.xacml.api.pap.PDPStatus;
50 import com.att.research.xacml.util.XACMLProperties;
51 import com.att.research.xacmlatt.pdp.policy.AllOf;
52 import com.att.research.xacmlatt.pdp.policy.AnyOf;
53 import com.att.research.xacmlatt.pdp.policy.Match;
54 import com.att.research.xacmlatt.pdp.policy.PolicyDef;
55 import com.fasterxml.jackson.core.JsonProcessingException;
56 import com.fasterxml.jackson.databind.ObjectMapper;
57 import com.fasterxml.jackson.databind.ObjectWriter;
60 * NotificationController Checks for the Updated and Removed policies. It
61 * notifies the Server to send Notifications to the Client.
66 public class NotificationController {
67 private static final Logger logger = FlexLogger.getLogger(NotificationController.class);
68 private static Notification record = new Notification();
69 private PDPStatus oldStatus = null;
70 private Removed removed = null;
71 private Updated updated = null;
72 private ManualNotificationUpdateThread registerMaunualNotificationRunnable = null;
73 private Thread manualNotificationThread = null;
74 private boolean manualThreadStarted = false;
76 private static String notificationJSON = null;
77 private static String propNotificationType = null;
78 private static String pdpURL = null;
79 private static Boolean notificationFlag = false;
81 public void check(PDPStatus newStatus,HashMap<String, PolicyDef> policyContainer) {
82 boolean updated = false;
83 boolean removed = false;
84 Notification notification = new Notification();
85 HashSet<Removed> removedPolicies = new HashSet<Removed>();
86 HashSet<Updated> updatedPolicies = new HashSet<Updated>();
88 if (oldStatus == null) {
89 oldStatus = newStatus;
91 // Debugging purpose only.
92 logger.debug("old config Status :" + oldStatus.getStatus());
93 logger.debug("new config Status :" + newStatus.getStatus());
95 // Depending on the above condition taking the Change as an Update.
96 if (oldStatus.getStatus().toString() != newStatus.getStatus().toString()) {
97 logger.info("There is an Update to the PDP");
98 logger.debug(oldStatus.getLoadedPolicies());
99 logger.debug(newStatus.getLoadedPolicies());
100 // Check if there is an Update/additions in the policy.
101 for (PDPPolicy newPolicy : newStatus.getLoadedPolicies()) {
102 boolean change = true;
103 for (PDPPolicy oldPolicy : oldStatus.getLoadedPolicies()) {
104 // Check if there are same policies.
105 if (oldPolicy.getId().equals(newPolicy.getId())) {
106 // Check if they have same version.
107 if (oldPolicy.getVersion().equals(newPolicy.getVersion())) {
112 // if there is a change Send the notifications to the Client.
114 sendUpdate(newPolicy, policyContainer);
116 updatedPolicies.add(this.updated);
119 // Check if there is any removal of policy.
120 for (PDPPolicy oldPolicy : oldStatus.getLoadedPolicies()) {
121 boolean change = true;
122 for (PDPPolicy newPolicy : newStatus.getLoadedPolicies()) {
123 // Check if there are same policies.
124 if (oldPolicy.getId().equals(newPolicy.getId())) {
125 // Check if they have same version.
126 if (oldPolicy.getVersion().equals(newPolicy.getVersion())) {
131 // if there is a change Send the notifications to the Client.
133 sendremove(oldPolicy);
135 removedPolicies.add(this.removed);
139 // At the end the oldStatus must be updated with the newStatus.
140 oldStatus = newStatus;
141 // Sending Notification to the Server to pass over to the clients
142 if (updated || removed) {
143 // Call the Notification Server..
144 notification.setRemovedPolicies(removedPolicies);
145 notification.setLoadedPolicies(updatedPolicies);
146 ObjectWriter om = new ObjectMapper().writer();
148 notificationJSON = om.writeValueAsString(notification);
149 logger.info(notificationJSON);
150 // NotificationServer Method here.
151 propNotificationType = XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_TYPE);
152 pdpURL = XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_ID);
153 if (propNotificationType!=null && propNotificationType.equals("ueb") && !manualThreadStarted) {
154 logger.debug("Starting Thread to accept UEB notfications.");
155 this.registerMaunualNotificationRunnable = new ManualNotificationUpdateThread();
156 this.manualNotificationThread = new Thread(this.registerMaunualNotificationRunnable);
157 this.manualNotificationThread.start();
158 manualThreadStarted = true;
160 String notificationJSON= null;
161 notificationFlag = true;
163 notificationJSON= record(notification);
166 // TODO:EELF Cleanup - Remove logger
167 //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "");
169 NotificationServer.setUpdate(notificationJSON);
170 ManualNotificationUpdateThread.setUpdate(notificationJSON);
171 } catch (JsonProcessingException e) {
172 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e.getMessage());
173 // TODO:EELF Cleanup - Remove logger
174 //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "");
179 public static void sendNotification(){
180 if(notificationFlag){
181 NotificationServer.sendNotification(notificationJSON, propNotificationType, pdpURL);
182 notificationFlag = false;
186 private void sendremove(PDPPolicy oldPolicy) {
187 removed = new Removed();
188 // Want to know what is removed ?
189 // logger.info("The Policy removed is: " + oldPolicy.getId());
190 // logger.info("The version no. is: " + oldPolicy.getVersion());
191 logger.info("Policy removed: " + oldPolicy.getId()+ " with version number: " + oldPolicy.getVersion());
192 removed.setPolicyName(oldPolicy.getId());
193 removed.setVersionNo(oldPolicy.getVersion());
194 removeFile(oldPolicy);
197 private void sendUpdate(PDPPolicy newPolicy,HashMap<String, PolicyDef> policyContainer) {
198 updated = new Updated();
199 // Want to know what is new ?
200 logger.info("The new Policy is: " + newPolicy.getId());
201 logger.info("The version no. is: " + newPolicy.getVersion());
202 updated.setPolicyName(newPolicy.getId());
203 updated.setVersionNo(newPolicy.getVersion());
204 // If the policy is of Config type then retrieve its matches.
205 if (newPolicy.getName().startsWith("Config")) {
206 // Take a Configuration copy to PDP webapps.
207 final String urlStart = "attributeId=URLID,expression";
208 final String urlEnd = "}}},{";
209 String policy = policyContainer.get(newPolicy.getId()).toString();
210 if(policy.contains(urlStart)){
211 String urlFinePartOne = policy.substring(policy.indexOf(urlStart)+urlStart.length());
212 String urlFinePart = urlFinePartOne.substring(0,urlFinePartOne.indexOf(urlEnd));
213 String urlString = urlFinePart.substring(urlFinePart.indexOf("value=$URL")+6);
214 callPap(urlString, "Config");
216 Iterator<AnyOf> anyOfs = policyContainer.get(newPolicy.getId()).getTarget().getAnyOfs();
217 while (anyOfs.hasNext()) {
218 AnyOf anyOf = anyOfs.next();
219 Iterator<AllOf> allOfs = anyOf.getAllOfs();
220 while (allOfs.hasNext()) {
221 AllOf allOf = allOfs.next();
222 Iterator<Match> matches = allOf.getMatches();
223 HashMap<String, String> matchValues = new HashMap<String, String>();
224 while (matches.hasNext()) {
225 Match match = matches.next();
226 logger.info("Attribute Value is: "+ match.getAttributeValue().getValue().toString());
227 String[] result = match.getAttributeRetrievalBase().toString().split("attributeId=");
228 result[1] = result[1].replaceAll("}", "");
229 if (!result[1].equals("urn:oasis:names:tc:xacml:1.0:subject:subject-id")) {
230 logger.info("Attribute id is: " + result[1]);
232 matchValues.put(result[1], match.getAttributeValue().getValue().toString());
233 logger.info("Match is : "+ result[1]+ " , " + match.getAttributeValue().getValue().toString());
235 updated.setMatches(matchValues);
238 }else if(newPolicy.getName().startsWith("Action")){
239 // Take Configuration copy to PDP Webapps.
240 // Action policies have .json as extension.
241 String urlString = "$URL/Action/" + newPolicy.getId().substring(0, newPolicy.getId().lastIndexOf(".")) + ".json";
242 callPap(urlString, "Action");
246 // Adding this for Recording the changes to serve Polling requests..
247 public static String record(Notification notification) throws Exception {
248 // Initialization with updates.
249 if (record.getRemovedPolicies() == null || record.getLoadedPolicies() == null) {
250 record.setRemovedPolicies(notification.getRemovedPolicies());
251 record.setLoadedPolicies(notification.getLoadedPolicies());
253 // Check if there is anything new and update the record..
254 if (record.getLoadedPolicies() != null || record.getRemovedPolicies() != null) {
255 HashSet<Removed> removedPolicies = (HashSet<Removed>) record.getRemovedPolicies();
256 HashSet<Updated> updatedPolicies = (HashSet<Updated>) record.getLoadedPolicies();
258 // Checking with New updated policies.
259 if (notification.getLoadedPolicies() != null && !notification.getLoadedPolicies().isEmpty()) {
260 for (Updated newUpdatedPolicy : notification.getLoadedPolicies()) {
261 // If it was removed earlier then we need to remove from our record
262 Iterator<Removed> oldRemovedPolicy = removedPolicies.iterator();
263 while (oldRemovedPolicy.hasNext()) {
264 Removed policy = oldRemovedPolicy.next();
265 if (newUpdatedPolicy.getPolicyName().equals(policy.getPolicyName())) {
266 if (newUpdatedPolicy.getVersionNo().equals(policy.getVersionNo())) {
267 oldRemovedPolicy.remove();
271 // If it was previously updated need to Overwrite it to the record.
272 Iterator<Updated> oldUpdatedPolicy = updatedPolicies.iterator();
273 while (oldUpdatedPolicy.hasNext()) {
274 Updated policy = oldUpdatedPolicy.next();
275 if (newUpdatedPolicy.getPolicyName().equals(policy.getPolicyName())) {
276 if (newUpdatedPolicy.getVersionNo().equals(policy.getVersionNo())) {
277 oldUpdatedPolicy.remove();
281 updatedPolicies.add(newUpdatedPolicy);
284 // Checking with New Removed policies.
285 if (notification.getRemovedPolicies() != null && !notification.getRemovedPolicies().isEmpty()) {
286 for (Removed newRemovedPolicy : notification.getRemovedPolicies()) {
287 // If it was previously removed Overwrite it to the record.
288 Iterator<Removed> oldRemovedPolicy = removedPolicies.iterator();
289 while (oldRemovedPolicy.hasNext()) {
290 Removed policy = oldRemovedPolicy.next();
291 if (newRemovedPolicy.getPolicyName().equals(policy.getPolicyName())) {
292 if (newRemovedPolicy.getVersionNo().equals(policy.getVersionNo())) {
293 oldRemovedPolicy.remove();
297 // If it was added earlier then we need to remove from our record.
298 Iterator<Updated> oldUpdatedPolicy = updatedPolicies.iterator();
299 while (oldUpdatedPolicy.hasNext()) {
300 Updated policy = oldUpdatedPolicy.next();
301 if (newRemovedPolicy.getPolicyName().equals(policy.getPolicyName())) {
302 if (newRemovedPolicy.getVersionNo().equals(policy.getVersionNo())) {
303 oldUpdatedPolicy.remove();
307 removedPolicies.add(newRemovedPolicy);
310 record.setRemovedPolicies(removedPolicies);
311 record.setLoadedPolicies(updatedPolicies);
314 // Send the Result to the caller.
315 ObjectWriter om = new ObjectMapper().writer();
318 json = om.writeValueAsString(record);
319 } catch (JsonProcessingException e) {
320 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e.getMessage());
321 // TODO:EELF Cleanup - Remove logger
322 //PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "");
328 private void removeFile(PDPPolicy oldPolicy) {
330 Path removedPolicyFile = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_CONFIG)+File.separator+oldPolicy.getId());
331 Files.deleteIfExists(removedPolicyFile);
332 boolean delete=false;
334 if(oldPolicy.getName().startsWith("Config")){
336 dir = new File(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)+File.separator+"Config");
337 }else if(oldPolicy.getName().startsWith("Action")){
339 dir = new File(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)+File.separator+"Action");
341 if(delete && dir!=null){
342 FileFilter fileFilter = new WildcardFileFilter(oldPolicy.getId().substring(0, oldPolicy.getId().lastIndexOf("."))+".*");
343 File[] configFile = dir.listFiles(fileFilter);
344 if(configFile.length==1){
345 Files.deleteIfExists(configFile[0].toPath());
349 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Couldn't remove the policy/config file " + oldPolicy.getName());
350 // TODO:EELF Cleanup - Remove logger
351 //PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "Couldn't remove the policy file " + oldPolicy.getName());
355 private void callPap(String urlString, String type) {
356 Path configLocation = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_WEBAPPS)+File.separator+type);
357 if(Files.notExists(configLocation)){
359 Files.createDirectories(configLocation);
360 } catch (IOException e) {
361 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW +"Failed to create config directory: " + configLocation.toAbsolutePath().toString(), e);
364 PapUrlResolver papUrls = PapUrlResolver.getInstance();
365 while(papUrls.hasMoreUrls()){
366 String papPath = papUrls.getUrl();
367 papPath = papPath.substring(0, papPath.lastIndexOf("/pap"));
368 String papAddress= urlString.replace("$URL", papPath);
369 String fileName = papAddress.substring(papAddress.lastIndexOf("/")+1);
370 String fileLocation = configLocation.toString() + File.separator + fileName;
372 URL papURL = new URL(papAddress);
373 logger.info("Calling " +papAddress + " for Configuration Copy.");
374 URLConnection urlConnection = papURL.openConnection();
375 File file= new File(fileLocation);
376 try (InputStream is = urlConnection.getInputStream();
377 OutputStream os = new FileOutputStream(file)) {
378 IOUtils.copy(is, os);
381 } catch (MalformedURLException e) {
382 logger.error(e + e.getMessage());
383 } catch(FileNotFoundException e){
384 logger.error(e + e.getMessage());
385 } catch (IOException e) {
386 logger.error(e + e.getMessage());