| /* JavaCC grammar for the SLING-5449 content repository |
| * initialization language |
| * See https://javacc.java.net/doc/docindex.html for the JavaCC docs |
| * and http://www.engr.mun.ca/~theo/JavaCC-FAQ/javacc-faq-moz.htm for the FAQ |
| */ |
| |
| options |
| { |
| STATIC=false; |
| LOOKAHEAD=3; |
| //FORCE_LA_CHECK=true; |
| //DEBUG_PARSER=true; |
| //DEBUG_LOOKAHEAD=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" > |
| | < DISABLE: "disable" > |
| | < SERVICE: "service" > |
| | < MIXIN: "mixin" > |
| | < PATH: "path" > |
| | < END: "end" > |
| | < REPOSITORY: "repository" > |
| | < PRINCIPAL: "principal" > |
| | < USER: "user" > |
| | < GROUP: "group" > |
| | < NODETYPES: "nodetypes" > |
| | < REGISTER: "register" > |
| | < NAMESPACE: "namespace" > |
| | < PRIVILEGE: "privilege" > |
| | < WITH: "with" > |
| | < ABSTRACT: "abstract" > |
| | < PASSWORD: "password" > |
| | < START_TEXTBLOCK: "<<===" > : TEXTBLOCK |
| | < LPAREN: "(" > |
| | < RPAREN: ")" > |
| | < LCURLY: "{" > |
| | < RCURLY: "}" > |
| | < COMMA: "," > |
| | < DQUOTE: "\"" > |
| | < COLON: ":" > |
| | < STAR: "*" > |
| | < EQUALS: "=" > |
| | < RESTRICTION: "restriction" > |
| | < ACL_OPTIONS: "ACLOptions" > |
| |
| /* The order of these fuzzy statements is important (first match wins?) */ |
| | < NAMESPACED_ITEM: (["a"-"z"] | ["A"-"Z"])+ ":" (["a"-"z"] | ["A"-"Z"])+ > |
| | < PATH_STRING: "/" (["a"-"z"] | ["A"-"Z"] | ["0"-"9"] | ["-"] | ["_"] | ["."] | ["@"] | [":"] | ["+"] | ["/"]) * > |
| | < PATH_REPOSITORY: ":repository" > |
| | < STRING: (["a"-"z"] | ["A"-"Z"] | ["0"-"9"] | ["-"] | ["_"] | ["."] | ["/"] | [":"] | ["*"]) + > |
| | < EOL: "\n" > |
| } |
| |
| /* Found out about this syntax later - would make STRING etc. simpler */ |
| TOKEN: { |
| <QUOTED: |
| <DQUOTE> |
| ( |
| "\\" ~[] // escaped chars |
| | |
| ~["\\","\""] //any char but not backslash nor quote |
| )* |
| <DQUOTE> |
| > |
| } |
| |
| <TEXTBLOCK> SKIP : |
| { |
| "\r" |
| } |
| |
| <TEXTBLOCK> TOKEN : |
| { |
| < TEXT : ~[] > |
| | < END_TEXTBLOCK: "===>>" > : DEFAULT |
| } |
| |
| List<Operation> parse() : |
| {} |
| { |
| { final List<Operation> result = new ArrayList<Operation>(); } |
| |
| ( |
| serviceUserStatement(result) |
| | setAclPaths(result) |
| | setAclPrincipals(result) |
| | setAclPrincipalBased(result) |
| | setAclRepository(result) |
| | createPathStatement(result) |
| | registerNamespaceStatement(result) |
| | registerNodetypesStatement(result) |
| | registerPrivilegeStatement(result) |
| | createGroupStatement(result) |
| | deleteGroupStatement(result) |
| | createUserStatement(result) |
| | deleteUserStatement(result) |
| | disableServiceUserStatement(result) |
| | blankLine() |
| ) * |
| <EOF> |
| |
| { return result; } |
| } |
| |
| void blankLine() : |
| {} |
| { |
| <EOL> |
| } |
| |
| List<String> principalsList() : |
| { |
| Token t = null; |
| List<String> principals = new ArrayList<String>(); |
| } |
| { |
| t = <STRING> { principals.add(t.image); } |
| ( <COMMA> t = <STRING> { principals.add(t.image); } )* |
| { return principals; } |
| } |
| |
| String withPathStatement() : |
| { |
| Token t = null; |
| } |
| { |
| /* accept relative (string) or absolute path */ |
| <WITH> <PATH> ( t=<STRING> | t=<PATH_STRING> ) |
| { return t.image; } |
| } |
| |
| void serviceUserStatement(List<Operation> result) : |
| { |
| Token t; |
| List<String> principals; |
| String path = null; |
| } |
| { |
| (t=<CREATE> | t=<DELETE>) |
| <SERVICE> <USER> |
| principals = principalsList() |
| ( path = withPathStatement() ) ? |
| (<EOL> | <EOF>) |
| |
| { |
| for(String principal : principals) { |
| if(CREATE == t.kind) { |
| result.add(new CreateServiceUser(principal, path)); |
| } 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> | t = <PATH_REPOSITORY> ) { paths.add(t.image); } |
| ( <COMMA> ( t = <PATH_STRING> | t = <PATH_REPOSITORY> ) { paths.add(t.image); } )* |
| { return paths; } |
| } |
| |
| void createPathStatement(List<Operation> result) : |
| { |
| CreatePath cp = null; |
| String defaultPrimaryType = null; |
| Token t1 = null; |
| Token t2 = null; |
| List<String> t3 = null; |
| } |
| { |
| <CREATE> <PATH> |
| ( <LPAREN> t1 = <NAMESPACED_ITEM> <RPAREN> { defaultPrimaryType = t1.image; } ) ? |
| |
| ( t1 = <PATH_STRING> ( <LPAREN> t2 = <NAMESPACED_ITEM> <RPAREN> ) ? |
| ( <LPAREN> <MIXIN> t3 = namespacedItemsList() <RPAREN>) ? |
| ( <LPAREN> t2 = <NAMESPACED_ITEM> <MIXIN> t3 = namespacedItemsList() <RPAREN>) ? |
| { |
| if(cp == null) { |
| cp = new CreatePath(defaultPrimaryType); |
| } |
| cp.addSegment(t1.image, t2 == null ? null : t2.image, t3); |
| t2 = null; |
| t3 = null; |
| } |
| ) + |
| |
| (<EOL> | <EOF>) |
| |
| { if(cp != null) result.add(cp); } |
| } |
| |
| void setAclPaths(List<Operation> result) : |
| { |
| List<String> paths; |
| List<AclLine> lines = new ArrayList<AclLine>(); |
| List<String> aclOptions; |
| } |
| { |
| <SET> <ACL> <ON> paths = pathsList() aclOptions=aclOptions() <EOL> |
| ( removeStarLine(lines) | userPrivilegesLine(lines) | blankLine() ) + |
| <END> |
| ( <EOL> | <EOF> ) |
| |
| { |
| result.add(new SetAclPaths(paths, lines, aclOptions)); |
| } |
| } |
| |
| 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; |
| List<RestrictionClause> restrictions; |
| } |
| { |
| line = privilegesLineOperation() |
| tmp = namespacedItemsList() { line.setProperty(AclLine.PROP_PRIVILEGES, tmp); } |
| <FOR> |
| tmp = principalsList() { line.setProperty(AclLine.PROP_PRINCIPALS, tmp); } |
| restrictions = restrictions() { line.setRestrictions(restrictions); } |
| <EOL> |
| |
| { |
| lines.add(line); |
| } |
| } |
| /** |
| * A single restriction value |
| */ |
| void restrictionValue(List<String> values) : |
| { |
| Token t; |
| } |
| { |
| <COMMA> ( t=<STAR> | t=<NAMESPACED_ITEM> | t=<PATH_STRING> | t=<STRING> ) |
| { |
| values.add(t.image); |
| } |
| } |
| |
| /** |
| * A list of restriction values |
| */ |
| List<String> restrictionValues() : |
| { |
| List<String> values = new ArrayList<String>(); |
| } |
| { |
| ( restrictionValue(values) ) * |
| |
| { |
| return values; |
| } |
| |
| } |
| |
| |
| /** |
| * A single restriction |
| */ |
| void restriction(List<RestrictionClause> restrictions) : |
| { |
| Token restrictionProp; |
| List<String> values; |
| } |
| { |
| <RESTRICTION> |
| <LPAREN> restrictionProp=<NAMESPACED_ITEM> values=restrictionValues() <RPAREN> |
| |
| { |
| restrictions.add(new RestrictionClause(restrictionProp.image,values)); |
| } |
| } |
| |
| /** |
| * A list of restrictions |
| */ |
| List<RestrictionClause> restrictions() : |
| { |
| List<RestrictionClause> restrictions = new ArrayList<RestrictionClause>(); |
| } |
| { |
| ( restriction(restrictions) )* |
| |
| { |
| return restrictions; |
| } |
| } |
| |
| void pathPrivilegesLine(List<AclLine> lines) : |
| { |
| AclLine line; |
| List<String> tmp; |
| List<RestrictionClause> restrictions; |
| } |
| { |
| 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); }) ? |
| restrictions = restrictions() { line.setRestrictions(restrictions); } |
| <EOL> |
| |
| { |
| lines.add(line); |
| } |
| } |
| void aclOption(List<String> options) : |
| { |
| Token t; |
| } |
| { |
| (t=<NAMESPACED_ITEM> | t=<STRING>) |
| { |
| options.add(t.image); |
| } |
| } |
| List<String> aclOptions() : |
| { |
| List<String> aclOptionList = new ArrayList<String>(); |
| Token t; |
| } |
| { |
| ( <LPAREN> <ACL_OPTIONS> <EQUALS> aclOption(aclOptionList) ( <COMMA> aclOption(aclOptionList) )* <RPAREN> )? |
| |
| { |
| return aclOptionList; |
| } |
| } |
| |
| void setAclRepository(List<Operation> result) : |
| { |
| List<AclLine> lines = new ArrayList<AclLine>(); |
| List<String> principals; |
| List<String> privileges; |
| List<String> aclOptions; |
| AclLine line = null; |
| |
| } |
| { |
| <SET> <REPOSITORY> <ACL> <FOR> principals = principalsList() aclOptions=aclOptions() <EOL> |
| ( |
| ( <REMOVE> <STAR> ) |
| { |
| line = new AclLine(AclLine.Action.REMOVE_ALL); |
| lines.add(line); |
| } |
| | ( line = privilegesLineOperation() privileges = namespacedItemsList() ) |
| { |
| line.setProperty(AclLine.PROP_PRIVILEGES, privileges); |
| lines.add(line); |
| } |
| | ( blankLine() ) |
| )+ |
| <END> |
| ( <EOL> | <EOF> ) |
| |
| { |
| result.add(new SetAclPrincipals(principals, lines, aclOptions)); |
| } |
| } |
| |
| void setAclPrincipals(List<Operation> result) : |
| { |
| List <String> principals; |
| List<AclLine> lines = new ArrayList<AclLine>(); |
| List<String> aclOptions; |
| } |
| { |
| <SET> <ACL> <FOR> principals = principalsList() aclOptions=aclOptions() <EOL> |
| ( removeStarLine(lines) | pathPrivilegesLine(lines) | blankLine() ) + |
| <END> |
| ( <EOL> | <EOF> ) |
| |
| { |
| result.add(new SetAclPrincipals(principals, lines, aclOptions)); |
| } |
| } |
| |
| void setAclPrincipalBased(List<Operation> result) : |
| { |
| List <String> principals; |
| List<AclLine> lines = new ArrayList<AclLine>(); |
| List<String> aclOptions; |
| } |
| { |
| <SET> <PRINCIPAL> <ACL> <FOR> principals = principalsList() aclOptions=aclOptions() <EOL> |
| ( removeStarLine(lines) | pathPrivilegesLine(lines) | blankLine() ) + |
| <END> |
| ( <EOL> | <EOF> ) |
| |
| { |
| result.add(new SetAclPrincipalBased(principals, lines, aclOptions)); |
| } |
| } |
| |
| void registerNamespaceStatement(List<Operation> result) : |
| { |
| Token prefix = null; |
| Token uri; |
| } |
| { |
| <REGISTER> <NAMESPACE> |
| <LPAREN> prefix = <STRING> <RPAREN> |
| uri = <STRING> |
| |
| { |
| result.add(new RegisterNamespace(prefix.image, uri.image)); |
| } |
| |
| (<EOL> | <EOF>) |
| } |
| |
| void registerPrivilegeStatement(List<Operation> result) : |
| { |
| Token privilege; |
| boolean isAbstract = false; |
| List<String> aggregates = new ArrayList<String>(); |
| } |
| { |
| <REGISTER> ((<ABSTRACT>) {isAbstract = true;})? <PRIVILEGE> (privilege = <STRING> | privilege = <NAMESPACED_ITEM>) (<WITH> aggregates = principalsList())? |
| { |
| result.add(new RegisterPrivilege(privilege.image, isAbstract, aggregates)); |
| } |
| (<EOL> | <EOF>) |
| } |
| |
| void textBlock(StringBuilder b) : |
| { |
| Token t; |
| } |
| { |
| <START_TEXTBLOCK> |
| ( t = <TEXT> { b.append(t.image); } )* |
| <END_TEXTBLOCK> |
| } |
| |
| void registerNodetypesStatement(List<Operation> result) : |
| { |
| StringBuilder b = new StringBuilder(); |
| } |
| { |
| <REGISTER> <NODETYPES> <EOL> |
| textBlock(b) |
| (<EOL> | <EOF>) |
| { |
| result.add(new RegisterNodetypes(b.toString())); |
| } |
| } |
| |
| void createGroupStatement(List<Operation> result) : |
| { |
| Token group = null; |
| Token encoding = null; |
| String path = null; |
| } |
| { |
| <CREATE> <GROUP> |
| ( group = <STRING> ) |
| ( path = withPathStatement() ) ? |
| |
| { |
| result.add(new CreateGroup(group.image, |
| path |
| )); |
| } |
| } |
| |
| void deleteGroupStatement(List<Operation> result) : |
| { |
| Token group = null; |
| } |
| { |
| <DELETE> <GROUP> |
| ( group = <STRING> ) |
| |
| { |
| result.add(new DeleteGroup(group.image)); |
| } |
| } |
| |
| void createUserStatement(List<Operation> result) : |
| { |
| Token user = null; |
| Token encoding = null; |
| Token password = null; |
| String path = null; |
| } |
| { |
| <CREATE> <USER> |
| ( user = <STRING> ) |
| ( path = withPathStatement() ) ? |
| ( <WITH> <PASSWORD> ( <LCURLY> encoding = <STRING> <RCURLY> )? password = <STRING> )? |
| |
| { |
| result.add(new CreateUser(user.image, |
| (encoding == null ? null : encoding.image), |
| (password == null ? null : password.image), |
| path |
| )); |
| } |
| } |
| |
| void deleteUserStatement(List<Operation> result) : |
| { |
| Token user = null; |
| } |
| { |
| <DELETE> <USER> |
| ( user = <STRING> ) |
| |
| { |
| result.add(new DeleteUser(user.image)); |
| } |
| } |
| |
| void disableServiceUserStatement(List<Operation> result) : |
| { |
| Token user = null; |
| Token msg = null; |
| } |
| { |
| <DISABLE> <SERVICE> <USER> |
| ( user = <STRING> ) |
| ( <COLON> msg = <QUOTED> ) |
| { |
| result.add(new DisableServiceUser(user.image, msg == null ? null : msg.image)); |
| } |
| } |