You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/10/20 14:39:10 UTC
[sling-org-apache-sling-repoinit-parser] 01/46: SLING-5449 - move
the repoinit modules under extensions, they do contain Sling-specific stuff
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-repoinit-parser.git
commit 848ab51b6eef8d6059af06fd548f0d1a436d7fd6
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Thu May 19 12:50:58 2016 +0000
SLING-5449 - move the repoinit modules under extensions, they do contain Sling-specific stuff
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1744564 13f79535-47bb-0310-9956-ffa450edef68
---
pom.xml | 92 +++++++
.../sling/repoinit/parser/RepoInitParser.java | 34 +++
.../repoinit/parser/RepoInitParsingException.java | 27 ++
.../parser/impl/RepoInitParserService.java | 49 ++++
.../repoinit/parser/operations/AclGroupBase.java | 43 ++++
.../sling/repoinit/parser/operations/AclLine.java | 71 ++++++
.../repoinit/parser/operations/CreatePath.java | 68 +++++
.../parser/operations/CreateServiceUser.java | 29 +++
.../parser/operations/DeleteServiceUser.java | 29 +++
.../repoinit/parser/operations/Operation.java | 30 +++
.../parser/operations/OperationVisitor.java | 26 ++
.../parser/operations/PathSegmentDefinition.java | 48 ++++
.../parser/operations/ServiceUserOperation.java | 34 +++
.../repoinit/parser/operations/SetAclPaths.java | 50 ++++
.../parser/operations/SetAclPrincipals.java | 50 ++++
.../repoinit/parser/operations/package-info.java | 21 ++
.../apache/sling/repoinit/parser/package-info.java | 21 ++
src/main/javacc/RepoInitGrammar.jjt | 276 +++++++++++++++++++++
.../parser/test/OperationToStringVisitor.java | 87 +++++++
.../repoinit/parser/test/ParserServiceTest.java | 39 +++
.../sling/repoinit/parser/test/ParserTest.java | 130 ++++++++++
.../repoinit/parser/test/ParsingErrorsTest.java | 89 +++++++
src/test/resources/testcases/test-1-output.txt | 4 +
src/test/resources/testcases/test-1.txt | 2 +
src/test/resources/testcases/test-10-output.txt | 5 +
src/test/resources/testcases/test-10.txt | 10 +
src/test/resources/testcases/test-11-output.txt | 5 +
src/test/resources/testcases/test-11.txt | 8 +
src/test/resources/testcases/test-2-output.txt | 3 +
src/test/resources/testcases/test-2.txt | 2 +
src/test/resources/testcases/test-20-output.txt | 4 +
src/test/resources/testcases/test-20.txt | 5 +
src/test/resources/testcases/test-3-output.txt | 1 +
src/test/resources/testcases/test-3.txt | 10 +
src/test/resources/testcases/test-30-output.txt | 6 +
src/test/resources/testcases/test-30.txt | 12 +
src/test/resources/testcases/test-99-output.txt | 19 ++
src/test/resources/testcases/test-99.txt | 31 +++
38 files changed, 1470 insertions(+)
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..2df3f3c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>26</version>
+ <relativePath/>
+ </parent>
+
+ <artifactId>org.apache.sling.repoinit.parser</artifactId>
+ <packaging>bundle</packaging>
+ <version>0.0.1-SNAPSHOT</version>
+ <name>Apache Sling RepoInit Parser</name>
+ <description>Parser for the Repository Initialization language used in Sling</description>
+
+ <scm>
+ <connection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/repoinit/parser</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/repoinit/parser</developerConnection>
+ <url>https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/repoinit/parser</url>
+ </scm>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>src/test/resources/testcases/**</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>javacc-maven-plugin</artifactId>
+ <version>2.5</version>
+ <executions>
+ <execution>
+ <id>calculator</id>
+ <configuration>
+ <sourceDirectory>${basedir}/src/main/javacc</sourceDirectory>
+ </configuration>
+ <goals>
+ <goal>jjtree-javacc</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/src/main/java/org/apache/sling/repoinit/parser/RepoInitParser.java b/src/main/java/org/apache/sling/repoinit/parser/RepoInitParser.java
new file mode 100644
index 0000000..8fe70eb
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/RepoInitParser.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import java.io.Reader;
+import java.util.List;
+
+import org.apache.sling.repoinit.parser.operations.Operation;
+
+/** ACL definitions parser service interface */
+public interface RepoInitParser {
+ /** Parse the supplied input.
+ * @param r Input in ACL definitions format. The reader is closed
+ * by this method.
+ * @throws AclParsingException on parsing errors
+ */
+ List<Operation> parse(Reader r) throws RepoInitParsingException;
+}
diff --git a/src/main/java/org/apache/sling/repoinit/parser/RepoInitParsingException.java b/src/main/java/org/apache/sling/repoinit/parser/RepoInitParsingException.java
new file mode 100644
index 0000000..fa40e52
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/RepoInitParsingException.java
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+public class RepoInitParsingException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public RepoInitParsingException(String reason, Throwable cause) {
+ super(reason, cause);
+ }
+}
diff --git a/src/main/java/org/apache/sling/repoinit/parser/impl/RepoInitParserService.java b/src/main/java/org/apache/sling/repoinit/parser/impl/RepoInitParserService.java
new file mode 100644
index 0000000..d599f55
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/impl/RepoInitParserService.java
@@ -0,0 +1,49 @@
+/*
+ * 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.impl;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.List;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.repoinit.parser.RepoInitParser;
+import org.apache.sling.repoinit.parser.RepoInitParsingException;
+import org.apache.sling.repoinit.parser.operations.Operation;
+
+/** ACL definitions parser service */
+@Component
+@Service(value=RepoInitParser.class)
+public class RepoInitParserService implements RepoInitParser {
+
+ @Override
+ public List<Operation> parse(Reader r) throws RepoInitParsingException {
+ try {
+ return new RepoInitParserImpl(r).parse();
+ } catch (ParseException pe) {
+ throw new RepoInitParsingException(pe.getMessage(), pe);
+ } finally {
+ try {
+ r.close();
+ } catch(IOException ignore) {
+ }
+ }
+ }
+}
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
new file mode 100644
index 0000000..3e67eae
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/AclGroupBase.java
@@ -0,0 +1,43 @@
+/*
+ * 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.operations;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/** Base class for operations that group AclLines */
+ abstract class AclGroupBase extends Operation {
+ private final List<AclLine> lines;
+
+ protected AclGroupBase(List<AclLine> lines) {
+ this.lines = Collections.unmodifiableList(lines);
+ }
+
+ protected String getParametersDescription() {
+ final StringBuilder sb = new StringBuilder();
+ for(AclLine line : lines) {
+ sb.append("\n ").append(line.toString());
+ }
+ return sb.toString();
+ }
+
+ public Collection<AclLine> getLines() {
+ return lines;
+ }
+}
diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/AclLine.java b/src/main/java/org/apache/sling/repoinit/parser/operations/AclLine.java
new file mode 100644
index 0000000..dc4da8a
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/AclLine.java
@@ -0,0 +1,71 @@
+/*
+ * 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.operations;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/** A single "set ACL" line */
+public class AclLine {
+
+ private final Action action;
+ private static final List<String> EMPTY_LIST = Collections.unmodifiableList(new ArrayList<String>());
+
+ public static final String PROP_PATHS = "paths";
+ public static final String PROP_PRINCIPALS = "principals";
+ public static final String PROP_PRIVILEGES = "privileges";
+ public static final String PROP_NODETYPES = "nodetypes";
+
+ public enum Action {
+ REMOVE,
+ REMOVE_ALL,
+ DENY,
+ ALLOW
+ };
+
+ private final Map<String, List<String>> properties;
+
+ public AclLine(Action a) {
+ action = a;
+ properties = new TreeMap<String, List<String>>();
+ }
+
+ public Action getAction() {
+ return action;
+ }
+
+ /** Return the named multi-value property, or an empty list
+ * if not found.
+ */
+ public List<String> getProperty(String name) {
+ List<String> value = properties.get(name);
+ return value != null ? value : EMPTY_LIST;
+ }
+
+ public void setProperty(String name, List<String> values) {
+ properties.put(name, Collections.unmodifiableList(values));
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " " + action + " " + properties;
+ }
+}
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
new file mode 100644
index 0000000..d1b87d0
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java
@@ -0,0 +1,68 @@
+/*
+ * 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.operations;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class CreatePath extends Operation {
+ private List<PathSegmentDefinition> pathDef;
+ private final String defaultPrimaryType;
+
+ public CreatePath(String defaultPrimaryType) {
+ this.pathDef = new ArrayList<PathSegmentDefinition>();
+ this.defaultPrimaryType = defaultPrimaryType;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " " + pathDef;
+ }
+
+ @Override
+ protected String getParametersDescription() {
+ return pathDef.toString();
+ }
+
+ @Override
+ public void accept(OperationVisitor v) {
+ v.visitCreatePath(this);
+ }
+
+ public void addSegment(String path, String primaryType) {
+ // We might get a path like /var/discovery, in which case
+ // the specified primary type applies to the last
+ // segment only
+ final String [] segments = path.split("/");
+ for(int i=0; i < segments.length; i++) {
+ if(segments[i].length() == 0) {
+ continue;
+ }
+ String pt = defaultPrimaryType;
+ if(i == segments.length -1 && primaryType != null) {
+ pt = primaryType;
+ }
+ pathDef.add(new PathSegmentDefinition(segments[i], pt));
+ }
+ }
+
+ public List<PathSegmentDefinition> getDefinitions() {
+ return Collections.unmodifiableList(pathDef);
+ }
+}
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
new file mode 100644
index 0000000..ef10180
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/CreateServiceUser.java
@@ -0,0 +1,29 @@
+/*
+ * 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.operations;
+
+public class CreateServiceUser extends ServiceUserOperation {
+ public CreateServiceUser(String username) {
+ super(username);
+ }
+
+ @Override
+ public void accept(OperationVisitor v) {
+ v.visitCreateServiceUser(this);
+ }
+}
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
new file mode 100644
index 0000000..f8cce8c
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/DeleteServiceUser.java
@@ -0,0 +1,29 @@
+/*
+ * 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.operations;
+
+public class DeleteServiceUser extends ServiceUserOperation {
+ public DeleteServiceUser(String username) {
+ super(username);
+ }
+
+ @Override
+ public void accept(OperationVisitor v) {
+ v.visitDeleteServiceUser(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
new file mode 100644
index 0000000..693cfc9
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/Operation.java
@@ -0,0 +1,30 @@
+/*
+ * 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.operations;
+
+public abstract class Operation {
+ public abstract void accept(OperationVisitor v);
+
+ protected abstract String getParametersDescription();
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " " + getParametersDescription();
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java b/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java
new file mode 100644
index 0000000..4079386
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java
@@ -0,0 +1,26 @@
+/*
+ * 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.operations;
+
+public interface OperationVisitor {
+ void visitCreateServiceUser(CreateServiceUser s);
+ void visitDeleteServiceUser(DeleteServiceUser s);
+ void visitSetAclPrincipal(SetAclPrincipals s);
+ void visitSetAclPaths(SetAclPaths s);
+ void visitCreatePath(CreatePath cp);
+}
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
new file mode 100644
index 0000000..62f95b8
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/PathSegmentDefinition.java
@@ -0,0 +1,48 @@
+/*
+ * 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.operations;
+
+/** Defines a segment of a path to be created,
+ * with its name and an optional primary type
+ */
+public class PathSegmentDefinition {
+ private final String segment;
+ private final String primaryType;
+
+ public PathSegmentDefinition(String segment, String primaryType) {
+ this.segment = segment;
+ this.primaryType = primaryType;
+ }
+
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(segment);
+ if(primaryType != null) {
+ sb.append("(").append(primaryType).append(")");
+ }
+ return sb.toString();
+ }
+
+ public String getSegment() {
+ return segment;
+ }
+
+ public String getPrimaryType() {
+ return primaryType;
+ }
+}
diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/ServiceUserOperation.java b/src/main/java/org/apache/sling/repoinit/parser/operations/ServiceUserOperation.java
new file mode 100644
index 0000000..7f055e2
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/ServiceUserOperation.java
@@ -0,0 +1,34 @@
+/*
+ * 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.operations;
+
+public abstract class ServiceUserOperation extends Operation {
+ protected final String username;
+
+ ServiceUserOperation(String username) {
+ this.username = username;
+ }
+
+ protected String getParametersDescription() {
+ return username;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+}
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
new file mode 100644
index 0000000..b2673dc
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPaths.java
@@ -0,0 +1,50 @@
+/*
+ * 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.operations;
+
+import java.util.Collections;
+import java.util.List;
+
+/** Set ACL statement that groups a set of AclLines
+ * that all refer to the same set of paths.
+ */
+public class SetAclPaths extends AclGroupBase {
+
+ private final List<String> paths;
+
+ public SetAclPaths(List<String> paths, List<AclLine> lines) {
+ super(lines);
+ this.paths = Collections.unmodifiableList(paths);
+ }
+
+ protected String getParametersDescription() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(paths);
+ sb.append(super.getParametersDescription());
+ return sb.toString();
+ }
+
+ public List<String> getPaths() {
+ return paths;
+ }
+
+ @Override
+ public void accept(OperationVisitor v) {
+ v.visitSetAclPaths(this);
+ }
+}
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
new file mode 100644
index 0000000..b3bb548
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/SetAclPrincipals.java
@@ -0,0 +1,50 @@
+/*
+ * 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.operations;
+
+import java.util.Collections;
+import java.util.List;
+
+/** Set ACL statement that groups a set of AclLines
+ * that all refer to the same set of principals.
+ */
+public class SetAclPrincipals extends AclGroupBase {
+
+ private final List<String> principals;
+
+ public SetAclPrincipals(List<String> principals, List<AclLine> lines) {
+ super(lines);
+ this.principals = Collections.unmodifiableList(principals);
+ }
+
+ protected String getParametersDescription() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(principals);
+ sb.append(super.getParametersDescription());
+ return sb.toString();
+ }
+
+ public List<String> getPrincipals() {
+ return principals;
+ }
+
+ @Override
+ public void accept(OperationVisitor v) {
+ v.visitSetAclPrincipal(this);
+ }
+}
diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/package-info.java b/src/main/java/org/apache/sling/repoinit/parser/operations/package-info.java
new file mode 100644
index 0000000..fad0a42
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/package-info.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+
+@Version("1.0.0")
+package org.apache.sling.repoinit.parser.operations;
+
+import aQute.bnd.annotation.Version;
diff --git a/src/main/java/org/apache/sling/repoinit/parser/package-info.java b/src/main/java/org/apache/sling/repoinit/parser/package-info.java
new file mode 100644
index 0000000..3c9ed48
--- /dev/null
+++ b/src/main/java/org/apache/sling/repoinit/parser/package-info.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+
+@Version("1.0.0")
+package org.apache.sling.repoinit.parser;
+
+import aQute.bnd.annotation.Version;
diff --git a/src/main/javacc/RepoInitGrammar.jjt b/src/main/javacc/RepoInitGrammar.jjt
new file mode 100644
index 0000000..66b52b0
--- /dev/null
+++ b/src/main/javacc/RepoInitGrammar.jjt
@@ -0,0 +1,276 @@
+/* JavaCC grammar for the SLING-5449 content repository
+ * initialization language
+ * See https://javacc.java.net/doc/docindex.html for the JavaCC docs
+ */
+
+options
+{
+ STATIC=false;
+ LOOKAHEAD=3;
+ //FORCE_LA_CHECK=true;
+}
+
+PARSER_BEGIN(RepoInitParserImpl)
+
+package org.apache.sling.repoinit.parser.impl;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import org.apache.sling.repoinit.parser.operations.*;
+
+/*
+ * 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.
+ */
+
+public class RepoInitParserImpl
+{
+}
+PARSER_END(RepoInitParserImpl)
+
+SKIP :
+{
+ " "
+| "\r"
+| "\t"
+| < COMMENT: "#" (~["\n"])* "\n" >
+}
+
+TOKEN:
+{
+ < SET: "set" >
+| < ACL: "ACL" >
+| < ON: "on" >
+| < REMOVE: "remove" >
+| < ALLOW: "allow" >
+| < DENY: "deny" >
+| < FOR: "for" >
+| < CREATE: "create" >
+| < DELETE: "delete" >
+| < SERVICE: "service" >
+| < PATH: "path" >
+| < END: "end" >
+| < USER: "user" >
+| < NODETYPES: "nodetypes" >
+| < LPAREN: "(" >
+| < RPAREN: ")" >
+| < PRINCIPAL: (["a"-"z"] | ["A"-"Z"] | ["0"-"9"] | "_" | "-")+ >
+| < COMMA: "," >
+| < STAR: "*" >
+| < NAMESPACED_ITEM: (["a"-"z"] | ["A"-"Z"])+ ":" (["a"-"z"] | ["A"-"Z"])+ >
+| < PATH_STRING: "/" (["a"-"z"] | ["A"-"Z"] | ["0"-"9"] | ["-"] | ["_"] | ["."] | ["/"]) * >
+| < EOL: "\n" >
+}
+
+List<Operation> parse() :
+{}
+{
+ { final List<Operation> result = new ArrayList<Operation>(); }
+
+ (
+ serviceUserStatement(result)
+ | setAclPaths(result)
+ | setAclPrincipals(result)
+ | createPathStatement(result)
+ | blankLine()
+ ) *
+ <EOF>
+
+ { return result; }
+}
+
+void blankLine() :
+{}
+{
+ <EOL>
+}
+
+List<String> principalsList() :
+{
+ Token t = null;
+ List<String> principals = new ArrayList<String>();
+}
+{
+ t = <PRINCIPAL> { principals.add(t.image); }
+ ( <COMMA> t = <PRINCIPAL> { principals.add(t.image); } )*
+ { return principals; }
+}
+
+void serviceUserStatement(List<Operation> result) :
+{
+ Token t;
+ List<String> principals;
+}
+{
+ (t=<CREATE> | t=<DELETE>)
+ <SERVICE> <USER>
+ principals = principalsList()
+ (<EOL> | <EOF>)
+
+ {
+ for(String PRINCIPAL : principals) {
+ if(CREATE == t.kind) {
+ result.add(new CreateServiceUser(PRINCIPAL));
+ } else {
+ result.add(new DeleteServiceUser(PRINCIPAL));
+ }
+ }
+ }
+}
+
+List<String> namespacedItemsList() :
+{
+ Token t = null;
+ List<String> priv = new ArrayList<String>();
+
+}
+{
+ t = <NAMESPACED_ITEM> { priv.add(t.image); }
+ ( <COMMA> t = <NAMESPACED_ITEM> { priv.add(t.image); } )*
+ { return priv; }
+}
+
+List<String> pathsList() :
+{
+ Token t = null;
+ List<String> paths = new ArrayList<String>();
+}
+{
+ t = <PATH_STRING> { paths.add(t.image); }
+ ( <COMMA> t = <PATH_STRING> { paths.add(t.image); } )*
+ { return paths; }
+}
+
+void createPathStatement(List<Operation> result) :
+{
+ CreatePath cp = null;
+ String defaultPrimaryType = null;
+ Token t1 = null;
+ Token t2 = null;
+}
+{
+ <CREATE> <PATH>
+ ( <LPAREN> t1 = <NAMESPACED_ITEM> <RPAREN> { defaultPrimaryType = t1.image; } ) ?
+
+ ( t1 = <PATH_STRING> ( <LPAREN> t2 = <NAMESPACED_ITEM> <RPAREN> ) ?
+ {
+ if(cp == null) {
+ cp = new CreatePath(defaultPrimaryType);
+ }
+ cp.addSegment(t1.image, t2 == null ? null : t2.image);
+ t2 = null;
+ }
+ ) +
+
+ (<EOL> | <EOF>)
+
+ { if(cp != null) result.add(cp); }
+}
+
+void setAclPaths(List<Operation> result) :
+{
+ List<String> paths;
+ List<AclLine> lines = new ArrayList<AclLine>();
+}
+{
+ <SET> <ACL> <ON> paths = pathsList() <EOL>
+ ( removeStarLine(lines) | userPrivilegesLine(lines) | blankLine() ) +
+ <END>
+ ( <EOL> | <EOF> )
+
+ {
+ result.add(new SetAclPaths(paths, lines));
+ }
+}
+
+void removeStarLine(List<AclLine> lines) :
+{
+ List<String> tmp = null;
+ AclLine line = new AclLine(AclLine.Action.REMOVE_ALL);
+}
+{
+ <REMOVE> <STAR>
+ (
+ <FOR> tmp = principalsList() { line.setProperty(AclLine.PROP_PRINCIPALS, tmp); }
+
+ | <ON> tmp = pathsList() { line.setProperty(AclLine.PROP_PATHS, tmp); }
+ )
+ <EOL>
+
+ {
+ lines.add(line);
+ }
+}
+
+AclLine privilegesLineOperation() :
+{}
+{
+ (
+ <REMOVE> { return new AclLine(AclLine.Action.REMOVE); }
+ | ( <ALLOW> { return new AclLine(AclLine.Action.ALLOW); } )
+ | ( <DENY> { return new AclLine(AclLine.Action.DENY); } )
+ )
+}
+
+void userPrivilegesLine(List<AclLine> lines) :
+{
+ AclLine line;
+ List<String> tmp;
+}
+{
+ line = privilegesLineOperation()
+ tmp = namespacedItemsList() { line.setProperty(AclLine.PROP_PRIVILEGES, tmp); }
+ <FOR>
+ tmp = principalsList() { line.setProperty(AclLine.PROP_PRINCIPALS, tmp); }
+ <EOL>
+
+ {
+ lines.add(line);
+ }
+}
+
+void pathPrivilegesLine(List<AclLine> lines) :
+{
+ AclLine line;
+ List<String> tmp;
+}
+{
+ line = privilegesLineOperation()
+ tmp = namespacedItemsList() { line.setProperty(AclLine.PROP_PRIVILEGES, tmp); }
+ <ON> tmp = pathsList() { line.setProperty(AclLine.PROP_PATHS, tmp); }
+ ( <NODETYPES> tmp = namespacedItemsList() { line.setProperty(AclLine.PROP_NODETYPES, tmp); }) ?
+ <EOL>
+
+ {
+ lines.add(line);
+ }
+}
+
+void setAclPrincipals(List<Operation> result) :
+{
+ List <String> principals;
+ List<AclLine> lines = new ArrayList<AclLine>();
+}
+{
+ <SET> <ACL> <FOR> principals = principalsList() <EOL>
+ ( removeStarLine(lines) | pathPrivilegesLine(lines) | blankLine() ) +
+ <END>
+ ( <EOL> | <EOF> )
+
+ {
+ result.add(new SetAclPrincipals(principals, lines));
+ }
+}
diff --git a/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java b/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java
new file mode 100644
index 0000000..a439549
--- /dev/null
+++ b/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java
@@ -0,0 +1,87 @@
+/*
+ * 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 java.io.PrintWriter;
+import java.util.Collection;
+
+import org.apache.sling.repoinit.parser.operations.AclLine;
+import org.apache.sling.repoinit.parser.operations.CreatePath;
+import org.apache.sling.repoinit.parser.operations.CreateServiceUser;
+import org.apache.sling.repoinit.parser.operations.DeleteServiceUser;
+import org.apache.sling.repoinit.parser.operations.OperationVisitor;
+import org.apache.sling.repoinit.parser.operations.SetAclPaths;
+import org.apache.sling.repoinit.parser.operations.SetAclPrincipals;
+
+/** OperationVisitor that dumps the operations using
+ * their toString() methods
+ */
+class OperationToStringVisitor implements OperationVisitor {
+
+ private final PrintWriter out;
+
+ OperationToStringVisitor(PrintWriter pw) {
+ out = pw;
+ }
+
+ @Override
+ public void visitCreateServiceUser(CreateServiceUser s) {
+ out.println(s.toString());
+ }
+
+ @Override
+ public void visitDeleteServiceUser(DeleteServiceUser s) {
+ out.println(s.toString());
+ }
+
+ @Override
+ public void visitSetAclPrincipal(SetAclPrincipals s) {
+ out.print(s.getClass().getSimpleName());
+ out.print(" for ");
+ for(String p : s.getPrincipals()) {
+ out.print(p);
+ out.print(' ');
+ }
+ out.println();
+ dumpAclLines(s.getLines());
+ }
+
+ @Override
+ public void visitSetAclPaths(SetAclPaths s) {
+ out.print(s.getClass().getSimpleName());
+ out.print(" on ");
+ for(String p : s.getPaths()) {
+ out.print(p);
+ out.print(' ');
+ }
+ out.println();
+ dumpAclLines(s.getLines());
+ }
+
+ @Override
+ public void visitCreatePath(CreatePath cp) {
+ out.println(cp.toString());
+ }
+
+ private void dumpAclLines(Collection<AclLine> c) {
+ for(AclLine line : c) {
+ out.print(" ");
+ out.println(line);
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/repoinit/parser/test/ParserServiceTest.java b/src/test/java/org/apache/sling/repoinit/parser/test/ParserServiceTest.java
new file mode 100644
index 0000000..41a0495
--- /dev/null
+++ b/src/test/java/org/apache/sling/repoinit/parser/test/ParserServiceTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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 java.io.Reader;
+import java.io.StringReader;
+
+import org.apache.sling.repoinit.parser.RepoInitParsingException;
+import org.apache.sling.repoinit.parser.impl.RepoInitParserService;
+import org.junit.Test;
+
+public class ParserServiceTest {
+ @Test
+ public void noErrors() throws RepoInitParsingException {
+ final Reader r = new StringReader("create service user foo");
+ new RepoInitParserService().parse(r);
+ }
+
+ @Test(expected = RepoInitParsingException.class)
+ public void syntaxError() throws RepoInitParsingException {
+ final Reader r = new StringReader("not a valid statement");
+ new RepoInitParserService().parse(r);
+ }
+}
diff --git a/src/test/java/org/apache/sling/repoinit/parser/test/ParserTest.java b/src/test/java/org/apache/sling/repoinit/parser/test/ParserTest.java
new file mode 100644
index 0000000..94c77e2
--- /dev/null
+++ b/src/test/java/org/apache/sling/repoinit/parser/test/ParserTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.sling.repoinit.parser.impl.ParseException;
+import org.apache.sling.repoinit.parser.impl.RepoInitParserImpl;
+import org.apache.sling.repoinit.parser.operations.Operation;
+import org.apache.sling.repoinit.parser.operations.OperationVisitor;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/** 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 ParserTest {
+
+ public static final String DEFAULT_ENCODING = "UTF-8";
+
+ static class TestCase {
+ final InputStream input;
+ final String inputFilename;
+ final InputStream expected;
+ final String outputFilename;
+
+ private static final String PREFIX = "/testcases/test-";
+
+ @Override
+ public String toString() {
+ return inputFilename;
+ }
+
+ private TestCase(int index) {
+ inputFilename = PREFIX + index + ".txt";
+ input = getClass().getResourceAsStream(inputFilename);
+ outputFilename = PREFIX + index + "-output.txt";
+ expected = getClass().getResourceAsStream(outputFilename);
+ }
+
+ static TestCase build(int index) {
+ final TestCase result = new TestCase(index);
+ if(result.input == null || result.expected == null) {
+ return null;
+ }
+ return result;
+ }
+
+ void close() {
+ try {
+ input.close();
+ } catch(IOException ignored) {
+ }
+ try {
+ expected.close();
+ } catch(IOException ignored) {
+ }
+ }
+ }
+
+ private final TestCase tc;
+
+ @Parameters(name="{0}")
+ public static Collection<Object[]> data() {
+ final List<Object []> result = new ArrayList<Object[]>();
+ for(int i=0; i < 100; i++) {
+ final TestCase tc = TestCase.build(i);
+ if(tc != null) {
+ result.add(new Object[] { tc });
+ }
+ }
+ return result;
+
+ }
+
+ public ParserTest(TestCase tc) {
+ this.tc = tc;
+ }
+
+ @Test
+ public void checkResult() throws ParseException, IOException {
+ final String expected = IOUtils.toString(tc.expected, DEFAULT_ENCODING).trim();
+ try {
+ final StringWriter sw = new StringWriter();
+ final OperationVisitor v = new OperationToStringVisitor(new PrintWriter(sw));
+ final List<Operation> result = new RepoInitParserImpl(tc.input).parse();
+ for(Operation o : result) {
+ o.accept(v);
+ }
+ sw.flush();
+ String actual = sw.toString().trim();
+
+ // normalize line endings to ensure tests run on windows as well
+ actual = actual.replaceAll("\r\n", "\n");
+
+ assertEquals(expected, actual);
+ } finally {
+ tc.close();
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/repoinit/parser/test/ParsingErrorsTest.java b/src/test/java/org/apache/sling/repoinit/parser/test/ParsingErrorsTest.java
new file mode 100644
index 0000000..fb46eef
--- /dev/null
+++ b/src/test/java/org/apache/sling/repoinit/parser/test/ParsingErrorsTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.sling.repoinit.parser.impl.ParseException;
+import org.apache.sling.repoinit.parser.impl.RepoInitParserImpl;
+import org.apache.sling.repoinit.parser.impl.TokenMgrError;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/** Test various parsing errors */
+@RunWith(Parameterized.class)
+public class ParsingErrorsTest {
+
+ private String input;
+ private Class<? extends Throwable> expected;
+
+ @Parameters
+ public static Collection<Object[]> data() {
+ @SuppressWarnings("serial")
+ final List<Object []> result = new ArrayList<Object []>() {{
+ add(new Object[] { "foo", ParseException.class });
+ add(new Object[] { "12", ParseException.class });
+
+ add(new Object[] { "set ACL on /apps \n remove * for u \n end", null });
+ add(new Object[] { "set ACL on /apps \n badkeyword * for u \n end", ParseException.class });
+ add(new Object[] { "set ACL on appsWithoutSlash \n remove * for u \n end", ParseException.class });
+ add(new Object[] { "set ACL", ParseException.class });
+ add(new Object[] { "set ACL \n end", ParseException.class });
+
+ add(new Object[] { "create service user bob, alice, tom21", null });
+ add(new Object[] { "create service user bob-221_BOB", null });
+ add(new Object[] { "create service user bob/221", ParseException.class });
+ add(new Object[] { "create service user bob,/alice, tom21", ParseException.class });
+ add(new Object[] { "create service user bob,alice,tom21 # comment not allowed here", TokenMgrError.class });
+ add(new Object[] { "CREATE service user bob, alice, tom21", ParseException.class });
+ add(new Object[] { "create SERVICE user bob, alice, tom21", ParseException.class });
+ }};
+ return result;
+ }
+
+ public ParsingErrorsTest(String input, Class<? extends Throwable> expected) {
+ this.input = input;
+ this.expected = expected;
+ }
+
+ @Test
+ public void checkResult() throws ParseException, IOException {
+ final StringReader r = new StringReader(input);
+ try {
+ new RepoInitParserImpl(r).parse();
+ if(expected != null) {
+ fail("Expected a " + expected.getSimpleName() + " for [" + input + "]");
+ }
+ } catch(Exception e) {
+ assertEquals(expected, e.getClass());
+ } catch(Error err) {
+ assertEquals(expected, err.getClass());
+ } finally {
+ r.close();
+ }
+ }
+}
diff --git a/src/test/resources/testcases/test-1-output.txt b/src/test/resources/testcases/test-1-output.txt
new file mode 100644
index 0000000..d4fde81
--- /dev/null
+++ b/src/test/resources/testcases/test-1-output.txt
@@ -0,0 +1,4 @@
+CreateServiceUser bob
+CreateServiceUser alice
+CreateServiceUser tom21
+CreateServiceUser lonesome
diff --git a/src/test/resources/testcases/test-1.txt b/src/test/resources/testcases/test-1.txt
new file mode 100644
index 0000000..1ad451a
--- /dev/null
+++ b/src/test/resources/testcases/test-1.txt
@@ -0,0 +1,2 @@
+create service user bob,alice, tom21
+create service user lonesome
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-10-output.txt b/src/test/resources/testcases/test-10-output.txt
new file mode 100644
index 0000000..c9106ac
--- /dev/null
+++ b/src/test/resources/testcases/test-10-output.txt
@@ -0,0 +1,5 @@
+SetAclPaths on /libs /apps / /content/example.com/some-other_path
+ AclLine REMOVE_ALL {principals=[user1, user2]}
+ AclLine ALLOW {principals=[user1, user2], privileges=[jcr:read]}
+ AclLine DENY {principals=[user2], privileges=[jcr:write, something:else, another:one]}
+ AclLine DENY {principals=[user1], privileges=[jcr:lockManagement]}
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-10.txt b/src/test/resources/testcases/test-10.txt
new file mode 100644
index 0000000..db91e9f
--- /dev/null
+++ b/src/test/resources/testcases/test-10.txt
@@ -0,0 +1,10 @@
+# Set ACL example from SLING-5355
+# Without the "with glob" option, we're not planning to support
+# that at this time.
+set ACL on /libs,/apps, /, /content/example.com/some-other_path
+ remove * for user1,user2
+ allow jcr:read for user1,user2
+
+ deny jcr:write,something:else,another:one for user2
+ deny jcr:lockManagement for user1
+end
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-11-output.txt b/src/test/resources/testcases/test-11-output.txt
new file mode 100644
index 0000000..aceed38
--- /dev/null
+++ b/src/test/resources/testcases/test-11-output.txt
@@ -0,0 +1,5 @@
+SetAclPaths on /libs /apps
+ AclLine REMOVE_ALL {principals=[user1, user2]}
+ AclLine ALLOW {principals=[user1, user2], privileges=[jcr:read]}
+ AclLine REMOVE_ALL {principals=[another]}
+ AclLine ALLOW {principals=[another], privileges=[x:y]}
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-11.txt b/src/test/resources/testcases/test-11.txt
new file mode 100644
index 0000000..7d27a2a
--- /dev/null
+++ b/src/test/resources/testcases/test-11.txt
@@ -0,0 +1,8 @@
+# Test multiple remove lines
+set ACL on /libs,/apps
+ remove * for user1,user2
+ allow jcr:read for user1,user2
+
+ remove * for another
+ allow x:y for another
+end
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-2-output.txt b/src/test/resources/testcases/test-2-output.txt
new file mode 100644
index 0000000..d2b3951
--- /dev/null
+++ b/src/test/resources/testcases/test-2-output.txt
@@ -0,0 +1,3 @@
+CreateServiceUser Mark-21
+DeleteServiceUser Leonardo
+DeleteServiceUser Winston_32
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-2.txt b/src/test/resources/testcases/test-2.txt
new file mode 100644
index 0000000..c0c7b7e
--- /dev/null
+++ b/src/test/resources/testcases/test-2.txt
@@ -0,0 +1,2 @@
+create service user Mark-21
+delete service user Leonardo,Winston_32
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-20-output.txt b/src/test/resources/testcases/test-20-output.txt
new file mode 100644
index 0000000..68fa997
--- /dev/null
+++ b/src/test/resources/testcases/test-20-output.txt
@@ -0,0 +1,4 @@
+CreatePath [var(sling:Folder), discovery(nt:unstructured), somefolder(sling:Folder)]
+CreatePath [one, two, three]
+CreatePath [three, four(nt:folk), five(nt:jazz), six]
+CreatePath [seven(nt:x), eight(nt:x), nine(nt:x)]
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-20.txt b/src/test/resources/testcases/test-20.txt
new file mode 100644
index 0000000..30f1355
--- /dev/null
+++ b/src/test/resources/testcases/test-20.txt
@@ -0,0 +1,5 @@
+# Various create path tests
+create path (sling:Folder) /var/discovery(nt:unstructured)/somefolder
+create path /one/two/three
+create path /three/four(nt:folk)/five(nt:jazz)/six
+create path (nt:x) /seven/eight/nine
diff --git a/src/test/resources/testcases/test-3-output.txt b/src/test/resources/testcases/test-3-output.txt
new file mode 100644
index 0000000..0178953
--- /dev/null
+++ b/src/test/resources/testcases/test-3-output.txt
@@ -0,0 +1 @@
+CreateServiceUser comments_test_passed
diff --git a/src/test/resources/testcases/test-3.txt b/src/test/resources/testcases/test-3.txt
new file mode 100644
index 0000000..49f1c07
--- /dev/null
+++ b/src/test/resources/testcases/test-3.txt
@@ -0,0 +1,10 @@
+#
+# single-word
+# We're testing the comments now
+# This is A COMMENT with other things like 12, 34
+# And now for a tag, <ok> ?
+# And some punctuation: .,;-_[]+"*ç%&/()=?^`"
+ # Also with leading whitespace.
+
+# blank lines work, of course
+create service user comments_test_passed
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-30-output.txt b/src/test/resources/testcases/test-30-output.txt
new file mode 100644
index 0000000..e619a2f
--- /dev/null
+++ b/src/test/resources/testcases/test-30-output.txt
@@ -0,0 +1,6 @@
+SetAclPrincipals for user1 u2
+ AclLine REMOVE_ALL {paths=[/libs, /apps]}
+ AclLine ALLOW {paths=[/content], privileges=[jcr:read]}
+ AclLine DENY {paths=[/apps], privileges=[jcr:write]}
+ AclLine DENY {nodetypes=[sling:Folder, nt:unstructured], paths=[/apps, /content], privileges=[jcr:lockManagement]}
+ AclLine REMOVE {paths=[/apps], privileges=[jcr:understand, some:other]}
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-30.txt b/src/test/resources/testcases/test-30.txt
new file mode 100644
index 0000000..c70f928
--- /dev/null
+++ b/src/test/resources/testcases/test-30.txt
@@ -0,0 +1,12 @@
+# Test the principal-centered ACL syntax
+
+set ACL for user1,u2
+ remove * on /libs,/apps
+ allow jcr:read on /content
+
+ deny jcr:write on /apps
+
+ # Optional nodetypes clause
+ deny jcr:lockManagement on /apps, /content nodetypes sling:Folder, nt:unstructured
+ remove jcr:understand,some:other on /apps
+end
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-99-output.txt b/src/test/resources/testcases/test-99-output.txt
new file mode 100644
index 0000000..2761b1b
--- /dev/null
+++ b/src/test/resources/testcases/test-99-output.txt
@@ -0,0 +1,19 @@
+CreateServiceUser user1
+CreateServiceUser u-ser_2
+SetAclPaths on /libs /apps
+ AclLine REMOVE_ALL {principals=[user1, u-ser_2]}
+ AclLine ALLOW {principals=[user1, u-ser_2], privileges=[jcr:read]}
+ AclLine DENY {principals=[u-ser_2], privileges=[jcr:write]}
+ AclLine DENY {principals=[user1], privileges=[jcr:lockManagement]}
+ AclLine REMOVE {principals=[u3], privileges=[jcr:understand, some:other]}
+CreateServiceUser bob_the_service
+SetAclPaths on /tmp
+ AclLine ALLOW {principals=[bob_the_service], privileges=[some:otherPrivilege]}
+CreatePath [content, example.com(sling:Folder)]
+CreatePath [var(nt:unstructured)]
+SetAclPrincipals for alice bob fred
+ AclLine REMOVE_ALL {paths=[/]}
+ AclLine ALLOW {paths=[/content, /var], privileges=[jcr:read]}
+ AclLine DENY {paths=[/content/example.com], privileges=[jcr:write]}
+ AclLine DENY {nodetypes=[example:Page], paths=[/], privileges=[jcr:all]}
+CreateServiceUser the-last-one
\ No newline at end of file
diff --git a/src/test/resources/testcases/test-99.txt b/src/test/resources/testcases/test-99.txt
new file mode 100644
index 0000000..df013a8
--- /dev/null
+++ b/src/test/resources/testcases/test-99.txt
@@ -0,0 +1,31 @@
+# Complete example with several intermixed statement types
+
+create service user user1, u-ser_2
+set ACL on /libs,/apps
+ remove * for user1,u-ser_2
+ allow jcr:read for user1,u-ser_2
+
+ deny jcr:write for u-ser_2
+ deny jcr:lockManagement for user1
+ remove jcr:understand,some:other for u3
+end
+
+create service user bob_the_service
+
+# Verify that indent is not required
+set ACL on /tmp
+allow some:otherPrivilege for bob_the_service
+end
+
+create path /content/example.com(sling:Folder)
+create path (nt:unstructured) /var
+
+set ACL for alice, bob,fred
+ remove * on /
+ allow jcr:read on /content,/var
+ deny jcr:write on /content/example.com
+ deny jcr:all on / nodetypes example:Page
+
+end
+
+create service user the-last-one
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.