2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 package org.openecomp.policy.xacml.std.pap;
22 import java.io.FileInputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.nio.file.FileVisitResult;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import java.nio.file.SimpleFileVisitor;
31 import java.nio.file.attribute.BasicFileAttributes;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.Enumeration;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Properties;
39 import java.util.TreeSet;
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.openecomp.policy.common.logging.eelf.MessageCodes;
44 import org.openecomp.policy.common.logging.eelf.PolicyLogger;
45 import org.openecomp.policy.xacml.api.XACMLErrorConstants;
46 import org.openecomp.policy.xacml.api.pap.EcompPDP;
47 import org.openecomp.policy.xacml.api.pap.EcompPDPGroup;
48 import org.openecomp.policy.xacml.api.pap.PAPPolicyEngine;
50 import com.att.research.xacml.api.pap.PAPException;
51 import com.att.research.xacml.api.pap.PDP;
52 import com.att.research.xacml.api.pap.PDPGroup;
53 import com.att.research.xacml.api.pap.PDPPIPConfig;
54 import com.att.research.xacml.api.pap.PDPPolicy;
55 import com.att.research.xacml.api.pap.PDPStatus;
56 import com.att.research.xacml.util.XACMLProperties;
57 import com.google.common.base.Joiner;
58 import com.google.common.base.Splitter;
59 import com.google.common.collect.Sets;
62 * This is a simple PAP engine that uses some property files and a simple directory
63 * structure in the file system to manage a policy repository and set of PDP nodes.
67 public class StdEngine extends StdPDPItemSetChangeNotifier implements PAPPolicyEngine {
68 public static final String pipPropertyFile = "pip.properties";
70 private static Log logger = LogFactory.getLog(StdEngine.class);
72 public static String PROP_PAP_REPO = "xacml.pap.pdps";
73 public static String PROP_PAP_GROUPS = "xacml.pap.groups";
74 public static String PROP_PAP_GROUPS_DEFAULT = "xacml.pap.groups.default";
75 public static String PROP_PAP_GROUPS_DEFAULT_NAME = "default";
76 //this value will be accessed from XacmlPapServlet so that we know if a default group did not exist
77 //and was just added. This way, we can add the new group to the database.
78 public boolean wasDefaultGroupJustAdded = false;
80 protected final Path repository;
81 protected Set<StdPDPGroup> groups;
83 public StdEngine() throws PAPException, IOException {
85 // Get the location in the file system of our repository
87 this.repository = Paths.get(XACMLProperties.getProperty(PROP_PAP_REPO));
94 public StdEngine(Properties properties) throws PAPException, IOException {
96 // Get the location in the file system of our repository
98 this.repository = Paths.get(properties.getProperty(PROP_PAP_REPO));
105 public StdEngine(Path repository) throws PAPException, IOException {
109 this.repository = repository;
116 private void intialize() throws PAPException, IOException {
118 // Sanity check the repository path
120 if (this.repository == null) {
121 throw new PAPException ("No repository specified.");
123 if (Files.notExists(this.repository)) {
124 Files.createDirectory(repository);
126 if (Files.isDirectory(this.repository) == false) {
127 throw new PAPException ("Repository is NOT a directory: " + this.repository.toAbsolutePath());
129 if (Files.isWritable(this.repository) == false) {
130 throw new PAPException ("Repository is NOT writable: " + this.repository.toAbsolutePath());
138 private void loadGroups() throws PAPException {
140 // Create a properties object
142 Properties properties = new Properties();
143 Path file = Paths.get(this.repository.toString(), XACMLProperties.XACML_PROPERTIES_NAME);
146 // Load the properties
148 try (InputStream is = new FileInputStream(file.toFile())) {
155 this.groups = this.readProperties(this.repository, properties);
156 } catch (IOException e) {
157 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdEngine", "Failed to load properties file");
158 this.groups = new HashSet<StdPDPGroup>();
161 // Initialize the default group
163 PDPGroup defaultGroup = this.initializeDefaultGroup(file, properties);
164 logger.info("Default group is: " + defaultGroup.getId() + "=" + defaultGroup.getName());
167 private PDPGroup initializeDefaultGroup(Path file, Properties properties) throws PAPException {
168 wasDefaultGroupJustAdded = false;
170 // Make sure we have the default group
172 PDPGroup group = this.getDefaultGroup();
177 // We don't have the default group, create it
179 String defaultId = properties.getProperty(PROP_PAP_GROUPS_DEFAULT, PROP_PAP_GROUPS_DEFAULT_NAME);
180 if(defaultId == null){
181 defaultId = PROP_PAP_GROUPS_DEFAULT_NAME;
183 if(defaultId.equals("")){
184 defaultId = PROP_PAP_GROUPS_DEFAULT_NAME;
186 //we're going to check one more time in case the PROP_PAP_GROUPS_DEFAULT_NAME doesn't exist
187 if(defaultId == null){
188 defaultId = "default";
190 if(defaultId.equals("")){
191 defaultId = "default";
193 logger.warn("Default group does NOT exist, creating " + defaultId);
194 Path defaultPath = Paths.get(this.repository.toString(), defaultId);
199 if (Files.notExists(defaultPath)) {
201 // Create its directory
203 Files.createDirectory(defaultPath);
205 // Create property files
208 Properties props = new Properties();
209 props.setProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, "");
210 props.setProperty(XACMLProperties.PROP_ROOTPOLICIES, "");
211 Path policyPath = Paths.get(defaultPath.toAbsolutePath().toString(), "xacml.policy.properties");
212 Files.createFile(policyPath);
213 try (OutputStream os = Files.newOutputStream(policyPath)) {
215 } catch (IOException e) {
216 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdEngine", "Failed to write default policy properties");
220 Properties props = new Properties();
221 props = setPIPProperties(props);
222 Path pipPath = Paths.get(defaultPath.toAbsolutePath().toString(), "xacml.pip.properties");
223 Files.createFile(pipPath);
224 try (OutputStream os = Files.newOutputStream(pipPath)) {
226 } catch (IOException e) {
227 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdEngine", "Failed to write default pip properties");
232 // Create the default group
234 StdPDPGroup newDefault = new StdPDPGroup(defaultId, true, "default", "The default group where new PDP's are put.", defaultPath);
236 // Add it to our list
238 this.groups.add(newDefault);
240 // Save our properties out since we have
241 // a new default group.
243 StdEngine.setGroupProperties(newDefault, properties);
248 try (OutputStream os = Files.newOutputStream(file)) {
249 properties.store(os, "");
251 } catch (IOException e) {
252 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "StdEngine", "Failed to save properties with new default group information.");
257 wasDefaultGroupJustAdded = true;
259 } catch (IOException e) {
260 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "StdEngine", "Failed to create default group");
261 throw new PAPException("Failed to create default group");
266 public EcompPDPGroup getDefaultGroup() throws PAPException{
267 for (EcompPDPGroup group : this.groups) {
268 if (group.isDefaultGroup()) {
273 // Default group doesn't exist
279 public EcompPDPGroup getGroup(String id) throws PAPException {
280 for (EcompPDPGroup g: this.groups) {
281 if (g.getId().equals(id)) {
289 public void newGroup(String name, String description) throws PAPException, NullPointerException{
294 throw new NullPointerException();
297 // Do we already have this group?
299 for (PDPGroup group : this.groups) {
300 if (group.getName().equals(name)) {
301 throw new PAPException("Group with this name=" + name + " already exists.");
306 // create an Id that can be used as a file name and a properties file key.
307 // Ids must not contain \/:*?"<>|=,;
308 // The ID must also be unique within the current set of PDPGroups.
309 String id = createNewPDPGroupId(name);
313 // Construct the directory path
315 Path groupPath = Paths.get(this.repository.toString(), id);
317 // If it exists already
319 if (Files.exists(groupPath)) {
320 logger.warn("addGroup " + id + " directory exists" + groupPath.toString());
324 // Create the directory
326 Files.createDirectory(groupPath);
327 } catch (IOException e) {
328 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdEngine", "Failed to create " + groupPath);
329 throw new PAPException("Failed to create " + id);
333 // Create the Policies
336 Path policyProperties = Paths.get(groupPath.toString(), "xacml.policy.properties");
337 if (Files.exists(policyProperties)) {
338 logger.warn("addGroup " + id + " file exists: " + policyProperties.toString());
340 Properties props = new Properties();
341 props.setProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, "");
342 props.setProperty(XACMLProperties.PROP_ROOTPOLICIES, "");
344 Files.createFile(policyProperties);
345 try (OutputStream os = Files.newOutputStream(policyProperties)) {
348 } catch (IOException e) {
349 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "StdEngine", "Failed to create " + policyProperties);
350 throw new PAPException("Failed to create " + id);
354 // Create the PIP config
356 Path pipProperties = Paths.get(groupPath.toString(), "xacml.pip.properties");
357 Properties props = new Properties();
358 if (Files.exists(pipProperties)) {
359 logger.warn("addGroup " + id + " file exists: " + pipProperties.toString());
362 props = setPIPProperties(props);
363 Files.createFile(pipProperties);
364 try (OutputStream os = Files.newOutputStream(pipProperties)) {
367 } catch (IOException e) {
368 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdEngine", "Failed to create " + pipProperties);
369 throw new PAPException("Failed to create " + id);
376 StdPDPGroup newGroup = new StdPDPGroup(id, name, description, groupPath);
377 // Add the default PIP configuration.
378 String list = props.getProperty(XACMLProperties.PROP_PIP_ENGINES);
379 if (list != null && list.length() > 0) {
380 Set<PDPPIPConfig> pipConfigs = new HashSet<PDPPIPConfig>();
381 for (String pipID : list.split("[,]")) {
382 StdPDPPIPConfig config = new StdPDPPIPConfig(pipID, props);
383 if (config.isConfigured()) {
384 pipConfigs.add(config);
387 newGroup.setPipConfigs(pipConfigs);
389 if (this.groups.add(newGroup)) {
390 // save the new group in our properties and notify any listeners of the change
391 groupChanged(newGroup);
400 * Helper to create a new Group ID.
401 * Use the Name field to create the Id.
402 * The Name is expected to not be null; if it is then this method throws an exception.
403 * The name is supposed to be unique within the current set of groups,
404 * so creating the ID based on the name will create a unique string.
409 private String createNewPDPGroupId(String name) {
411 // replace "bad" characters with sequences that will be ok for file names and properties keys.
412 id = id.replace(" ", "_sp_");
413 id = id.replace("\t", "_tab_");
414 id = id.replace("\\", "_bksl_");
415 id = id.replace("/", "_sl_");
416 id = id.replace(":", "_col_");
417 id = id.replace("*", "_ast_");
418 id = id.replace("?", "_q_");
419 id = id.replace("\"", "_quo_");
420 id = id.replace("<", "_lt_");
421 id = id.replace(">", "_gt_");
422 id = id.replace("|", "_bar_");
423 id = id.replace("=", "_eq_");
424 id = id.replace(",", "_com_");
425 id = id.replace(";", "_scom_");
432 public EcompPDP getPDP(String pdpId) throws PAPException {
433 for (EcompPDPGroup group : this.groups) {
434 for (EcompPDP pdp : group.getEcompPdps()) {
435 if (pdp.getId().equals(pdpId)) {
445 public void movePDP(EcompPDP pdp, EcompPDPGroup newGroup) throws PAPException {
446 if (newGroup == null) {
447 throw new NullPointerException("You must specify which group the PDP will belong to.");
449 PDPGroup currentGroup = this.getPDPGroup(pdp);
450 if (currentGroup == null) {
451 throw new PAPException("PDP must already belong to a group.");
453 if (currentGroup.equals(newGroup)) {
454 logger.warn("Already in that group.");
457 if (currentGroup instanceof StdPDPGroup && newGroup instanceof StdPDPGroup) {
458 if (((StdPDPGroup) currentGroup).removePDP(pdp)) {
459 boolean result = ((StdPDPGroup) newGroup).addPDP(pdp);
462 // Save the configuration
466 PolicyLogger.error("Failed to add to new group, putting back into original group.");
467 if (((StdPDPGroup) currentGroup).removePDP(pdp) == false) {
468 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + "Failed to put PDP back into original group.");
473 String message = "Unknown PDP group class: " + newGroup.getClass().getCanonicalName() + " and " + currentGroup.getClass().getCanonicalName();
474 logger.warn(message);
475 throw new PAPException(message);
481 public void updatePDP(EcompPDP pdp) throws PAPException {
482 PDP currentPDP = this.getPDP(pdp.getId());
483 if (currentPDP == null) {
484 String message = "Unknown PDP id '" + pdp.getId() + "'";
485 logger.warn(message);
486 throw new PAPException(message);
489 // the only things that the user can change are name and description
490 currentPDP.setDescription(pdp.getDescription());
491 currentPDP.setName(pdp.getName());
492 if (currentPDP instanceof EcompPDP && pdp instanceof EcompPDP) {
493 ((EcompPDP)currentPDP).setJmxPort(((EcompPDP)pdp).getJmxPort());
499 public void removePDP(EcompPDP pdp) throws PAPException {
500 PDPGroup group = this.getPDPGroup(pdp);
502 throw new NullPointerException();
504 if (group instanceof StdPDPGroup) {
505 boolean result = ((StdPDPGroup) group).removePDP(pdp);
511 String message = "Unknown PDP group class: " + group.getClass().getCanonicalName();
512 logger.warn(message);
513 throw new PAPException(message);
519 * Should never be called - Detailed status is held on the PDP, not the PAP
521 public PDPStatus getStatus(EcompPDP pdp) throws PAPException {
522 return getPDP(pdp.getId()).getStatus();
526 public void publishPolicy(String id, String name, boolean isRoot, InputStream policy, EcompPDPGroup group) throws PAPException {
528 throw new NullPointerException();
530 if (group instanceof StdPDPGroup && this.groups.contains(group)) {
531 ((StdPDPGroup) group).publishPolicy(id, name, isRoot, policy);
534 logger.warn("unknown PDP Group: " + group);
535 throw new PAPException("Unknown PDP Group: " + group.getId());
538 // Currently not used on the PAP side. This is done by ((StdPDPGroup) group).copyPolicyToFile
540 public void copyPolicy(PDPPolicy policy, EcompPDPGroup group)
541 throws PAPException {
546 public void removePolicy(PDPPolicy policy, EcompPDPGroup group) throws PAPException {
548 throw new NullPointerException();
550 if (group instanceof StdPDPGroup && this.groups.contains(group)) {
551 ((StdPDPGroup) group).removePolicy(policy);
554 logger.warn("unknown PDP Group: " + group);
555 throw new PAPException("Unknown PDP Group: " + group.getId());
563 private Set<StdPDPGroup> readProperties(Path repository, Properties properties) throws PAPException {
564 Set<StdPDPGroup> groups = new HashSet<StdPDPGroup>();
566 // See if there is a groups property
568 String groupList = properties.getProperty(PROP_PAP_GROUPS, "");
569 if (groupList == null) {
570 logger.warn("null group list " + PROP_PAP_GROUPS);
573 if (logger.isDebugEnabled()) {
574 logger.debug("group list: " + groupList);
577 // Iterate the groups, converting to a set ensures we have unique groups.
579 for (String id : Splitter.on(',').trimResults().omitEmptyStrings().split(groupList)) {
581 // Add our Group Object
583 StdPDPGroup g = new StdPDPGroup(id.trim(),
584 id.equals(properties.getProperty(PROP_PAP_GROUPS_DEFAULT, PROP_PAP_GROUPS_DEFAULT_NAME)),
586 Paths.get(repository.toString(), id));
596 if (logger.isDebugEnabled()) {
597 logger.debug("PDP Group List: " + groups.toString());
602 private void saveConfiguration() throws PAPException, IOException {
604 // Create our properties object
606 Properties properties = new Properties() {
607 private static final long serialVersionUID = 1L;
608 // For Debugging it is helpful for the file to be in a sorted order,
609 // any by returning the keys in the natural Alpha order for strings we get close enough.
610 // TreeSet is sorted, and this just overrides the normal Properties method to get the keys.
612 public synchronized Enumeration<Object> keys() {
613 return Collections.enumeration(new TreeSet<Object>(super.keySet()));
617 // Iterate our groups
619 List<String> ids = new ArrayList<String>();
620 for (PDPGroup group : this.groups) {
621 ids.add(group.getId());
622 properties.setProperty(group.getId() + ".name", (group.getName() == null ? "" : group.getName()));
623 properties.setProperty(group.getId() + ".description", (group.getDescription() == null ? "" : group.getDescription()));
627 List<String> pdps = new ArrayList<String>();
628 for (PDP pdp : group.getPdps()) {
629 pdps.add(pdp.getId());
630 properties.setProperty(pdp.getId() + ".name", (pdp.getName() == null ? "" : pdp.getName()));
631 properties.setProperty(pdp.getId() + ".description", (pdp.getDescription() == null ? "" : pdp.getDescription()));
632 if (pdp instanceof EcompPDP) {
633 properties.setProperty(pdp.getId() + ".jmxport", (((EcompPDP)pdp).getJmxPort()==0 ? "" : ((EcompPDP)pdp).getJmxPort()).toString());
637 if (pdps.size() == 1) {
638 pdpList = pdps.get(0);
639 } else if (pdps.size() > 1) {
640 pdpList = Joiner.on(',').skipNulls().join(pdps);
642 if (logger.isDebugEnabled()) {
643 logger.debug("Group " + group.getId() + " PDPS: " + pdpList);
645 properties.setProperty(group.getId() + ".pdps", pdpList);
648 throw new PAPException("Inconsistency - we have NO groups. We should have at least one.");
650 String groupList = "";
651 if (ids.size() == 1) {
652 groupList = ids.get(0);
653 } else if (ids.size() > 1){
654 groupList = Joiner.on(',').skipNulls().join(ids);
656 logger.info("New Group List: " + groupList);
658 properties.setProperty(PROP_PAP_GROUPS, groupList);
660 // Get the default group
662 PDPGroup defaultGroup = this.getDefaultGroup();
663 if (defaultGroup == null) {
664 throw new PAPException("Invalid state - no default group.");
666 properties.setProperty(PROP_PAP_GROUPS_DEFAULT, defaultGroup.getId());
668 // Now we can save the file
670 Path file = Paths.get(this.repository.toString(), "xacml.properties");
671 try (OutputStream os = Files.newOutputStream(file)) {
672 properties.store(os, "");
676 public static void removeGroupProperties(String id, Properties properties) {
677 for (Object key : properties.keySet()) {
678 if (key.toString().startsWith(id + ".")) {
679 properties.remove(key);
684 public static void setGroupProperties(PDPGroup group, Properties properties) {
686 // make sure its in the list of groups
688 Iterable<String> groups = Splitter.on(',').trimResults().omitEmptyStrings().split( properties.getProperty(PROP_PAP_GROUPS, ""));
689 boolean inList = false;
690 for (String g : groups) {
691 if (g.equals(group.getId())) {
695 if (inList == false) {
696 Set<String> grps = Sets.newHashSet(groups);
697 grps.add(group.getId());
698 String newGroupList = "";;
699 if (grps.size() == 1) {
700 newGroupList = grps.iterator().next();
701 } else if (grps.size() > 1) {
702 newGroupList = Joiner.on(',').skipNulls().join(grps);
704 logger.info("New Group List: " + newGroupList);
705 properties.setProperty(PROP_PAP_GROUPS, newGroupList);
708 // Set its properties
710 properties.setProperty(group.getId() + ".name", group.getName());
711 properties.setProperty(group.getId() + ".description", group.getDescription());
715 if (group.getPdps().size() > 0) {
717 if (group.getPdps().size() == 1) {
718 pdpList = group.getPdps().iterator().next().getId();
719 } else if (group.getPdps().size() > 1) {
720 Set<String> ids = new HashSet<String>();
721 for (PDP pdp : group.getPdps()) {
722 ids.add(pdp.getId());
724 pdpList = Joiner.on(',').skipNulls().join(ids);
726 properties.setProperty(group.getId() + ".pdps", pdpList);
728 properties.setProperty(group.getId() + ".pdps", "");
733 public void changed() {
734 if (logger.isDebugEnabled()) {
735 logger.debug("changed");
741 public void groupChanged(EcompPDPGroup group) {
742 if (logger.isDebugEnabled()) {
743 logger.debug("groupChanged: " + group);
746 this.firePDPGroupChanged(group);
750 public void pdpChanged(EcompPDP pdp) {
751 if (logger.isDebugEnabled()) {
752 logger.debug("pdpChanged: " + pdp);
755 this.firePDPChanged(pdp);
758 private void doSave() {
761 // Save the configuration
763 this.saveConfiguration();
764 } catch (IOException e) {
765 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "StdEngine", "Failed to save configuration");
766 } catch (PAPException e) {
767 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "StdEngine", "Failed to save configuration");
771 private Properties setPIPProperties(Properties props){
772 props.setProperty(XACMLProperties.PROP_PIP_ENGINES, "AAF");
773 props.setProperty("AAF.name", "AAFEngine");
774 props.setProperty("AAF.description", "AAFEngine to communicate with AAF to take decisions");
775 props.setProperty("AAF.classname","org.openecomp.policy.xacml.std.pip.engines.aaf.AAFEngine");
776 // read from PIP properties file.
777 Path file = Paths.get(pipPropertyFile);
778 if (!Files.notExists(file)) {
780 Properties prop = new Properties();
782 in = new FileInputStream(file.toFile());
784 } catch (IOException e) {
785 PolicyLogger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "can not load the pip properties from file" +e);
794 public Set<EcompPDPGroup> getEcompPDPGroups() throws PAPException {
795 final Set<EcompPDPGroup> grps = new HashSet<EcompPDPGroup>();
796 for (EcompPDPGroup g : this.groups) {
799 return Collections.unmodifiableSet(grps);
803 public EcompPDPGroup getPDPGroup(EcompPDP pdp) throws PAPException {
804 for (EcompPDPGroup group : this.groups) {
805 if (group.getPdps().contains(pdp)) {
813 public void SetDefaultGroup(EcompPDPGroup group) throws PAPException {
814 boolean changesMade = false;
815 for (EcompPDPGroup aGroup : groups) {
816 if (aGroup.getId().equals(group.getId())) {
817 if ( ! aGroup.isDefaultGroup()) {
818 if (aGroup instanceof StdPDPGroup) {
819 ((StdPDPGroup) aGroup).setDefault(true);
822 throw new IllegalArgumentException("Group in groups of unknown type '" + aGroup.getClass().getName() + "'");
826 // not the new default group
827 if (aGroup.isDefaultGroup()) {
828 if (aGroup instanceof StdPDPGroup) {
829 ((StdPDPGroup) aGroup).setDefault(false);
832 throw new IllegalArgumentException("Group in groups of unknown type '" + aGroup.getClass().getName() + "'");
846 public void newPDP(String id, EcompPDPGroup group, String name, String description, int jmxport)
847 throws PAPException, NullPointerException {
849 throw new PAPException("You must specify which group the PDP will belong to.");
851 if (this.groups.contains(group) == false) {
852 throw new PAPException("Unknown group, not in our list.");
854 for (EcompPDP p : group.getEcompPdps()) {
855 if (p.getId().equals(id)) {
856 throw new PAPException("A PDP with this ID exists.");
859 if (group instanceof StdPDPGroup) {
860 StdPDP pdp = new StdPDP(id, name, description, jmxport);
861 if (((StdPDPGroup) group).addPDP(pdp)) {
863 // Save the properties and notify any listeners
874 public void updateGroup(EcompPDPGroup group) throws PAPException {
875 if (group == null || group.getId() == null) {
876 throw new PAPException("Group or id is null");
878 if (group.getName() == null || group.getName().trim().length() == 0) {
879 throw new PAPException("New name for group cannot be null or blank");
881 StdPDPGroup existingGroup = (StdPDPGroup)getGroup(group.getId());
882 if (existingGroup == null) {
883 throw new PAPException("Update found no existing group with id '" + group.getId() + "'");
887 // We do dramatically different things when the Name changes
888 // because the Name is essentially the identity of the group (as the User knows it) so when the Identity changes we have to change the group ID.
889 if (group.getName().equals(existingGroup.getName())) {
893 ((StdPDPGroup)group).saveGroupConfiguration();
894 } catch (IOException e) {
895 throw new PAPException("Unable to save new configuration for '" + group.getName() + "': " + e.getMessage());
897 // update the group in the set by simply replacing the old instance with the new one
898 this.groups.remove(existingGroup);
899 this.groups.add((StdPDPGroup)group);
902 // the name/identity of the group has changed
903 // generate the new id
904 String newId = createNewPDPGroupId(group.getName());
906 // make sure no other group uses the new id
907 for (EcompPDPGroup g : groups) {
908 if (g.getId().equals(newId)) {
909 throw new PAPException("Replacement name maps to ID '" + newId + "' which is already in use");
912 ((StdPDPGroup)group).setId(newId);
914 // rename the existing directory to the new id
915 Path oldPath = existingGroup.getDirectory();
916 Path newPath = Paths.get(oldPath.getParent().toString(), newId);
917 ((StdPDPGroup)group).setDirectory(newPath);
920 boolean success = oldPath.toFile().renameTo(newPath.toFile());
922 throw new PAPException("Unable to rename directory; reason unknown");
924 } catch (Exception e) {
925 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "StdEngine", "Unable to rename directory");
926 throw new PAPException("Unable to move directory from '" + oldPath + "' to '" + newPath + "': " + e.getMessage());
930 ((StdPDPGroup)group).saveGroupConfiguration();
931 } catch (IOException e) {
932 throw new PAPException("Unable to save new configuration for '" + group.getName() + "': " + e.getMessage());
935 // save the new group into the Set
936 groups.remove(existingGroup);
937 groups.add((StdPDPGroup)group);
941 // perhaps only the group changed, but if the name/id changed it may look to a listener like more than one group
948 public void removeGroup(EcompPDPGroup group, EcompPDPGroup newGroup) throws PAPException, NullPointerException {
950 throw new NullPointerException();
953 // Does this group exist?
955 if (this.groups.contains(group) == false) {
956 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + "This group doesn't exist.");
957 throw new PAPException("The group '" + group.getId() + "' does not exist");
960 // Is it the default group?
962 if (group.isDefaultGroup()) {
963 throw new PAPException("You cannot delete the default group.");
965 Set<EcompPDP> pdps = group.getEcompPdps();
967 // Are there PDPs? If so, then we need a target group
969 if (pdps.isEmpty() == false && newGroup == null) {
970 throw new NullPointerException("Group targeted for deletion has PDPs, you must provide a new group for them.");
975 if (pdps.isEmpty() == false) {
976 if (! (newGroup instanceof StdPDPGroup)) {
977 throw new PAPException("Unexpected class for newGroup: " + newGroup.getClass().getCanonicalName());
979 // The movePDP function will modify the set of PDPs in the group.
980 // To avoid concurrent modification exceptions we need to duplicate the list before calling that function.
981 List<EcompPDP> pdpList = new ArrayList<EcompPDP>();
982 for (EcompPDP pdp : pdps) {
985 // now we can use the PDPs from the list without having ConcurrentAccessExceptions
986 for (EcompPDP pdp : pdpList) {
987 this.movePDP(pdp, newGroup);
991 // remove the directory for the group
993 String id = group.getId();
994 Path groupPath = Paths.get(this.repository.toString(), id);
996 // If it exists already
998 if ( ! Files.exists(groupPath)) {
999 logger.warn("removeGroup " + id + " directory does not exist" + groupPath.toString());
1002 Files.walkFileTree(groupPath, new SimpleFileVisitor<Path>() {
1005 public FileVisitResult visitFile(Path file,
1006 BasicFileAttributes attrs) throws IOException {
1008 return super.visitFile(file, attrs);
1013 // delete the directory
1015 Files.delete(groupPath);
1016 } catch (IOException e) {
1017 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "StdEngine", "Failed to delete " + groupPath);
1018 throw new PAPException("Failed to delete " + id);
1022 // remove the group from the set of all groups
1023 groups.remove(group);