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