You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by an...@apache.org on 2021/03/23 16:47:41 UTC
[sling-org-apache-sling-repoinit-parser] branch SLING-10236 created
(now 6007f20)
This is an automated email from the ASF dual-hosted git repository.
angela pushed a change to branch SLING-10236
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-repoinit-parser.git.
at 6007f20 SLING-10236 : Introduce Operation.asRepoInitString (initial draft with FIXMEs and TODOs)
This branch includes the following new commits:
new 6007f20 SLING-10236 : Introduce Operation.asRepoInitString (initial draft with FIXMEs and TODOs)
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
[sling-org-apache-sling-repoinit-parser] 01/01: SLING-10236 :
Introduce Operation.asRepoInitString (initial draft with FIXMEs and TODOs)
Posted by an...@apache.org.
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 <an...@adobe.com>
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
+ }
+}