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