Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.getperka.flatpack.policy;
  
  /*
   * #%L
   * FlatPack Security Policy
   * %%
   * Copyright (C) 2012 - 2013 Perka Inc.
   * %%
   * Licensed 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.
  * #L%
  */
 
 import java.util.List;
 
 
The grammar definition for the policy file.

The method names in this type use parboiled's naming scheme, where methods returning org.parboiled.Rule objects are named with a capitalized first letter. Since most rules will push an object onto the value stack, the rules are generally named in accordance with the object type that they will push.

Also note that due to parboiled's extensive class rewriting, the code-coverage numbers on this class are completely wrong.

 
 class PolicyParser extends BaseParser<Object> {
   private static final String WILDCARD = "*";
   private static final PolicyParser parser = Parboiled.createParser(PolicyParser.class);

  
Return a new instance of a PolicyParser.
 
   public static PolicyParser get() {
     return .newInstance();
   }

  
The top-level parse rule.
 
   public Rule PolicyFile() {
     Var<PolicyFilex = new Var<PolicyFile>(new PolicyFile());
     return Sequence(
         PolicyBlock(x),
         );
   }

  
Tweak the value-stack push method to record the line number on which the current rule started.
 
   @Override
   public boolean push(Object value) {
     if (value instanceof PolicyNode) {
       PolicyNode x = (PolicyNodevalue;
       int startIndex = getContext().getStartIndex();
       x.setLineNumber(getContext().getInputBuffer().getPosition(startIndex).);
    }
    return super.push(value);
  }

  
Makes string literals passed to Rule objects also consume any trailing whitespace.
  protected Rule fromStringLiteral(String string) {
    return Sequence(String(string), WS());
  }

  
An individual ACL rule:
 groupName none
 
 groupName to verbName.actionName
 
 inheritedProperty.groupName to ...
 
  Rule AclRule() {
    return Sequence(
        FirstOf(
            Sequence(
                Ident(Property.class),
                ".",
                Ident(SecurityGroup.class),
                new Action<Object>() {
                  @Override
                  public boolean run(Context<Objectctx) {
                    Ident<SecurityGroupgroup = popIdent(SecurityGroup.class);
                    Ident<Propertyproperty = popIdent(Property.class);
                    push(new Ident<SecurityGroup>(SecurityGroup.classpropertygroup));
                    return true;
                  }
                }),
            WildcardOrIdent(SecurityGroup.class)),
        FirstOf(
            // Special syntax for a zero-length list
            Sequence("none"ACTION(push(new ArrayList<Ident<SecurityAction>>()))),
            // Or require at least one
            Sequence(
                "to",
                OneOrListOf(VerbActionOrWildcard(), Ident.class",")
            )
        ),
        new Action<Object>() {
          @Override
          public boolean run(Context<Objectctx) {
            AllowRule x = new AllowRule();
            x.setSecurityActions(popIdentList(SecurityAction.class));
            x.setGroupName(popIdent(SecurityGroup.class));
            push(x);
            return true;
          }
        });
  }

  
Defines an action verb.
 verb name = action, anotherAction, ...;
 
  Rule ActionDef() {
    final Var<ActionDefinitionvar = new Var<ActionDefinition>(new ActionDefinition());
    return Sequence(
        "action",
        NodeName(ActionDefinition.classvar),
        "=",
        OneOrListOf(Ident(SecurityAction.class), Ident.class","),
        ";",
        new Action<Object>() {
          @Override
          public boolean run(Context<Objectctx) {
            ActionDefinition x = var.get();
            x.setActions(popIdentList(SecurityAction.class));
            push(x);
            return true;
          }
        });
  }

  
An inheritable block which holds zero or more com.getperka.flatpack.policy.pst.AllowRule. Also supports a single-line version.
 allow [ only ] [ inherit somePropertyName ] {
   aclRule;
   ...;
   aclRule;
 }
 
 allow [ inherit somePropertyName ] [ aclRule ];
 
  Rule Allow() {
    final Var<AllowBlockvar = new Var<AllowBlock>(new AllowBlock());
    final Var<Booleanonly = new Var<Boolean>(false);
    return Sequence(
        "allow",
        Optional("only"ACTION(only.set(true))),
        MaybeInherit(Property.classvar),
        ZeroOneOrBlock(AclRule(), AllowRule.class),
        new Action<Object>() {
          @Override
          @SuppressWarnings("unchecked")
          public boolean run(Context<Objectctx) {
            AllowBlock x = var.get();
            x.setAclRules((List<AllowRule>) pop());
            x.setOnly(only.get());
            push(x);
            return true;
          }
        });
  }

  
Implement single-line and multi-line comments.
  Rule Comment() {
    return FirstOf(
        Sequence(
            String("//"),
            ZeroOrMore(NoneOf(new char[] { '\n''\r' })),
            WS()),
        Sequence(
            String("/*"),
            ZeroOrMore(
            FirstOf(
                NoneOf(),
                Sequence(String(), NoneOf("/")))),
            String("*/"),
            WS()));
  }
  <R, E> Rule CompoundIdent(final Class<R> referentTypefinal Class<E> elementType) {
    @SuppressWarnings("rawtypes")
    final Var<List<Ident>> parts = new Var<List<Ident>>(new ArrayList<Ident>());
    return Sequence(
        Ident(elementType),
        popToList(Ident.classparts),
        ZeroOrMore("."Ident(elementType), popToList(Ident.classparts)),
        new Action<Object>() {
          @Override
          public boolean run(Context<Objectctx) {
            @SuppressWarnings({ "unchecked""rawtypes" })
            List<Ident<?>> list = (Listparts.get();
            if (list.size() == 1) {
              push(new Ident<R>(referentTypelist.get(0).getSimpleName()));
            } else {
              push(new Ident<R>(referentTypelist));
            }
            return true;
          }
        });
  }

  
An inheritable group which holds zero or more com.getperka.flatpack.policy.pst.GroupDefinition.
 group [ inherit somePropertyName ] {
   groupDefinition;
   ...
   groupDefinition;
 }
 
 group [ inherit somePropertyName ] [ groupDefinition ];
 
  Rule Group() {
    final Var<GroupBlockvar = new Var<GroupBlock>(new GroupBlock());
    return Sequence(
        "group",
        MaybeInherit(Property.classvar),
        new Action<Object>() {
          @Override
          @SuppressWarnings("unchecked")
          public boolean run(Context<Objectctx) {
            GroupBlock x = var.get();
            x.setDefinitions((List<GroupDefinition>) pop());
            push(x);
            return true;
          }
        });
  }

  
Associates one or more property paths with a group name.
 groupName = some.property.path [ , another.path ]
 groupName empty
 
    final Var<GroupDefinitionvar = new Var<GroupDefinition>(new GroupDefinition());
    return Sequence(
        NodeName(SecurityGroup.classvar),
        FirstOf(
            Sequence(
                "empty",
                ACTION(push(new ArrayList<Object>()))
            ),
            Sequence(
                "=",
                OneOrListOf(CompoundIdent(PropertyPath.classProperty.class), Ident.class","))),
        new Action<Object>() {
          @Override
          public boolean run(Context<Objectctx) {
            GroupDefinition x = var.get();
            x.setPaths(popIdentList(PropertyPath.class));
            push(x);
            return true;
          }
        });
  }

  
A lazy, by-name reference to another object. The syntax for these identifiers uses the same rules as Java identifiers.
  <R> Rule Ident(Class<R> referentType) {
    StringVar x = new StringVar();
    return Sequence(
        ,
        ACTION(Character.isJavaIdentifierStart(matchedChar()) && x.append(matchedChar())),
        ZeroOrMore(
            ,
            ACTION(Character.isJavaIdentifierPart(matchedChar()) && x.append(matchedChar()))
        ),
        ACTION(push(new Ident<R>(referentTypex.get()))),
        WS());
  }

  
Support rule to allow an optional inherit ident clause. If the inherit clause is present, an com.getperka.flatpack.policy.pst.Ident will be created and passed to target.
  <P extends HasInheritFrom<R>, R> Rule MaybeInherit(final Class<R> clazzfinal Var<P> target) {
    return Optional(
        "inherit",
        Ident(clazz),
        new Action<Object>() {
          @Override
          public boolean run(Context<Objectctx) {
            target.get().setInheritFrom(popIdent(clazz));
            return true;
          }
        });
  }

  
Support rule to parse a single com.getperka.flatpack.policy.pst.Ident and set x's name.
  <P extends HasName<R>, R> Rule NodeName(final Class<R> clazzfinal Var<P> x) {
    return Sequence(
        FirstOf(
            Ident(clazz),
            ACTION(push(new Ident<R>(clazz"$" + getContext().getPosition().)))
        ),
        new Action<Object>() {
          @Override
          public boolean run(Context<Objectctx) {
            Ident<R> ident = popIdent(clazz);
            P node = x.get();
            node.setName(ident);
            if (ident.getReferentType().isInstance(node)) {
              ident.setReferent(ident.getReferentType().cast(node));
            }
            return true;
          }
        });
  }

  
A hack when generics get in the way.
  @SuppressWarnings({ "unchecked""rawtypes" })
  Rule NodeNameRaw(Class clazzfinal Var x) {
    return NodeName(clazzx);
  }

  
Matches at least one instance of r, which must push exactly one value onto the stack. The matched values will be added to a list, which will be placed on the stack.
  <T extends PolicyNodeRule OneOrListOf(Rule rClass<T> clazzString separator) {
    Var<List<T>> var = new Var<List<T>>(new ArrayList<T>());
    return Sequence(
        r,
        ACTION(popToList(clazzvar)),
        ZeroOrMore(
            separator,
            r,
            ACTION(popToList(clazzvar))),
        ACTION(clazz == null || push(var.get())));
  }
    Var<PackagePolicyx = new Var<PackagePolicy>(new PackagePolicy());
    return Sequence(
        "package",
        NodeName(PackagePolicy.classx),
        "{",
        PolicyBlock(x),
        "}");
  }

  
Main contents blocks.
  Rule PolicyBlock(Var<? extends PolicyBlockx) {
    return Sequence(
        WS(),
        ZeroOrMore(FirstOf(
            Sequence(Allow(), ACTION(x.get().getAllows().add((AllowBlockpop()))),
            Sequence(PackagePolicy(), ACTION(x.get().getPackagePolicies()
                .add((PackagePolicypop()))),
            Sequence(TypePolicy(), ACTION(x.get().getTypePolicies().add((TypePolicypop()))),
            Sequence(ActionDef(), ACTION(x.get().getVerbs().add((ActionDefinitionpop())))
        )),
        ACTION(push(x.get())));
  }
  <T> Ident<T> popIdent(Class<T> clazz) {
    return ((Ident<?>) pop()).cast(clazz);
  }
  <T> List<Ident<T>> popIdentList(Class<T> clazz) {
    @SuppressWarnings("unchecked")
    List<Ident<T>> toReturn = (List<Ident<T>>) pop();
    for (Ident<T> ident : toReturn) {
      ident.cast(clazz);
    }
    return toReturn;
  }

  
Utility method to pop a value from the value stack, cast it to clazz and add it to list. if clazz is null, this method is a no-op.
  <T> boolean popToList(Class<T> clazzVar<List<T>> list) {
    if (clazz != null) {
      list.get().add(clazz.cast(pop()));
    }
    return true;
  }

  
One or more property-name references.
 property ident [ , ident [ ... ] ];
 
    return Sequence(
        "property",
        OneOrListOf(Ident(Property.class), Ident.class","),
        ";",
        new Action<Object>() {
          @Override
          public boolean run(Context<Objectctx) {
            PropertyList x = new PropertyList();
            x.setPropertyNames(popIdentList(Property.class));
            push(x);
            return true;
          }
        });
  }

  
An named block that contains com.getperka.flatpack.policy.pst.AllowBlock and com.getperka.flatpack.policy.pst.PropertyList nodes.
 policy name {
   property a, b, c;
   allow {
     ...
   }
 }
 
    Var<PropertyPolicyx = new Var<PropertyPolicy>(new PropertyPolicy());
    return Sequence(
        "policy",
        NodeName(PropertyPolicy.classx),
        "{",
        ZeroOrMore(FirstOf(
            Sequence(
                Allow(),
                ACTION(x.get().getAllows().add((AllowBlockpop()))),
            Sequence(
                PropertyList(),
                ACTION(x.get().getPropertyLists().add((PropertyListpop())))
        )),
        "}",
        ACTION(push(x.get())));
  }

  
Defines policies for an entity type.
 type typeName {
   allow { ... }
   group { ... }
   policy { ... }
   verb ...;
 }
 
    final Var<TypePolicyx = new Var<TypePolicy>(new TypePolicy());
    return Sequence(
        "type",
        NodeNameRaw(Class.classx),
        "{",
        ZeroOrMore(FirstOf(
            Sequence(Allow(), ACTION(x.get().getAllows().add((AllowBlockpop()))),
            Sequence(Group(), ACTION(x.get().getGroups().add((GroupBlockpop()))),
            Sequence(PropertyPolicy(), ACTION(x.get().getPolicies().add((PropertyPolicypop()))),
            Sequence(ActionDef(), ACTION(x.get().getVerbs().add((ActionDefinitionpop()))))),
        "}",
        ACTION(push(x.get())));
  }

  
A reference to an action. This may be a single com.getperka.flatpack.policy.pst.Ident or a wildcard, possibly qualified by a verb name.
 * 
 *.*
 Foo.bar
 Foo.*
 bar
 
    return FirstOf(
        Sequence(
            ,
            Optional("."),
            ACTION(push(new Ident<SecurityAction>(SecurityAction.class"*")))),
        Sequence(
            Ident(ActionDefinition.class),
            ".",
            WildcardOrIdent(SecurityAction.class),
            ACTION(swap()
              && push(new Ident<SecurityAction>(SecurityAction.class,
                  popIdent(ActionDefinition.class),
                  popIdent(SecurityAction.class))))),
        Ident(SecurityAction.class)
    );
  }

  
A single identifier or a wildcard.
  <R> Rule WildcardOrIdent(Class<R> referentType) {
    return FirstOf(
        Sequence(ACTION(push(new Ident<R>(referentType)))),
        Ident(referentType));
  }

  
Matches whitespace or # comments.
  @Label("whitespace")
  Rule WS() {
    return Sequence(
        ZeroOrMore(AnyOf(new char[] { ' ''\n''\r''\t' })),
        Optional(Comment()));
  }

  
A utility rule to allow another rule to be specified zero, one, or any number of times.
 {
   rule;
   rule;
   ...
 }
 
 rule;
 
 ;
 
  <T> Rule ZeroOneOrBlock(Rule rClass<T> clazz) {
    Var<List<T>> var = new Var<List<T>>(new ArrayList<T>());
    return Sequence(
        FirstOf(
            Sequence(
                "{",
                ZeroOrMore(r";"ACTION(popToList(clazzvar))),
                "}"),
            Sequence(
                r,
                ";",
                ACTION(popToList(clazzvar))),
            ";"),
        ACTION(clazz == null || push(var.get())));
  }
New to GrepCode? Check out our FAQ X