in src/main/java/org/apache/sling/starter/access/models/Ace.java [155:316]
public Collection<PrivilegeItem> getPrivileges() throws RepositoryException {
Map<Privilege, PrivilegeItem> privilegesMap = getPersistedPrivilegesMap();
if (privilegesMap == null || privilegesMap.isEmpty()) {
return Collections.emptyList();
}
//make a temp map for quick lookup below
Set<RestrictionDefinition> supportedRestrictions = getSupportedRestrictions();
Map<String, RestrictionDefinition> srMap = toSrMap(supportedRestrictions);
Map<String, List<RestrictionItem>> postedAllowRestrictionsMap = new HashMap<>();
Map<String, List<RestrictionItem>> postedDenyRestrictionsMap = new HashMap<>();
Map<String, String[]> fieldValues = populateEntriesFromPreviousFailedPost(postedAllowRestrictionsMap, postedDenyRestrictionsMap, srMap);
Map<String, String[]> toDeleteFieldValues = getFieldValuesForPattern(RESTRICTION_PATTERN_DELETE);
//entries from the previous failed POST.
for (PrivilegeItem entry : privilegesMap.values()) {
String privilegeName = entry.getName();
// check for any submitted form fields in case of error and redisplay of the page
String paramValue = request.getParameter(String.format("privilege@%s", privilegeName));
if (paramValue != null) {
//req param was here from a failed post?
if ("granted".equals(paramValue)) {
entry.setGranted(true);
} else if ("denied".equals(paramValue)) {
entry.setDenied(true);
}
} else {
// check for delete existing param
String paramDeleteValue = request.getParameter(String.format("privilege@%s@Delete", privilegeName));
if (paramDeleteValue != null) {
//req param was here from a failed post?
if ("granted".equals(paramDeleteValue)) {
entry.setGranted(false);
} else if ("denied".equals(paramDeleteValue)) {
entry.setDenied(false);
}
}
}
for (boolean forAllow : new boolean [] {true, false}) {
// first add items for any posted fields
Map<String, List<RestrictionItem>> postedRestrictionsMap = forAllow ? postedAllowRestrictionsMap : postedDenyRestrictionsMap;
List<RestrictionItem> newRestrictionsList = postedRestrictionsMap.computeIfAbsent(privilegeName, pn -> new ArrayList<>());
//now merge in any declared restrictions that were not posted
List<RestrictionItem> declaredRestrictions = forAllow ? entry.getAllowRestrictions() : entry.getDenyRestrictions();
if (declaredRestrictions != null && !declaredRestrictions.isEmpty()) {
for (RestrictionItem ri : declaredRestrictions) {
String restrictionName = ri.getName();
boolean addIt = true;
String fieldKeyPrefix = String.format("restriction@%s@%s", privilegeName, restrictionName);
String fieldKey = String.format("%s@%s", fieldKeyPrefix, (forAllow ? "Allow" : "Deny"));
// skip it if it was requested to be deleted in the previous POST attempt
// or already handled above
if (toDeleteFieldValues.containsKey(String.format("%s%s", fieldKeyPrefix, SlingPostConstants.SUFFIX_DELETE))) {
addIt = false;
} else if (fieldValues.containsKey(fieldKey)) {
// mark the form posted item as exists since it also
// had a persisted value
newRestrictionsList.stream()
.filter(list -> list.getName().equals(restrictionName))
.forEach(item -> item.setExists(true));
addIt = false;
}
if (addIt) {
newRestrictionsList.add(ri);
}
}
}
// check if we are missing an item for any mandatory restrictions
populateEntriesForMissingMandatoryRestrictions(newRestrictionsList, supportedRestrictions);
// and apply it
if (forAllow) {
entry.setAllowRestrictions(newRestrictionsList);
} else {
entry.setDenyRestrictions(newRestrictionsList);
}
// populate restrictions to delete here.
toDeleteFieldValues.keySet().stream()
.filter(key -> RESTRICTION_PATTERN_DELETE.matcher(key).matches())
.forEach(key -> {
Matcher matcher = RESTRICTION_PATTERN_DELETE.matcher(key);
if (matcher.matches()) {
String restrictionName = matcher.group(2);
if (forAllow) {
entry.addAllowRestrictionToDelete(restrictionName);
} else {
entry.addDenyRestrictionToDelete(restrictionName);
}
}
});
}
}
List<PrivilegeItem> list = new ArrayList<>(privilegesMap.values());
list.sort((p1, p2) -> {
String longestPath1 = p1.getLongestPath();
String[] segments1 = longestPath1.split("/");
String longestPath2 = p2.getLongestPath();
String[] segments2 = longestPath2.split("/");
for (int i = 0; i < segments1.length; i++) {
Integer priority1 = privilegesPriority.getOrDefault(segments1[i], 1000);
if (segments2.length <= i) {
return longestPath1.compareTo(longestPath2);
}
Integer priority2 = privilegesPriority.getOrDefault(segments2[i], 1000);
int cmp = priority1.compareTo(priority2);
if (cmp != 0) {
return cmp;
}
}
if (segments1.length == segments2.length) {
// natural sort of the namespace-free last segment of each path
String lastSegment1 = segments1[segments1.length - 1];
String lastSegment2 = segments2[segments2.length - 1];
lastSegment1 = lastSegment1.substring(lastSegment1.indexOf(':'));
lastSegment2 = lastSegment2.substring(lastSegment2.indexOf(':'));
return lastSegment1.compareTo(lastSegment2);
}
return longestPath1.compareTo(longestPath2);
});
// loop through one more time to annotate the items with
// extra css markers to help render a tree-ish view
boolean lastBranch = true;
for (int i = list.size() - 1; i > 0; i--) {
PrivilegeItem item = list.get(i);
if (lastBranch) {
item.addExtraCssClass("lastBranch");
}
if (lastBranch && item.getDepth() == 1) {
lastBranch = false;
}
if (i == list.size() - 1) {
item.addExtraCssClass("lastSibling");
} else {
boolean lastSibling = true;
// if the there remains another item that has the same depth as this
// then this is not the last sibling
for (int j = i + 1; j < list.size(); j++) {
PrivilegeItem nextItem = list.get(j);
if (nextItem.getDepth() == item.getDepth()) {
String nextItemParentPath = ResourceUtil.getParent(nextItem.getLongestPath());
String itemParentPath = ResourceUtil.getParent(item.getLongestPath());
if (nextItemParentPath != null && nextItemParentPath.equals(itemParentPath)) {
lastSibling = false;
break;
}
}
}
if (lastSibling) {
item.addExtraCssClass("lastSibling");
}
}
}
return list;
}