Initial OpenECOMP policy/engine commit
[policy/engine.git] / ECOMP-XACML / src / main / java / org / openecomp / policy / xacml / std / pap / StdPDPGroup.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ECOMP-XACML
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20 package org.openecomp.policy.xacml.std.pap;
21
22 import org.openecomp.policy.common.logging.eelf.MessageCodes;
23 import org.openecomp.policy.common.logging.eelf.PolicyLogger;
24
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.io.Serializable;
29 import java.nio.file.Files;
30 import java.nio.file.Path;
31 import java.nio.file.Paths;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.Enumeration;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Properties;
38 import java.util.Set;
39 import java.util.TreeSet;
40
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.openecomp.policy.xacml.api.pap.EcompPDP;
44 import org.openecomp.policy.xacml.api.pap.EcompPDPGroup;
45 import org.openecomp.policy.xacml.std.pap.StdPDPItemSetChangeNotifier.StdItemSetChangeListener;
46
47 import com.att.research.xacml.api.pap.PAPException;
48 import com.att.research.xacml.api.pap.PDP;
49 import com.att.research.xacml.api.pap.PDPGroup;
50 //import com.att.research.xacml.api.pap.PDPGroup;
51 import com.att.research.xacml.api.pap.PDPGroupStatus;
52 import com.att.research.xacml.api.pap.PDPGroupStatus.Status;
53 import com.att.research.xacml.api.pap.PDPPIPConfig;
54 import com.att.research.xacml.api.pap.PDPPolicy;
55 import com.att.research.xacml.util.XACMLProperties;
56 import com.fasterxml.jackson.annotation.JsonIgnore;
57 import com.google.common.base.Joiner;
58 import com.google.common.base.Splitter;
59 import com.google.common.io.ByteStreams;
60
61 public class StdPDPGroup extends StdPDPItemSetChangeNotifier implements EcompPDPGroup, StdItemSetChangeListener, Comparable<Object>, Serializable {
62         private static final long serialVersionUID = 1L;
63         private static Log      logger  = LogFactory.getLog(StdPDPGroup.class);
64         
65         private String id;
66         
67         private boolean isDefault = false;
68         
69         private String name;
70         
71         private String description;
72         
73         private StdPDPGroupStatus status = new StdPDPGroupStatus(Status.UNKNOWN);
74         
75         private Set<EcompPDP>   pdps = new HashSet<EcompPDP>();
76         
77         private Set<PDPPolicy> policies = new HashSet<PDPPolicy>();
78         
79         private Set<PDPPIPConfig> pipConfigs = new HashSet<PDPPIPConfig>();
80         
81         @JsonIgnore
82         private  Path directory;
83         
84         @JsonIgnore
85         private Integer jmxport;
86         
87         
88         public StdPDPGroup(String id, Path directory) {
89                 this.id = id;
90                 this.directory = directory;
91         }
92         
93         public StdPDPGroup(String id, boolean isDefault, Path directory) {
94                 this(id, directory);
95                 this.isDefault = isDefault;
96         }
97         
98         public StdPDPGroup(String id, boolean isDefault, String name, String description, Path directory) {
99                 this(id, isDefault, directory);
100                 this.name = name;
101                 // force all policies to have a name
102                 if (name == null) {
103                         this.name = id;
104                 }
105                 this.description = description;
106         }
107         
108         public StdPDPGroup(String id, String name, String description, Path directory) {
109                 this(id, false, name, description, directory);
110                 this.resetStatus();
111         }
112         
113         public StdPDPGroup(String id, boolean isDefault, Properties properties, Path directory) throws PAPException {
114                 this(id, isDefault, directory);
115                 this.initialize(properties, directory);
116                 this.resetStatus();
117         }
118         
119         private void initialize(Properties properties, Path directory) throws PAPException {
120                 if (this.id == null || this.id.length() == 0) {
121                         logger.warn("Cannot initialize with a null or zero length id");
122                         return;
123                 }
124                 //
125                 // Pull the group's properties
126                 //
127                 for (Object key : properties.keySet()) {
128                         if (key.toString().startsWith(this.id + ".")) {
129                                 if (key.toString().endsWith(".name")) {
130                                         this.name = properties.getProperty(key.toString());
131                                 } else if (key.toString().endsWith(".description")) {
132                                         this.description = properties.getProperty(key.toString());
133                                 } else if (key.toString().endsWith(".pdps")) {
134                                         String pdpList = properties.getProperty(key.toString());
135                                         if (pdpList != null && pdpList.length() > 0) {
136                                                 for (String id : Splitter.on(',').omitEmptyStrings().trimResults().split(pdpList)) {
137                                                         StdPDP pdp = new StdPDP(id, properties);
138                                                         pdp.addItemSetChangeListener(this);
139                                                         this.pdps.add(pdp);
140                                                 }
141                                         }
142                                 }
143                         }
144                         // force all policies to have a name
145                         if (this.name == null) {
146                                 this.name = this.id;
147                         }
148                 }
149                 //
150                 // Validate our directory
151                 //
152                 if (Files.notExists(directory)) {
153                         logger.warn("Group directory does NOT exist: " + directory.toString());
154                         try {
155                                 Files.createDirectory(directory);
156                                 this.status.addLoadWarning("Group directory does NOT exist");
157                         } catch (IOException e) {
158                                 //TODO:EELF Cleanup - Remove logger
159                                 //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e);
160                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Group directory does NOT exist");
161                                 this.status.addLoadError("Group directory does NOT exist");
162                                 this.status.setStatus(PDPGroupStatus.Status.LOAD_ERRORS);
163                         }
164                 }
165                 //
166                 // Parse policies
167                 //
168                 this.loadPolicies(Paths.get(directory.toString(), "xacml.policy.properties"));
169                 //
170                 // Parse pip config
171                 //
172                 this.loadPIPConfig(Paths.get(directory.toString(), "xacml.pip.properties"));
173         }
174         
175         public void loadPolicies(Path file) throws PAPException {
176                 //
177                 // Read the Groups Policies
178                 //
179                 Properties policyProperties = new Properties();
180                 if ( ! file.toFile().exists()) {
181                         // need to create the properties file with default values
182                         policyProperties.setProperty(XACMLProperties.PROP_ROOTPOLICIES, "");
183                         policyProperties.setProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, "");
184                         // save properties to file
185                         try (OutputStream os = Files.newOutputStream(file)) {
186                                 policyProperties.store(os, "");
187                         } catch (Exception e) {
188                                 throw new PAPException("Failed to create new default policy properties file '" + file +"'");
189                         }
190                 } else {
191                         // load previously existing file
192                         try {
193                                 //
194                                 // Load the properties
195                                 //
196                                 try (InputStream is = Files.newInputStream(file)) {
197                                         policyProperties.load(is);
198                                 }
199                                 //
200                                 // Parse the policies
201                                 //
202                                 this.readPolicyProperties(directory, policyProperties);
203                         } catch (IOException e) {
204                                 logger.warn("Failed to load group policy properties file: " + file, e);
205                                 this.status.addLoadError("Not policy properties defined");
206                                 this.status.setStatus(Status.LOAD_ERRORS);
207                                 throw new PAPException("Failed to load group policy properties file: " + file);
208                         }
209                 }
210         }
211         
212         public void loadPIPConfig(Path file) throws PAPException {
213                 //
214                 // Read the Groups' PIP configuration
215                 //
216                 Properties pipProperties = new Properties();
217                 if ( ! file.toFile().exists()) {
218                         // need to create the properties file with no values
219                         // TODO: Adding Default PIP engine(s) while Loading initially. We don't want 
220                         // Programmer intervention with the PIP engines. 
221                         pipProperties = setPIPProperties(pipProperties);
222                         // save properties to file
223                         try {
224                                 try (OutputStream os = Files.newOutputStream(file)) {
225                                         pipProperties.store(os, "");
226                                 }
227                         } catch (Exception e) {
228                                 throw new PAPException("Failed to create new default pip properties file '" + file +"'");
229                         }
230                 } else {
231                         try {
232                                 //
233                                 // Load the properties
234                                 //
235                                 try (InputStream is = Files.newInputStream(file)) {
236                                         pipProperties.load(is);
237                                 }
238                                 // For all old PIP config's modify to the new PIP Configuration. 
239                                 // If PIP is empty add the new values and save it. 
240                                 if(pipProperties.get(XACMLProperties.PROP_PIP_ENGINES).toString().trim().equals("")){
241                                         pipProperties = setPIPProperties(pipProperties);
242                                         try (OutputStream os = Files.newOutputStream(file)) {
243                                                 pipProperties.store(os, "");
244                                         }
245                                 }
246                                 //
247                                 // Parse the pips
248                                 //
249                                 this.readPIPProperties(directory, pipProperties);
250                         } catch (IOException e) {
251                                 logger.warn("Failed to open group PIP Config properties file: " + file, e);
252                                 this.status.addLoadError("Not PIP config properties defined");
253                                 this.status.setStatus(Status.LOAD_ERRORS);
254                                 throw new PAPException("Failed to load group policy properties file: " + file);
255
256                         }
257                 }
258         }
259         
260         public void resetStatus() {
261 //              //
262 //              // If we are updating, don't allow reset
263 //              //
264 //              if (this.status.getStatus() == Status.UPDATING_CONFIGURATION) {
265 //                      logger.warn("We are updating, chill.");
266 //                      return;
267 //              }
268 //              //
269 //              // Load errors take precedence
270 //              //
271 //              if (this.status.getStatus() == Status.LOAD_ERRORS) {
272 //                      logger.warn("We had load errors.");
273 //                      return;
274 //              }
275                 //
276                 // Reset our status object
277                 //
278                 this.status.reset();
279                 //
280                 // Determine our status
281                 //
282                 for (PDP pdp : this.pdps) {
283                         switch (pdp.getStatus().getStatus()) {
284                         case OUT_OF_SYNCH:
285                                 this.status.addOutOfSynchPDP(pdp);
286                                 break;
287                         case LAST_UPDATE_FAILED:
288                                 this.status.addLastUpdateFailedPDP(pdp);
289                                 break;
290                         case LOAD_ERRORS:
291                                 this.status.addFailedPDP(pdp);
292                                 break;
293                         case UPDATING_CONFIGURATION:
294                                 this.status.addUpdatingPDP(pdp);
295                                 break;
296                         case UP_TO_DATE:
297                                 this.status.addInSynchPDP(pdp);
298                                 break;
299                         case UNKNOWN:
300                         case CANNOT_CONNECT:
301                         case NO_SUCH_HOST:
302                         default:
303                                 this.status.addUnknownPDP(pdp);
304                                 break;
305                         }
306                 }
307                 
308                 // priority is worst-cast to best case
309                 if (this.status.getUnknownPDPs().size() > 0) {
310                         this.status.setStatus(Status.UNKNOWN);
311                 } else if (this.status.getFailedPDPs().size() > 0 || this.status.getLastUpdateFailedPDPs().size() > 0) {
312                         this.status.setStatus(Status.LOAD_ERRORS);
313                 } else if (this.status.getOutOfSynchPDPs().size() > 0) {
314                         this.status.setStatus(Status.OUT_OF_SYNCH);
315                 } else if (this.status.getUpdatingPDPs().size() > 0) {
316                         this.status.setStatus(Status.UPDATING_CONFIGURATION);
317                 } else {
318                         this.status.setStatus(Status.OK); 
319                 }
320         }
321
322         @Override
323         public String getId() {
324                 return this.id;
325         }
326         
327         public void setId(String id) {
328                 this.id = id;
329         }
330
331         @Override
332         public boolean isDefaultGroup() {
333                 return this.isDefault;
334         }
335         
336         public void setDefaultGroup(boolean isDefault) {
337                 this.isDefault = isDefault;
338                 //
339                 // Cannot fire this because 2 operations have
340                 // to occur: 1) old default=false (don't want to fire) and
341                 // then 2) new default=true (yes fire - but we'll have to do that
342                 // elsewhere.
343                 //this.firePDPGroupChanged(this);
344         }
345
346         @Override
347         public String getName() {
348                 return name;
349         }
350
351         @Override
352         public void setName(String groupName) {
353                 this.name = groupName;
354                 this.firePDPGroupChanged(this);
355         }
356
357         @Override
358         public String getDescription() {
359                 return this.description;
360         }
361
362         @Override
363         public void setDescription(String groupDescription) {
364                 this.description = groupDescription;
365                 this.firePDPGroupChanged(this);
366         }
367         
368         public Path getDirectory() {
369                 return this.directory;
370         }
371
372         public void setDirectory(Path groupDirectory) {
373                 this.directory = groupDirectory;
374                 // this is used only for transmission on the RESTful interface, so no need to fire group changed?
375         }
376
377         @Override
378         public PDPGroupStatus getStatus()
379         {
380                 return this.status;
381         }
382         
383         @Override
384         public Set<PDP> getPdps() {
385                 return Collections.unmodifiableSet(pdps);
386         }
387
388         public void setEcompPdps(Set<EcompPDP> pdps) {
389                 this.pdps = pdps;
390         }
391         
392         public Set<EcompPDP> getEcompPdps(){
393                 return Collections.unmodifiableSet(pdps);
394         }
395         
396         public boolean addPDP(EcompPDP pdp) {
397                 return this.pdps.add(pdp);
398         }
399         
400         public boolean removePDP(PDP pdp) {
401                 return this.pdps.remove(pdp);
402         }
403
404         @Override
405         public Set<PDPPolicy> getPolicies() {
406                 return Collections.unmodifiableSet(this.policies);
407         }
408
409         @Override
410         public PDPPolicy getPolicy(String id) {
411                 for (PDPPolicy policy : this.policies) {
412                         if (policy.getId().equals(id)) {
413                                 return policy;
414                         }
415                 }
416                 return null;
417         }
418
419         public Properties getPolicyProperties()
420         {
421                 Properties properties = new Properties(){
422                         private static final long serialVersionUID = 1L;
423                         // For Debugging it is helpful for the file to be in a sorted order,
424                         // any by returning the keys in the natural Alpha order for strings we get close enough.
425                         // TreeSet is sorted, and this just overrides the normal Properties method to get the keys.
426                         @Override
427                     public synchronized Enumeration<Object> keys() {
428                         return Collections.enumeration(new TreeSet<Object>(super.keySet()));
429                     }
430             };;
431                 List<String> roots = new ArrayList<String>();
432                 List<String> refs = new ArrayList<String>();
433                 
434                 for (PDPPolicy policy : this.policies) {
435                         // for all policies need to tell PDP the "name", which is the base name for the file id
436                         if (policy.getName() != null) {
437                                 properties.setProperty(policy.getId() + ".name", policy.getName());
438                         }
439                         // put the policy on the correct list
440                         if (policy.isRoot()) {
441                                 roots.add(policy.getId());
442                         } else {
443                                 refs.add(policy.getId());
444                         }
445                 }
446                 
447                 properties.setProperty(XACMLProperties.PROP_ROOTPOLICIES, Joiner.on(',').join(roots));
448                 properties.setProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, Joiner.on(',').join(refs));
449         
450                 return properties;
451         }
452         
453         public PDPPolicy publishPolicy(String id, String name, boolean isRoot, InputStream policy) throws PAPException {
454                 //
455                 // Does it exist already?
456                 //
457                 if (this.getPolicy(id) != null) {
458                         throw new PAPException("Policy with id " + id + " already exists - unpublish it first.");
459                 }
460                 Path tempFile = null;
461                 try {
462                         //
463                         // Copy the policy over
464                         //
465                         tempFile = Files.createFile(Paths.get(this.directory.toAbsolutePath().toString(), id));
466                         long num;
467                         try (OutputStream os = Files.newOutputStream(tempFile)) {
468                                 num = ByteStreams.copy(policy, os);
469                         }
470                         logger.info("Copied " + num + " bytes for policy " + name);
471                         
472                         StdPDPPolicy tempRootPolicy = new StdPDPPolicy(id, isRoot, name, tempFile.toUri());
473                         if (tempRootPolicy.isValid() == false) {
474                                 try {
475                                         Files.delete(tempFile);
476                                 } catch(Exception ee) {
477                                         //TODO:EELF Cleanup - Remove logger
478                                         //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Policy was invalid, could NOT delete it.", ee);
479                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, ee, "StdPDPGroup", "Policy was invalid, could NOT delete it.");
480                                 }
481                                 throw new PAPException("Policy is invalid");
482                         }
483                         //
484                         // Add it in
485                         //
486                         this.policies.add(tempRootPolicy);
487                         //
488                         // We are changed
489                         //
490                         this.firePDPGroupChanged(this);
491                         //
492                         // Return our new object.
493                         //
494                         return tempRootPolicy;
495                 } catch (IOException e) {
496                         //TODO:EELF Cleanup - Remove logger
497                         //logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to publishPolicy: ", e);
498                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "StdPDPGroup", "Failed to publishPolicy");
499                 }
500                 return null;
501         }
502         
503         /**
504          * Copy one policy file into the Group's directory but do not change the configuration.
505          * This is one part of a multi-step process of publishing policies.
506          * There may be multiple changes in the group (adding multiple policies, deleting policies, changine root<->referenced)
507          * that must be done all at once, so we just copy the file in preparation for a later "update whole group" operation.
508          * 
509          * @param id
510          * @param name
511          * @param isRoot
512          * @param policy
513          * @return
514          * @throws PAPException
515          */
516         public void copyPolicyToFile(String id,  InputStream policy) throws PAPException {
517                 try {
518                         //
519                         // Copy the policy over
520                         //
521                         long num;
522                         Path policyFilePath = Paths.get(this.directory.toAbsolutePath().toString(), id);
523                         
524                         //
525                         // THERE IS A WEIRD PROBLEM ON WINDOWS...
526                         // The file is already "in use" when we try to access it.  
527                         // Looking at the file externally while this is halted here does not show the file in use,
528                         // so there is no indication what is causing the problem.
529                         //
530                         // As a way to by-pass the issue, I simply check if the input and the existing file are identical
531                         // and generate an exception if they are not.
532                         //
533                         
534
535                         
536 //                      if (Files.exists(policyFilePath)) {
537 //                              // compare the 
538 //                              String incomingPolicyString = null;
539 //                              try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
540 //                                      num = ByteStreams.copy(policy, os);
541 //                                      incomingPolicyString = new String(os.toByteArray(), "UTF-8"); 
542 //                              }
543 //                              String existingPolicyString = null;
544 //                              try {
545 //                                      byte[] bytes =  Files.readAllBytes(policyFilePath);
546 //                                      existingPolicyString = new String(bytes, "UTF-8"); 
547 //                              } catch (Exception e) {
548 //                                      //TODO:EELF Cleanup - Remove logger
549 //                                      logger.error("Unable to read existing file '" + policyFilePath + "': " + e, e);
550 //                                      PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "StdPDPGroup", "Unable to read existing policy file");
551 //                                      throw new PAPException("Unable to read policy file for comparison: " + e);
552 //                              }
553 //                              if (incomingPolicyString.equals(existingPolicyString)) {
554 //                                      throw new PAPException("Policy '" + policyFilePath + "' does not match existing policy on server");
555 //                              }
556 //                              // input is same as existing file
557 //                              return;
558 //                      }
559                         
560                         
561                         Path policyFile;
562                         if (Files.exists(policyFilePath)) {
563                                 policyFile = policyFilePath;
564                         } else {
565                                 policyFile = Files.createFile(policyFilePath);
566                         }
567
568                         try (OutputStream os = Files.newOutputStream(policyFile)) {
569                                 num = ByteStreams.copy(policy, os);
570                         }
571                         
572                         logger.info("Copied " + num + " bytes for policy " + name);
573
574                         for (PDPPolicy p : policies) {
575                                 if (p.getId().equals(id)) {
576                                         // we just re-copied/refreshed/updated the policy file for a policy that already exists in this group
577                                         logger.info("Policy '" + id + "' already exists in group '" + getId() + "'");
578                                         return;
579                                 }
580                         }
581                         
582                         // policy is new to this group
583                         StdPDPPolicy tempRootPolicy = new StdPDPPolicy(id, true, name, policyFile.toUri());
584                         if (tempRootPolicy.isValid() == false) {
585                                 try {
586                                         Files.delete(policyFile);
587                                 } catch(Exception ee) {
588                                         //TODO:EELF Cleanup - Remove logger
589                                         //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Policy was invalid, could NOT delete it.", ee);
590                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, ee, "StdPDPGroup", "Policy was invalid, could NOT delete it.");
591                                 }
592                                 throw new PAPException("Policy is invalid");
593                         }
594                         //
595                         // Add it in
596                         //
597                         this.policies.add(tempRootPolicy);
598                         //
599                         // We are changed
600                         //
601                         this.firePDPGroupChanged(this);
602                         
603                         
604                         
605                         
606                 } catch (IOException e) {
607                         //TODO:EELF Cleanup - Remove logger
608                         //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Failed to copyPolicyToFile: ", e);
609                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to copyPolicyToFile");
610                         throw new PAPException("Failed to copy policy to file: " + e);
611                 }
612                 return;
613         }
614         
615         public boolean removePolicyFromGroup(PDPPolicy policy) {
616                 StdPDPPolicy currentPolicy = (StdPDPPolicy) this.getPolicy(policy.getId());
617                 if (currentPolicy == null) {
618                         //TODO:EELF Cleanup - Remove logger
619                         //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Policy " + policy.getId() + " does not exist.");
620                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + "Policy " + policy.getId() + " does not exist.");
621                         return false;
622                 }
623                 try {
624                         //
625                         // Remove it from our list
626                         //
627                         this.policies.remove(currentPolicy);
628                         //
629                         // We are changed
630                         //
631                         this.firePDPGroupChanged(this);
632                         return true;
633                 } catch (Exception e) {
634                         //TODO:EELF Cleanup - Remove logger
635                         //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Failed to delete policy " + policy);
636                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to delete policy");
637                 }
638                 return false;
639         }
640         
641         public boolean removePolicy(PDPPolicy policy) {
642                 StdPDPPolicy currentPolicy = (StdPDPPolicy) this.getPolicy(policy.getId());
643                 if (currentPolicy == null) {
644                         //TODO:EELF Cleanup - Remove logger
645                         //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Policy " + policy.getId() + " does not exist.");
646                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + "Policy " + policy.getId() + " does not exist.");
647                         return false;
648                 }
649                 try {
650                         //
651                         // Delete it on disk
652                         //
653                         Files.delete(Paths.get(currentPolicy.getLocation()));
654                         //
655                         // Remove it from our list
656                         //
657                         this.policies.remove(currentPolicy);
658                         //
659                         // We are changed
660                         //
661                         this.firePDPGroupChanged(this);
662                         return true;
663                 } catch (Exception e) {
664                         //TODO:EELF Cleanup - Remove logger
665                         //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Failed to delete policy " + policy);
666                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to delete policy " + policy);
667                 }
668                 return false;
669         }
670
671         @Override
672         public Set<PDPPIPConfig> getPipConfigs() {
673                 return Collections.unmodifiableSet(this.pipConfigs);
674         }
675
676         @Override
677         public PDPPIPConfig getPipConfig(String id) {
678                 for (PDPPIPConfig config : this.pipConfigs) {
679                         if (config.getId().equals(id)) {
680                                 return config;
681                         }
682                 }
683                 return null;
684         }
685         
686         public void setPipConfigs(Set<PDPPIPConfig> pipConfigs) {
687                 this.pipConfigs = pipConfigs;
688                 this.firePDPGroupChanged(this);
689         }
690         
691         public void removeAllPIPConfigs() {
692                 this.pipConfigs.clear();
693                 this.firePDPGroupChanged(this);
694         }
695         
696         public Properties getPipConfigProperties() {
697                 Properties properties = new Properties();
698                 List<String> configs = new ArrayList<String>();
699                 
700                 for (PDPPIPConfig config : this.pipConfigs) {
701                         configs.add(config.getId());
702                         properties.putAll(config.getConfiguration());
703                 }
704                 
705                 properties.setProperty(XACMLProperties.PROP_PIP_ENGINES, Joiner.on(',').join(configs));
706
707                 return properties;
708         }
709
710         @Override
711         public void repair() {
712                 //
713                 // Reset the status object
714                 //
715                 this.status.reset();
716                 //
717                 // Validate our directory
718                 //
719                 boolean fire = false;
720                 if (Files.notExists(directory)) {
721                         logger.warn("Group directory does NOT exist: " + directory.toString());
722                         try {
723                                 Files.createDirectory(directory);
724                                 fire = true;
725                                 this.status.addLoadWarning("Created missing group directory");
726                         } catch (IOException e) {
727                                 //TODO:EELF Cleanup - Remove logger
728                                 //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e);
729                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to create missing Group directory.");
730                                 this.status.addLoadError("Failed to create missing Group directory.");
731                                 this.status.setStatus(PDPGroupStatus.Status.LOAD_ERRORS);
732                         }
733                 }
734                 //
735                 // Validate our PIP config file
736                 //
737                 Path pipPropertiesFile = Paths.get(directory.toString(), "xacml.pip.properties");
738                 if (Files.notExists(pipPropertiesFile)) {
739                         try {
740                                 Files.createFile(pipPropertiesFile);
741                                 fire = true;
742                                 this.status.addLoadWarning("Created missing PIP properties file");
743                         } catch (IOException e) {
744                                 //TODO:EELF Cleanup - Remove logger
745                                 //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e);
746                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to create missing PIP properties file");
747                                 this.status.addLoadError("Failed to create missing PIP properties file");
748                                 this.status.setStatus(PDPGroupStatus.Status.LOAD_ERRORS);
749                         }
750                 }
751                 //
752                 // Valid our policy properties file
753                 //
754                 Path policyPropertiesFile = Paths.get(directory.toString(), "xacml.policy.properties");
755                 if (Files.notExists(policyPropertiesFile)) {
756                         try {
757                                 Files.createFile(policyPropertiesFile);
758                                 fire = true;
759                                 this.status.addLoadWarning("Created missing Policy properties file");
760                         } catch (IOException e) {
761                                 //TODO:EELF Cleanup - Remove logger
762                                 //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e);
763                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to create missing Policy properties file");
764                                 this.status.addLoadError("Failed to create missing Policy properties file");
765                                 this.status.setStatus(PDPGroupStatus.Status.LOAD_ERRORS);
766                         }
767                 }
768                 this.resetStatus();
769                 if (fire) {
770                         this.fireChanged();
771                 }
772         }
773
774         private void    readPolicyProperties(Path directory, Properties properties) {
775                 //
776                 // There are 2 property values that hold policies, root and referenced
777                 //
778                 String[] lists = new String[2];
779                 lists[0] = properties.getProperty(XACMLProperties.PROP_ROOTPOLICIES);
780                 lists[1] = properties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES);
781                 //
782                 // Iterate each policy list
783                 //
784                 boolean isRoot = true;
785                 for (String list : lists) {
786                         //
787                         // Was there actually a property?
788                         //
789                         if (list == null || list.length() == 0) {
790                                 isRoot = false;
791                                 continue;
792                         }
793                         //
794                         // Parse it out
795                         //
796                         Iterable<String> policyList = Splitter.on(',').trimResults().omitEmptyStrings().split(list);
797                         //
798                         // Was there actually a list
799                         //
800                         if (policyList == null) {
801                                 isRoot = false;
802                                 continue;
803                         }
804                         for (String id : policyList) {
805                                 //
806                                 // Construct the policy filename
807                                 //
808                                 Path policyPath = Paths.get(directory.toString(), id );
809                                 //
810                                 // Create the Policy Object
811                                 //
812                                 StdPDPPolicy policy;
813                                 try {
814                                         policy = new StdPDPPolicy(id, isRoot, policyPath.toUri(), properties);
815                                 } catch (IOException e) {
816                                         //TODO:EELF Cleanup - Remove logger
817                                         //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Failed to create policy object", e);
818                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to create policy object");
819                                         policy = null;
820                                 }
821                                 //
822                                 // Is it valid?
823                                 //
824                                 if (policy != null && policy.isValid()) {
825                                         this.policies.add(policy);
826                                         this.status.addLoadedPolicy(policy);
827                                 } else {
828                                         this.status.addFailedPolicy(policy);
829                                         this.status.setStatus(Status.LOAD_ERRORS);
830                                 }
831                                 // force all policies to have a name
832                                 if (policy.getName() == null) {
833                                         policy.setName(policy.getId());
834                                 }
835                         }
836                         isRoot = false;
837                 }
838         }
839
840         private void    readPIPProperties(Path directory, Properties properties) {
841                 String list = properties.getProperty(XACMLProperties.PROP_PIP_ENGINES);
842                 if (list == null || list.length() == 0) {
843                         return;
844                 }
845                 for (String id : list.split("[,]")) {
846                         StdPDPPIPConfig config = new StdPDPPIPConfig(id, properties);
847                         if (config.isConfigured()) {
848                                 this.pipConfigs.add(config);
849                                 this.status.addLoadedPipConfig(config);
850                         } else {
851                                 this.status.addFailedPipConfig(config);
852                                 this.status.setStatus(Status.LOAD_ERRORS);
853                         }
854                 }
855         }
856
857         @Override
858         public int hashCode() {
859                 final int prime = 31;
860                 int result = 1;
861                 result = prime * result + ((id == null) ? 0 : id.hashCode());
862                 return result;
863         }
864
865         @Override
866         public boolean equals(Object obj) {
867                 if (this == obj)
868                         return true;
869                 if (obj == null)
870                         return false;
871                 if (getClass() != obj.getClass())
872                         return false;
873                 StdPDPGroup other = (StdPDPGroup) obj;
874                 if (id == null) {
875                         if (other.id != null)
876                                 return false;
877                 } else if (!id.equals(other.id))
878                         return false;
879                 return true;
880         }
881
882         @Override
883         public String toString() {
884                 return "StdPDPGroup [id=" + id + ", isDefault=" + isDefault + ", name="
885                                 + name + ", description=" + description + ", status=" + status
886                                 + ", pdps=" + pdps + ", policies=" + policies + ", pipConfigs="
887                                 + pipConfigs + ", directory=" + directory + "]";
888         }
889
890         @Override
891         public void changed() {
892
893                 // save the (changed) properties
894                 try {
895                         saveGroupConfiguration();
896                 } catch (PAPException | IOException e) {
897                         //TODO:EELF Cleanup - Remove logger
898                         //logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Unable to save group configuration change");
899                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "StdPDPGroup", "Unable to save group configuration change");
900                         // don't notify other things of change if we cannot save it???
901                         return;
902                 }
903                 
904                 this.firePDPGroupChanged(this);
905
906         }
907
908         @Override
909         public void groupChanged(EcompPDPGroup group) {
910                 this.changed();
911         }
912
913         @Override
914         public void pdpChanged(EcompPDP pdp) {
915                 //
916                 // If one of the group's PDP's changed, then the group changed
917                 //
918                 // TODO Really?
919                 //
920                 this.changed();
921         }
922
923         
924         //
925         // Methods needed for JSON deserialization
926         //
927         public StdPDPGroup() {
928                 
929         }
930         
931         public StdPDPGroup(EcompPDPGroup group) {
932                 this.id = group.getId();
933                 this.name = group.getName();
934                 this.description = group.getDescription();
935                 this.isDefault = group.isDefaultGroup();
936                 this.pdps = group.getEcompPdps();
937                 this.policies = group.getPolicies();
938                 this.pipConfigs = group.getPipConfigs();
939         }
940
941         public boolean isDefault() {
942                 return isDefault;
943         }
944         public void setDefault(boolean isDefault) {
945                 this.isDefault = isDefault;
946         }
947         public void setStatus(PDPGroupStatus status) {
948                 this.status = new StdPDPGroupStatus(status);
949         }
950         public void setPolicies(Set<PDPPolicy> policies) {
951                 this.policies = policies;
952         }
953
954         
955         
956         public void saveGroupConfiguration() throws PAPException, IOException {
957                 
958                 // First save the Policy properties
959                 
960                 // save the lists of policies
961                 Properties policyProperties = this.getPolicyProperties();
962                 
963                 // save info about each policy
964                 for (PDPPolicy policy : this.policies){
965                         policyProperties.put(policy.getId() + ".name", policy.getName());
966                 }
967
968                 //
969                 // Now we can save the file
970                 //
971                 Path file = Paths.get(this.directory.toString(), "xacml.policy.properties");
972                 try (OutputStream os = Files.newOutputStream(file)) {
973                         policyProperties.store(os, "");
974                 } catch (Exception e) {
975                         //TODO:EELF Cleanup - Remove logger
976                         //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Group Policies Config save failed: " + e, e);
977                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "STdPDPGroup", "Group Policies Config save failed");
978                         throw new PAPException("Failed to save policy properties file '" + file +"'");
979                 }
980                 
981                                 
982                 // Now save the PIP Config properties
983                 Properties pipProperties = this.getPipConfigProperties();
984
985                 //
986                 // Now we can save the file
987                 //
988                 file = Paths.get(this.directory.toString(), "xacml.pip.properties");
989                 try (OutputStream os = Files.newOutputStream(file)) {
990                         pipProperties.store(os, "");
991                 } catch (Exception e) {
992                         //TODO:EELF Cleanup - Remove logger
993                         //logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Group PIP Config save failed: " + e, e);
994                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Group PIP Config save failed");
995                         throw new PAPException("Failed to save pip properties file '" + file +"'");
996                 }
997         }
998
999         //
1000         // Comparable Interface
1001         //
1002         @Override
1003         public int compareTo(Object arg0) {
1004                 if (arg0 == null) {
1005                         return -1;
1006                 }
1007                 if ( ! (arg0 instanceof StdPDPGroup)) {
1008                         return -1;
1009                 }
1010                 if (((StdPDPGroup)arg0).name == null) {
1011                         return -1;
1012                 }
1013                 if (name == null) {
1014                         return 1;
1015                 }
1016
1017                 return name.compareTo(((StdPDPGroup)arg0).name);
1018         }
1019         
1020         // TODO: Adding Default PIP engine(s) while Loading initially. We don't want 
1021         //                      Programmer intervention with the PIP engines. 
1022         private Properties setPIPProperties(Properties props){
1023                 props.setProperty("AAF.name", "AAFEngine");
1024                 props.setProperty("AAF.description", "AAFEngine to communicate with AAF to take decisions");
1025                 props.setProperty("AAF.classname","org.openecomp.policy.xacml.std.pip.engines.aaf.AAFEngine");
1026                 props.setProperty(XACMLProperties.PROP_PIP_ENGINES, "AAF");
1027                 return props;
1028         }
1029
1030
1031 }