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