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