2  * Copyright (c) 2015 Brocade Communications Systems, Inc. and others.  All rights reserved.
 
   4  * This program and the accompanying materials are made available under the
 
   5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 
   6  * and is available at http://www.eclipse.org/legal/epl-v10.html
 
   8 package org.opendaylight.aaa.shiro.authorization;
 
  10 import com.google.common.base.Preconditions;
 
  11 import com.google.common.collect.Sets;
 
  12 import java.util.Arrays;
 
  13 import java.util.Collection;
 
  14 import java.util.HashSet;
 
  15 import org.slf4j.Logger;
 
  16 import org.slf4j.LoggerFactory;
 
  19  * A container for RBAC Rules. An RBAC Rule is composed of a url pattern which
 
  20  * may contain asterisk characters (*), and a collection of roles. These are
 
  21  * represented in shiro.ini in the following format:
 
  22  * <code>urlPattern=roles[atLeastOneCommaSeperatedRole]</code>
 
  24  * RBACRules are immutable; that is, you cannot change the url pattern or the
 
  25  * roles after creation. This is done for security purposes. RBACRules are
 
  26  * created through utilizing a static factory method:
 
  27  * <code>RBACRule.createRBACRule()</code>
 
  29  * @author Ryan Goulding (ryandgoulding@gmail.com)
 
  32 public class RBACRule {
 
  34     private static final Logger LOG = LoggerFactory.getLogger(RBACRule.class);
 
  37      * a url pattern that can optional contain asterisk characters (*)
 
  39     private String urlPattern;
 
  42      * a collection of role names, such as "admin" and "user"
 
  44     private Collection<String> roles = new HashSet<String>();
 
  47      * Creates an RBAC Rule. Made private for static factory method.
 
  50      *            Cannot be null or the empty string.
 
  52      *            Must contain at least one role.
 
  53      * @throws NullPointerException
 
  54      *             if <code>urlPattern</code> or <code>roles</code> is null
 
  55      * @throws IllegalArgumentException
 
  56      *             if <code>urlPattern</code> is an empty string or
 
  57      *             <code>roles</code> is an empty collection.
 
  59     private RBACRule(final String urlPattern, final Collection<String> roles)
 
  60             throws NullPointerException, IllegalArgumentException {
 
  62         this.setUrlPattern(urlPattern);
 
  67      * The static factory method used to create RBACRules.
 
  70      *            Cannot be null or the empty string.
 
  72      *            Cannot be null or an emtpy collection.
 
  73      * @return An immutable RBACRule
 
  75     public static RBACRule createAuthorizationRule(final String urlPattern,
 
  76             final Collection<String> roles) {
 
  78         RBACRule authorizationRule = null;
 
  80             authorizationRule = new RBACRule(urlPattern, roles);
 
  81         } catch (Exception e) {
 
  82             LOG.error("Cannot instantiate the AuthorizationRule", e);
 
  84         return authorizationRule;
 
  89      * @return the urlPattern for the RBACRule
 
  91     public String getUrlPattern() {
 
  96      * helper to ensure the url pattern is not the empty string
 
  98     private static void checkUrlPatternLength(final String urlPattern)
 
  99             throws IllegalArgumentException {
 
 101         final String EXCEPTION_MESSAGE = "Empty String is not allowed for urlPattern";
 
 102         if (urlPattern.isEmpty()) {
 
 103             throw new IllegalArgumentException(EXCEPTION_MESSAGE);
 
 107     private void setUrlPattern(final String urlPattern) throws NullPointerException,
 
 108             IllegalArgumentException {
 
 110         Preconditions.checkNotNull(urlPattern);
 
 111         checkUrlPatternLength(urlPattern);
 
 112         this.urlPattern = urlPattern;
 
 117      * @return a copy of the rule, so any modifications to the returned
 
 118      *         reference do not affect the immutable <code>RBACRule</code>.
 
 120     public Collection<String> getRoles() {
 
 121         // Returns a copy of the roles collection such that the original set
 
 123         // its contract of remaining immutable.
 
 125         // Since this method is only called at shiro initialiation time,
 
 126         // memory consumption of creating a new set is a non-issue.
 
 127         return Sets.newHashSet(roles);
 
 131      * check to ensure the roles collection is not empty
 
 133     private static void checkRolesCollectionSize(final Collection<String> roles)
 
 134             throws IllegalArgumentException {
 
 136         final String EXCEPTION_MESSAGE = "roles must contain at least 1 role";
 
 137         if (roles.isEmpty()) {
 
 138             throw new IllegalArgumentException(EXCEPTION_MESSAGE);
 
 142     private void setRoles(final Collection<String> roles) throws NullPointerException,
 
 143             IllegalArgumentException {
 
 145         Preconditions.checkNotNull(roles);
 
 146         checkRolesCollectionSize(roles);
 
 151      * Generates a string representation of the <code>RBACRule</code> roles in
 
 154      * @return roles string representation in the form
 
 155      *         <code>roles[roleOne,roleTwo]</code>
 
 157     public String getRolesInShiroFormat() {
 
 158         final String ROLES_STRING = "roles";
 
 159         return ROLES_STRING + Arrays.toString(roles.toArray());
 
 163      * Generates the string representation of the <code>RBACRule</code> in shiro
 
 164      * form. For example: <code>urlPattern=roles[admin,user]</code>
 
 167     public String toString() {
 
 168         return String.format("%s=%s", urlPattern, getRolesInShiroFormat());