Policy 1707 commit to LF
[policy/engine.git] / ECOMP-XACML / src / main / java / org / openecomp / policy / xacml / std / pap / StdPDPGroup.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ECOMP-XACML
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.openecomp.policy.xacml.std.pap;
21
22 import 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.openecomp.policy.common.logging.eelf.MessageCodes;
42 import org.openecomp.policy.common.logging.eelf.PolicyLogger;
43 import org.openecomp.policy.xacml.api.XACMLErrorConstants;
44 import org.openecomp.policy.xacml.api.pap.EcompPDP;
45 import org.openecomp.policy.xacml.api.pap.EcompPDPGroup;
46 import org.openecomp.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 EcompPDPGroup, StdItemSetChangeListener, Comparable<Object>, Serializable {
62         private static final long serialVersionUID = 1L;
63         private static Log      logger  = LogFactory.getLog(StdPDPGroup.class);
64         
65         private String id;
66         
67         private boolean isDefault = false;
68         
69         private String name;
70         
71         private String description;
72         
73         private StdPDPGroupStatus status = new StdPDPGroupStatus(Status.UNKNOWN);
74         
75         private Set<EcompPDP>   pdps = new HashSet<EcompPDP>();
76         
77         private Set<PDPPolicy> policies = new HashSet<PDPPolicy>();
78         
79         private Set<PDPPolicy> selectedPolicies = new HashSet<PDPPolicy>();
80         
81         private Set<PDPPIPConfig> pipConfigs = new HashSet<PDPPIPConfig>();
82         
83         private String operation;
84         
85         @JsonIgnore
86         private  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 +"'");
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 +"'");
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");
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 setEcompPdps(Set<EcompPDP> pdps) {
404                 this.pdps = pdps;
405         }
406         
407         public Set<EcompPDP> getEcompPdps(){
408                 return Collections.unmodifiableSet(pdps);
409         }
410         
411         public boolean addPDP(EcompPDP 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                 StdPDPPolicy currentPolicy = (StdPDPPolicy) this.getPolicy(policy.getId());
646                 if (currentPolicy == null) {
647                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + "Policy " + policy.getId() + " does not exist.");
648                         return false;
649                 }
650                 try {
651                         //
652                         // Remove it from our list
653                         //
654                         this.policies.remove(currentPolicy);
655                         //
656                         // We are changed
657                         //
658                         this.firePDPGroupChanged(this);
659                         return true;
660                 } catch (Exception e) {
661                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to delete policy");
662                 }
663                 return false;
664         }
665         
666         public boolean removePolicy(PDPPolicy policy) {
667                 StdPDPPolicy currentPolicy = (StdPDPPolicy) this.getPolicy(policy.getId());
668                 if (currentPolicy == null) {
669                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + "Policy " + policy.getId() + " does not exist.");
670                         return false;
671                 }
672                 try {
673                         //
674                         // Delete it on disk
675                         //
676                         Files.delete(Paths.get(currentPolicy.getLocation()));
677                         //
678                         // Remove it from our list
679                         //
680                         this.policies.remove(currentPolicy);
681                         //
682                         // We are changed
683                         //
684                         this.firePDPGroupChanged(this);
685                         return true;
686                 } catch (Exception e) {
687                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to delete policy " + policy);
688                 }
689                 return false;
690         }
691
692         @Override
693         public Set<PDPPIPConfig> getPipConfigs() {
694                 return Collections.unmodifiableSet(this.pipConfigs);
695         }
696
697         @Override
698         public PDPPIPConfig getPipConfig(String id) {
699                 for (PDPPIPConfig config : this.pipConfigs) {
700                         if (config.getId().equals(id)) {
701                                 return config;
702                         }
703                 }
704                 return null;
705         }
706         
707         public void setPipConfigs(Set<PDPPIPConfig> pipConfigs) {
708                 this.pipConfigs = pipConfigs;
709                 this.firePDPGroupChanged(this);
710         }
711         
712         public void removeAllPIPConfigs() {
713                 this.pipConfigs.clear();
714                 this.firePDPGroupChanged(this);
715         }
716         
717         public Properties getPipConfigProperties() {
718                 Properties properties = new Properties();
719                 List<String> configs = new ArrayList<String>();
720                 
721                 for (PDPPIPConfig config : this.pipConfigs) {
722                         configs.add(config.getId());
723                         properties.putAll(config.getConfiguration());
724                 }
725                 
726                 properties.setProperty(XACMLProperties.PROP_PIP_ENGINES, Joiner.on(',').join(configs));
727
728                 return properties;
729         }
730
731         @Override
732         public void repair() {
733                 //
734                 // Reset the status object
735                 //
736                 this.status.reset();
737                 //
738                 // Validate our directory
739                 //
740                 boolean fire = false;
741                 if (Files.notExists(directory)) {
742                         logger.warn("Group directory does NOT exist: " + directory.toString());
743                         try {
744                                 Files.createDirectory(directory);
745                                 fire = true;
746                                 this.status.addLoadWarning("Created missing group directory");
747                         } catch (IOException e) {
748                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to create missing Group directory.");
749                                 this.status.addLoadError("Failed to create missing Group directory.");
750                                 this.status.setStatus(PDPGroupStatus.Status.LOAD_ERRORS);
751                         }
752                 }
753                 //
754                 // Validate our PIP config file
755                 //
756                 Path pipPropertiesFile = Paths.get(directory.toString(), "xacml.pip.properties");
757                 if (Files.notExists(pipPropertiesFile)) {
758                         try {
759                                 Files.createFile(pipPropertiesFile);
760                                 fire = true;
761                                 this.status.addLoadWarning("Created missing PIP properties file");
762                         } catch (IOException e) {
763                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to create missing PIP properties file");
764                                 this.status.addLoadError("Failed to create missing PIP properties file");
765                                 this.status.setStatus(PDPGroupStatus.Status.LOAD_ERRORS);
766                         }
767                 }
768                 //
769                 // Valid our policy properties file
770                 //
771                 Path policyPropertiesFile = Paths.get(directory.toString(), "xacml.policy.properties");
772                 if (Files.notExists(policyPropertiesFile)) {
773                         try {
774                                 Files.createFile(policyPropertiesFile);
775                                 fire = true;
776                                 this.status.addLoadWarning("Created missing Policy properties file");
777                         } catch (IOException e) {
778                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to create missing Policy properties file");
779                                 this.status.addLoadError("Failed to create missing Policy properties file");
780                                 this.status.setStatus(PDPGroupStatus.Status.LOAD_ERRORS);
781                         }
782                 }
783                 this.resetStatus();
784                 if (fire) {
785                         this.fireChanged();
786                 }
787         }
788
789         private void    readPolicyProperties(Path directory, Properties properties) {
790                 //
791                 // There are 2 property values that hold policies, root and referenced
792                 //
793                 String[] lists = new String[2];
794                 lists[0] = properties.getProperty(XACMLProperties.PROP_ROOTPOLICIES);
795                 lists[1] = properties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES);
796                 //
797                 // Iterate each policy list
798                 //
799                 boolean isRoot = true;
800                 for (String list : lists) {
801                         //
802                         // Was there actually a property?
803                         //
804                         if (list == null || list.length() == 0) {
805                                 isRoot = false;
806                                 continue;
807                         }
808                         //
809                         // Parse it out
810                         //
811                         Iterable<String> policyList = Splitter.on(',').trimResults().omitEmptyStrings().split(list);
812                         //
813                         // Was there actually a list
814                         //
815                         if (policyList == null) {
816                                 isRoot = false;
817                                 continue;
818                         }
819                         for (String id : policyList) {
820                                 //
821                                 // Construct the policy filename
822                                 //
823                                 Path policyPath = Paths.get(directory.toString(), id );
824                                 //
825                                 // Create the Policy Object
826                                 //
827                                 StdPDPPolicy policy;
828                                 try {
829                                         policy = new StdPDPPolicy(id, isRoot, policyPath.toUri(), properties);
830                                 } catch (IOException e) {
831                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Failed to create policy object");
832                                         policy = null;
833                                 }
834                                 //
835                                 // Is it valid?
836                                 //
837                                 if (policy != null && policy.isValid()) {
838                                         this.policies.add(policy);
839                                         this.status.addLoadedPolicy(policy);
840                                 } else {
841                                         this.status.addFailedPolicy(policy);
842                                         this.status.setStatus(Status.LOAD_ERRORS);
843                                 }
844                                 // force all policies to have a name
845                                 if (policy!=null && policy.getName() == null) {
846                                         policy.setName(policy.getId());
847                                 }
848                         }
849                         isRoot = false;
850                 }
851         }
852
853         private void    readPIPProperties(Path directory, Properties properties) {
854                 String list = properties.getProperty(XACMLProperties.PROP_PIP_ENGINES);
855                 if (list == null || list.length() == 0) {
856                         return;
857                 }
858                 for (String id : list.split("[,]")) {
859                         StdPDPPIPConfig config = new StdPDPPIPConfig(id, properties);
860                         if (config.isConfigured()) {
861                                 this.pipConfigs.add(config);
862                                 this.status.addLoadedPipConfig(config);
863                         } else {
864                                 this.status.addFailedPipConfig(config);
865                                 this.status.setStatus(Status.LOAD_ERRORS);
866                         }
867                 }
868         }
869
870         @Override
871         public int hashCode() {
872                 final int prime = 31;
873                 int result = 1;
874                 result = prime * result + ((id == null) ? 0 : id.hashCode());
875                 return result;
876         }
877
878         @Override
879         public boolean equals(Object obj) {
880                 if (this == obj)
881                         return true;
882                 if (obj == null)
883                         return false;
884                 if (getClass() != obj.getClass())
885                         return false;
886                 StdPDPGroup other = (StdPDPGroup) obj;
887                 if (id == null) {
888                         if (other.id != null)
889                                 return false;
890                 } else if (!id.equals(other.id))
891                         return false;
892                 return true;
893         }
894
895         @Override
896         public String toString() {
897                 return "StdPDPGroup [id=" + id + ", isDefault=" + isDefault + ", name="
898                                 + name + ", description=" + description + ", status=" + status
899                                 + ", pdps=" + pdps + ", policies=" + policies + ", pipConfigs="
900                                 + pipConfigs + ", directory=" + directory + ",selectedPolicies=" 
901                                                 + selectedPolicies + ",operation=" + operation + "]";
902         }
903
904         @Override
905         public void changed() {
906
907                 // save the (changed) properties
908                 try {
909                         saveGroupConfiguration();
910                 } catch (PAPException | IOException e) {
911                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "StdPDPGroup", "Unable to save group configuration change");
912                         // don't notify other things of change if we cannot save it???
913                         return;
914                 }
915                 
916                 this.firePDPGroupChanged(this);
917
918         }
919
920         @Override
921         public void groupChanged(EcompPDPGroup group) {
922                 this.changed();
923         }
924
925         @Override
926         public void pdpChanged(EcompPDP pdp) {
927                 //
928                 // If one of the group's PDP's changed, then the group changed
929                 //
930                 this.changed();
931         }
932
933         
934         //
935         // Methods needed for JSON deserialization
936         //
937         public StdPDPGroup() {
938                 
939         }
940         
941         public StdPDPGroup(EcompPDPGroup group) {
942                 this.id = group.getId();
943                 this.name = group.getName();
944                 this.description = group.getDescription();
945                 this.isDefault = group.isDefaultGroup();
946                 this.pdps = group.getEcompPdps();
947                 this.policies = group.getPolicies();
948                 this.pipConfigs = group.getPipConfigs();
949         }
950
951         public boolean isDefault() {
952                 return isDefault;
953         }
954         public void setDefault(boolean isDefault) {
955                 this.isDefault = isDefault;
956         }
957         public void setStatus(PDPGroupStatus status) {
958                 this.status = new StdPDPGroupStatus(status);
959         }
960         public void setPolicies(Set<PDPPolicy> policies) {
961                 this.policies = policies;
962         }
963         public void setSelectedPolicies(Set<PDPPolicy> selectedPolicies) {
964                 this.selectedPolicies = selectedPolicies;
965         }
966         public void setOperation(String operation) {
967                 this.operation = operation;
968         }
969         
970         public void saveGroupConfiguration() throws PAPException, IOException {
971                 
972                 // First save the Policy properties
973                 
974                 // save the lists of policies
975                 Properties policyProperties = this.getPolicyProperties();
976                 
977                 // save info about each policy
978                 for (PDPPolicy policy : this.policies){
979                         policyProperties.put(policy.getId() + ".name", policy.getName());
980                 }
981
982                 //
983                 // Now we can save the file
984                 //
985                 Path file = Paths.get(this.directory.toString(), "xacml.policy.properties");
986                 try (OutputStream os = Files.newOutputStream(file)) {
987                         policyProperties.store(os, "");
988                 } catch (Exception e) {
989                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "STdPDPGroup", "Group Policies Config save failed");
990                         throw new PAPException("Failed to save policy properties file '" + file +"'");
991                 }
992                 
993                                 
994                 // Now save the PIP Config properties
995                 Properties pipProperties = this.getPipConfigProperties();
996
997                 //
998                 // Now we can save the file
999                 //
1000                 file = Paths.get(this.directory.toString(), "xacml.pip.properties");
1001                 try (OutputStream os = Files.newOutputStream(file)) {
1002                         pipProperties.store(os, "");
1003                 } catch (Exception e) {
1004                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdPDPGroup", "Group PIP Config save failed");
1005                         throw new PAPException("Failed to save pip properties file '" + file +"'");
1006                 }
1007         }
1008
1009         //
1010         // Comparable Interface
1011         //
1012         @Override
1013         public int compareTo(Object arg0) {
1014                 if (arg0 == null) {
1015                         return -1;
1016                 }
1017                 if ( ! (arg0 instanceof StdPDPGroup)) {
1018                         return -1;
1019                 }
1020                 if (((StdPDPGroup)arg0).name == null) {
1021                         return -1;
1022                 }
1023                 if (name == null) {
1024                         return 1;
1025                 }
1026
1027                 return name.compareTo(((StdPDPGroup)arg0).name);
1028         }
1029         
1030         //Adding Default PIP engine(s) while Loading initially. We don't want 
1031         //                      Programmer intervention with the PIP engines. 
1032         private Properties setPIPProperties(Properties props){
1033                 props.setProperty("AAF.name", "AAFEngine");
1034                 props.setProperty("AAF.description", "AAFEngine to communicate with AAF to take decisions");
1035                 props.setProperty("AAF.classname","org.openecomp.policy.xacml.std.pip.engines.aaf.AAFEngine");
1036                 props.setProperty(XACMLProperties.PROP_PIP_ENGINES, "AAF");
1037                 // read from PIP properties file. 
1038                 Path file = Paths.get(StdEngine.pipPropertyFile);
1039                 if (!Files.notExists(file)) {
1040                         InputStream in;
1041                         Properties prop = new Properties();
1042                         try {
1043                                 in = new FileInputStream(file.toFile());
1044                                 prop.load(in);
1045                         } catch (IOException e) {
1046                                 PolicyLogger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "can not load the pip properties from file" +e);
1047                         }
1048                         props = prop;
1049                 }
1050                 return props;
1051         }
1052
1053
1054 }