This is an automated email from the ASF dual-hosted git repository. angela pushed a commit to branch SLING-10236 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-repoinit-parser.git
commit 6007f20efe551320d4321d1b3c374fdacd1c7b50 Author: angela <[email protected]> AuthorDate: Tue Mar 23 17:46:56 2021 +0100 SLING-10236 : Introduce Operation.asRepoInitString (initial draft with FIXMEs and TODOs) --- pom.xml | 6 ++ .../repoinit/parser/operations/AclGroupBase.java | 79 ++++++++++++++++++++++ .../parser/operations/AddGroupMembers.java | 7 ++ .../repoinit/parser/operations/CreateGroup.java | 7 ++ .../repoinit/parser/operations/CreatePath.java | 25 ++++++- .../parser/operations/CreateServiceUser.java | 7 ++ .../repoinit/parser/operations/CreateUser.java | 23 +++++++ .../repoinit/parser/operations/DeleteGroup.java | 7 ++ .../parser/operations/DeleteServiceUser.java | 5 ++ .../repoinit/parser/operations/DeleteUser.java | 7 ++ .../parser/operations/DisableServiceUser.java | 9 ++- .../repoinit/parser/operations/Operation.java | 23 ++++++- .../operations/OperationWithPathOptions.java | 12 ++++ .../parser/operations/PathSegmentDefinition.java | 24 +++++-- .../parser/operations/RegisterNamespace.java | 7 ++ .../parser/operations/RegisterNodetypes.java | 40 ++++++++++- .../parser/operations/RegisterPrivilege.java | 7 ++ .../parser/operations/RemoveGroupMembers.java | 7 ++ .../repoinit/parser/operations/SetAclPaths.java | 12 +++- .../parser/operations/SetAclPrincipalBased.java | 8 ++- .../parser/operations/SetAclPrincipals.java | 19 +++++- .../repoinit/parser/operations/SetProperties.java | 42 ++++++++++++ .../sling/repoinit/parser/test/AsRepoInitTest.java | 79 ++++++++++++++++++++++ 23 files changed, 450 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index 0d78786..465267c 100644 --- a/pom.xml +++ b/pom.xml @@ -105,6 +105,12 @@ <version>2.20.0</version> <scope>compile</scope> </dependency> + <dependency> + <groupId>org.jetbrains</groupId> + <artifactId>annotations</artifactId> + <version>18.0.0</version> + <scope>provided</scope> + </dependency> <!-- testing --> <dependency> diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/AclGroupBase.java b/src/main/java/org/apache/sling/repoinit/parser/operations/AclGroupBase.java index 9bc5861..7623470 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/AclGroupBase.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/AclGroupBase.java @@ -20,8 +20,11 @@ package org.apache.sling.repoinit.parser.operations; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Formatter; import java.util.List; +import java.util.stream.Collectors; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; /** Base class for operations that group AclLines */ @@ -59,4 +62,80 @@ abstract class AclGroupBase extends Operation { public List<String> getOptions() { return aclOptions; } + + String asRepoInit(@NotNull String topLine, boolean hasPathLines) { + try (Formatter formatter = new Formatter()) { + formatter.format("%s",topLine); + for (AclLine line : lines) { + String action = actionToString(line.getAction()); + String privileges = privilegesToString(line.getAction(), line.getProperty(AclLine.PROP_PRIVILEGES)); + String onOrFor; + if (hasPathLines) { + String pathStr = pathsToString(line.getProperty(AclLine.PROP_PATHS)); + onOrFor = (pathStr.isEmpty()) ? "" : " on " + pathStr; + } else { + onOrFor = " for " + listToString(line.getProperty(AclLine.PROP_PRINCIPALS)); + } + formatter.format(" %s %s%s%s%s%n", action, privileges, onOrFor, + nodetypesToString(line.getProperty(AclLine.PROP_NODETYPES)), + restrictionsToString(line.getRestrictions())); + } + formatter.format("end%n"); + return formatter.toString(); + } + } + + @NotNull + String getAclOptionsString() { + return (aclOptions.isEmpty()) ? "" : " (ACLOptions="+ listToString(aclOptions)+")"; + } + + @NotNull + static String privilegesToString(@NotNull AclLine.Action action, @NotNull List<String> privileges) { + return (action == AclLine.Action.REMOVE_ALL) ? "*" : listToString(privileges); + } + + @NotNull + static String pathsToString(@NotNull List<String> paths) { + return listToString(paths.stream() + .map(s -> { + if (s.startsWith(":") && s.contains("#")) { + String func = s.substring(1, s.indexOf(":",1)); + String s2 = s.substring(func.length()+2, s.lastIndexOf('#')); + String trailingPath = (s.endsWith("#")) ? "" : s.substring(s.indexOf("#")+1); + return func + "(" + s2 +")" + trailingPath; + } else { + return s; + } + }) + .collect(Collectors.toList())); + } + + @NotNull + private static String nodetypesToString(@NotNull List<String> nodetypes) { + return (nodetypes.isEmpty()) ? "" : " nodetypes " + listToString(nodetypes); + } + + @NotNull + private static String restrictionsToString(@NotNull List<RestrictionClause> restrictionClauses) { + StringBuilder sb = new StringBuilder(); + for (RestrictionClause rc : restrictionClauses) { + sb.append(" restriction(").append(rc.getName()); + for (String v : rc.getValues()) { + sb.append(",").append(v); + } + sb.append(')'); + } + return sb.toString(); + } + + @NotNull + private static String actionToString(@NotNull AclLine.Action action) { + switch (action) { + case DENY: return "deny"; + case REMOVE: return "remove"; + case REMOVE_ALL: return "remove"; + default: return "allow"; + } + } } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/AddGroupMembers.java b/src/main/java/org/apache/sling/repoinit/parser/operations/AddGroupMembers.java index 89aa5ac..5ccb49f 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/AddGroupMembers.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/AddGroupMembers.java @@ -19,6 +19,7 @@ package org.apache.sling.repoinit.parser.operations; import java.util.List; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -51,6 +52,12 @@ public class AddGroupMembers extends Operation { return sb.toString(); } + @NotNull + @Override + public String asRepoInitString() { + return String.format("add %s to group %s%n", listToString(members), groupname); + } + public String getGroupname() { return groupname; } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/CreateGroup.java b/src/main/java/org/apache/sling/repoinit/parser/operations/CreateGroup.java index 34a594b..3384c46 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/CreateGroup.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/CreateGroup.java @@ -18,6 +18,7 @@ package org.apache.sling.repoinit.parser.operations; import org.apache.sling.repoinit.parser.impl.WithPathOptions; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -59,6 +60,12 @@ public class CreateGroup extends OperationWithPathOptions { return sb.toString(); } + @NotNull + @Override + public String asRepoInitString() { + return asRepoInitString("group", groupname); + } + public String getGroupname() { return groupname; } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java b/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java index 4b66144..2332ff8 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java @@ -44,6 +44,27 @@ public class CreatePath extends Operation { } @Override + public String asRepoInitString() { + String defaultTypeStr = (defaultPrimaryType == null) ? "" : "("+defaultPrimaryType+") "; + StringBuilder sb = new StringBuilder(); + for (PathSegmentDefinition psd : getDefinitions()) { + sb.append("/").append(psd.getSegment()); + List<String> mixins = psd.getMixins(); + if (!psd.isDefaultPrimary() || !mixins.isEmpty()) { + sb.append("("); + if (!psd.isDefaultPrimary()) { + sb.append(psd.getPrimaryType()); + } + if (!mixins.isEmpty()) { + sb.append(" mixin ").append(listToString(mixins)); + } + sb.append(")"); + } + } + return String.format("create path %s%s%n", defaultTypeStr, sb.toString()); + } + + @Override public void accept(OperationVisitor v) { v.visitCreatePath(this); } @@ -62,16 +83,18 @@ public class CreatePath extends Operation { continue; } String pt = defaultPrimaryType; + boolean isDefaultPrimary = true; List<String> ms = null; if(i == segments.length -1) { if (primaryType != null) { pt = primaryType; + isDefaultPrimary = false; } if (mixins != null && ! mixins.isEmpty()) { ms = mixins; } } - pathDef.add(new PathSegmentDefinition(segments[i], pt, ms)); + pathDef.add(new PathSegmentDefinition(segments[i], pt, ms, isDefaultPrimary)); } } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/CreateServiceUser.java b/src/main/java/org/apache/sling/repoinit/parser/operations/CreateServiceUser.java index e6b7611..ade4d12 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/CreateServiceUser.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/CreateServiceUser.java @@ -18,6 +18,7 @@ package org.apache.sling.repoinit.parser.operations; import org.apache.sling.repoinit.parser.impl.WithPathOptions; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -48,4 +49,10 @@ public class CreateServiceUser extends ServiceUserOperation { return sb.toString(); } + + @NotNull + @Override + public String asRepoInitString() { + return asRepoInitString("service user", username); + } } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/CreateUser.java b/src/main/java/org/apache/sling/repoinit/parser/operations/CreateUser.java index 7d18b1b..827cdf5 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/CreateUser.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/CreateUser.java @@ -18,6 +18,7 @@ package org.apache.sling.repoinit.parser.operations; import org.apache.sling.repoinit.parser.impl.WithPathOptions; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -70,6 +71,28 @@ public class CreateUser extends OperationWithPathOptions { return sb.toString(); } + @NotNull + @Override + public String asRepoInitString() { + String path = getPath(); + if (path == null || path.isEmpty()) { + return String.format("create user %s%s%n", username, getPwString()); + } else { + String forced = (isForcedPath()) ? "forced " : ""; + return String.format("create user %s with %spath %s%s%n", username, forced, path, getPwString()); + } + } + + @NotNull + private String getPwString() { + if (password == null || password.isEmpty()) { + return ""; + } else { + String enc = (passwordEncoding != null) ? "{"+passwordEncoding+"} " : ""; + return String.format(" with password %s%s", enc, password); + } + } + public String getUsername() { return username; } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteGroup.java b/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteGroup.java index 0d10651..1fcb807 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteGroup.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteGroup.java @@ -17,6 +17,7 @@ package org.apache.sling.repoinit.parser.operations; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -42,6 +43,12 @@ public class DeleteGroup extends Operation { return groupname; } + @NotNull + @Override + public String asRepoInitString() { + return String.format("delete group %s%n", groupname); + } + public String getGroupname() { return groupname; } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteServiceUser.java b/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteServiceUser.java index 91d0061..6b19d8c 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteServiceUser.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteServiceUser.java @@ -29,4 +29,9 @@ public class DeleteServiceUser extends ServiceUserOperation { public void accept(OperationVisitor v) { v.visitDeleteServiceUser(this); } + + @Override + public String asRepoInitString() { + return String.format("delete service user %s%n", username); + } } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteUser.java b/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteUser.java index f0934d0..7f85d18 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteUser.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteUser.java @@ -17,6 +17,7 @@ package org.apache.sling.repoinit.parser.operations; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -40,6 +41,12 @@ public class DeleteUser extends Operation { return username; } + @NotNull + @Override + public String asRepoInitString() { + return String.format("delete user %s%n", username); + } + public String getUsername() { return username; } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/DisableServiceUser.java b/src/main/java/org/apache/sling/repoinit/parser/operations/DisableServiceUser.java index 6e4a393..1fb947b 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/DisableServiceUser.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/DisableServiceUser.java @@ -17,6 +17,7 @@ package org.apache.sling.repoinit.parser.operations; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -41,7 +42,13 @@ public class DisableServiceUser extends ServiceUserOperation { } return sb.toString(); } - + + @NotNull + @Override + public String asRepoInitString() { + return String.format("disable service user %s : %s%n", username, escape(reason)); + } + @Override public void accept(OperationVisitor v) { v.visitDisableServiceUser(this); diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/Operation.java b/src/main/java/org/apache/sling/repoinit/parser/operations/Operation.java index bf6581e..434ccc8 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/Operation.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/Operation.java @@ -17,15 +17,20 @@ package org.apache.sling.repoinit.parser.operations; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; +import java.util.List; + @ProviderType public abstract class Operation { public abstract void accept(OperationVisitor v); public static final String DQUOTE = "\""; protected abstract String getParametersDescription(); - + + public abstract String asRepoInitString(); + @Override public String toString() { return getClass().getSimpleName() + " " + getParametersDescription(); @@ -41,4 +46,20 @@ public abstract class Operation { } return s; } + + @NotNull + static String escape(@NotNull String s) { + // TODO: verify + String esc = s.replace("\\", "\\\\"); + String escapequotes = esc.replace("\"", "\\\""); + return "\"" + escapequotes + "\""; + } + + static String listToString(@NotNull List<String> list) { + if (list.isEmpty()) { + return ""; + } else { + return String.join(",", list); + } + } } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/OperationWithPathOptions.java b/src/main/java/org/apache/sling/repoinit/parser/operations/OperationWithPathOptions.java index 79c00b8..a4f1f65 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/OperationWithPathOptions.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/OperationWithPathOptions.java @@ -18,6 +18,7 @@ package org.apache.sling.repoinit.parser.operations; import org.apache.sling.repoinit.parser.impl.WithPathOptions; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -35,4 +36,15 @@ abstract class OperationWithPathOptions extends Operation { public boolean isForcedPath() { return wpopt.forcedPath; } + + @NotNull + String asRepoInitString(@NotNull String type, @NotNull String name) { + String path = wpopt.path; + if (path == null || path.isEmpty()) { + return String.format("create %s %s%n", type, name); + } else { + String forced = (wpopt.forcedPath) ? "forced " : ""; + return String.format("create %s %s with %spath %s%n", type, name, forced, path); + } + } } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/PathSegmentDefinition.java b/src/main/java/org/apache/sling/repoinit/parser/operations/PathSegmentDefinition.java index 96ce656..327156a 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/PathSegmentDefinition.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/PathSegmentDefinition.java @@ -17,8 +17,10 @@ package org.apache.sling.repoinit.parser.operations; +import java.util.Collections; import java.util.List; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; /** Defines a segment of a path to be created, @@ -29,22 +31,32 @@ public class PathSegmentDefinition { private final String segment; private final String primaryType; private final List<String> mixins; - + private final boolean isDefaultPrimary; + public PathSegmentDefinition(String segment, String primaryType) { - this(segment, primaryType, null); + this(segment, primaryType, null, false); } public PathSegmentDefinition(String segment, String primaryType, List<String> mixins) { + this(segment, primaryType, mixins, false); + } + + public PathSegmentDefinition(String segment, String primaryType, boolean isDefaultPrimary) { + this(segment, primaryType, null, isDefaultPrimary); + } + + public PathSegmentDefinition(String segment, String primaryType, List<String> mixins, boolean isDefaultPrimary) { this.segment = segment; this.primaryType = primaryType; - this.mixins = mixins; + this.mixins = (mixins == null) ? Collections.emptyList() : mixins; + this.isDefaultPrimary = isDefaultPrimary; } public String toString() { final StringBuilder sb = new StringBuilder(); sb.append(segment); boolean hasPrimaryType = primaryType != null; - boolean hasMixin = mixins != null && ! mixins.isEmpty(); + boolean hasMixin = !mixins.isEmpty(); if (hasPrimaryType || hasMixin) { sb.append("("); if (hasPrimaryType) { @@ -73,4 +85,8 @@ public class PathSegmentDefinition { public List<String> getMixins() { return mixins; } + + public boolean isDefaultPrimary() { + return isDefaultPrimary; + } } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterNamespace.java b/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterNamespace.java index 5d8f0dc..9ba2c99 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterNamespace.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterNamespace.java @@ -17,6 +17,7 @@ package org.apache.sling.repoinit.parser.operations; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -42,6 +43,12 @@ public class RegisterNamespace extends Operation { return sb.toString(); } + @NotNull + @Override + public String asRepoInitString() { + return String.format("register namespace ( %s ) %s%n", prefix, uri); + } + @Override public void accept(OperationVisitor v) { v.visitRegisterNamespace(this); diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterNodetypes.java b/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterNodetypes.java index fa43c5e..4bc363f 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterNodetypes.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterNodetypes.java @@ -17,8 +17,16 @@ package org.apache.sling.repoinit.parser.operations; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Formatter; +import java.util.List; + /** An embedded block of text */ @ProviderType public class RegisterNodetypes extends Operation { @@ -46,7 +54,37 @@ public class RegisterNodetypes extends Operation { sb.append(getCndStatements()); return sb.toString(); } - + + @Override + public String asRepoInitString() { + try (Formatter formatter = new Formatter()) { + for (String nodetypeRegistrationSentence : generateRepoInitLines(new BufferedReader(new StringReader(cndStatements)))) { + formatter.format("%s%n", nodetypeRegistrationSentence); + } + return formatter.toString(); + } catch (IOException e) { + throw new RuntimeException("Unexpected IOException", e); + } + } + + @NotNull + public static List<String> generateRepoInitLines(@NotNull BufferedReader rawLines) throws IOException { + List<String> lines = new ArrayList<>(); + lines.add("register nodetypes"); + lines.add("<<==="); + + String raw; + while((raw = rawLines.readLine()) != null) { + if (raw.isEmpty()) { + lines.add(""); + } else { + lines.add("<< "+raw); + } + } + lines.add("===>>"); + return lines; + } + @Override public void accept(OperationVisitor v) { v.visitRegisterNodetypes(this); diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterPrivilege.java b/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterPrivilege.java index 3b62f87..c5e49f5 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterPrivilege.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/RegisterPrivilege.java @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -59,6 +60,12 @@ public class RegisterPrivilege extends Operation { return this.privilegeName + "," + this.isAbstract + "," + this.declaredAggregateNames; } + @NotNull + @Override + public String asRepoInitString() { + return String.format("%s%n", toString()); + } + public String toString() { StringBuilder builder = new StringBuilder("register "); if (this.isAbstract) { diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/RemoveGroupMembers.java b/src/main/java/org/apache/sling/repoinit/parser/operations/RemoveGroupMembers.java index ecd28c2..320e647 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/RemoveGroupMembers.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/RemoveGroupMembers.java @@ -19,6 +19,7 @@ package org.apache.sling.repoinit.parser.operations; import java.util.List; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -51,6 +52,12 @@ public class RemoveGroupMembers extends Operation { return sb.toString(); } + @NotNull + @Override + public String asRepoInitString() { + return String.format("remove %s from group %s%n", listToString(members), groupname); + } + public String getGroupname() { return groupname; } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPaths.java b/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPaths.java index 4b60953..e43aed7 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPaths.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPaths.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; /** Set ACL statement that groups a set of AclLines @@ -32,7 +33,7 @@ public class SetAclPaths extends AclGroupBase { private final List<String> paths; public SetAclPaths(List<String> paths, List<AclLine> lines) { - this(paths,lines,new ArrayList<String>()); + this(paths,lines,new ArrayList<>()); } public SetAclPaths(List<String> paths,List<AclLine> lines, List<String> aclOptions){ @@ -46,7 +47,14 @@ public class SetAclPaths extends AclGroupBase { sb.append(super.getParametersDescription()); return sb.toString(); } - + + @NotNull + @Override + public String asRepoInitString() { + String topline = String.format("set ACL on %s%s%n", pathsToString(paths), getAclOptionsString()); + return asRepoInit(topline, false); + } + public List<String> getPaths() { return paths; } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java b/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java index 8c8b3b5..40ecb1a 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipalBased.java @@ -46,7 +46,13 @@ public class SetAclPrincipalBased extends AclGroupBase { sb.append(super.getParametersDescription()); return sb.toString(); } - + + @Override + public String asRepoInitString() { + String topline = String.format("set principal ACL for %s%s%n", listToString(principals), getAclOptionsString()); + return asRepoInit(topline, true); + } + public List<String> getPrincipals() { return principals; } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipals.java b/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipals.java index d740cc4..a5585da 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipals.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipals.java @@ -20,7 +20,9 @@ package org.apache.sling.repoinit.parser.operations; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import org.jetbrains.annotations.NotNull; import org.osgi.annotation.versioning.ProviderType; /** Set ACL statement that groups a set of AclLines @@ -46,7 +48,22 @@ public class SetAclPrincipals extends AclGroupBase { sb.append(super.getParametersDescription()); return sb.toString(); } - + + @NotNull + @Override + public String asRepoInitString() { + if (getLines().stream().anyMatch(line -> { + List<String> paths = line.getProperty(AclLine.PROP_PATHS); + return paths == null || paths.isEmpty(); + })) { + String topline = String.format("set repository ACL for %s%s%n", listToString(principals), getAclOptionsString()); + return asRepoInit(topline, true); + } else { + String topline = String.format("set ACL for %s%s%n", listToString(principals), getAclOptionsString()); + return asRepoInit(topline, true); + } + } + public List<String> getPrincipals() { return principals; } diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/SetProperties.java b/src/main/java/org/apache/sling/repoinit/parser/operations/SetProperties.java index f72ca11..d9c2de5 100644 --- a/src/main/java/org/apache/sling/repoinit/parser/operations/SetProperties.java +++ b/src/main/java/org/apache/sling/repoinit/parser/operations/SetProperties.java @@ -18,8 +18,15 @@ package org.apache.sling.repoinit.parser.operations; +import java.util.Calendar; +import java.util.Formatter; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import org.apache.jackrabbit.util.ISO8601; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.osgi.annotation.versioning.ProviderType; @ProviderType @@ -46,6 +53,41 @@ public class SetProperties extends Operation { return sb.toString(); } + @Override + public String asRepoInitString() { + // FIXME: see SLING-10238 for type and quoted values that cannot be generated + // exactly as they were originally defined in repo-init + try (Formatter formatter = new Formatter()) { + formatter.format("set properties on %s%n", listToString(paths)); + for (PropertyLine line : lines) { + String type = (line.getPropertyType() == null) ? "" : "{" + line.getPropertyType().name() + "}"; + String values = valuesToString(line.getPropertyValues(), line.getPropertyType()); + if (line.isDefault()) { + formatter.format("default %s%s to %s%n", line.getPropertyName(), type, values); + } else { + formatter.format("set %s%s to %s%n", line.getPropertyName(), type, values); + } + } + formatter.format("end%n"); + return formatter.toString(); + } + } + + private static String valuesToString(@NotNull List<Object> values, @Nullable PropertyLine.PropertyType type) { + List<String> strings = values.stream() + .map(o -> { + if (type == null || type == PropertyLine.PropertyType.String) { + return escape(Objects.toString(o, "")); + } else if (type == PropertyLine.PropertyType.Date) { + return "\"" + ISO8601.format((Calendar) o) + "\""; + } else { + return Objects.toString(o, null); + } + }) + .collect(Collectors.toList()); + return listToString(strings); + } + public List<String> getPaths() { return paths; } diff --git a/src/test/java/org/apache/sling/repoinit/parser/test/AsRepoInitTest.java b/src/test/java/org/apache/sling/repoinit/parser/test/AsRepoInitTest.java new file mode 100644 index 0000000..199f152 --- /dev/null +++ b/src/test/java/org/apache/sling/repoinit/parser/test/AsRepoInitTest.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.sling.repoinit.parser.test; + +import org.apache.sling.repoinit.parser.impl.RepoInitParserService; +import org.apache.sling.repoinit.parser.operations.Operation; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** Test the parser using our test-* input/expected output files. + * The code of this class doesn't contain any actual tests, it + * just looks for test-*.txt files, parses them and verifies the + * results according to the test-*-output.txt files. + */ +@RunWith(Parameterized.class) +public class AsRepoInitTest { + + private final ParserTest.TestCase tc; + + @Parameters(name="{0}") + public static Collection<Object[]> data() throws IOException { + final List<Object []> result = new ArrayList<>(); + for(int i=0; i < 100; i++) { + final ParserTest.TestCase tc = ParserTest.TestCase.build(i); + if(tc != null) { + result.add(new Object[] { tc }); + } + } + return result; + + } + + public AsRepoInitTest(ParserTest.TestCase tc) { + this.tc = tc; + } + + @Test + public void checkResultAsRepoInit() throws Exception { + StringBuilder repoInit = new StringBuilder(); + final List<Operation> expectedResult; + try { + expectedResult = new RepoInitParserService().parse(tc.input); + for (Operation o : expectedResult) { + repoInit.append(o.asRepoInitString()); + } + } finally { + tc.close(); + } + + List<Operation> ops = new RepoInitParserService().parse(new StringReader(repoInit.toString())); + assertEquals(expectedResult.size(), ops.size()); + // FIXME: assert operations are equivalent + } +}
