/* * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.aaa.shiro.authorization; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A container for RBAC Rules. An RBAC Rule is composed of a url pattern which * may contain asterisk characters (*), and a collection of roles. These are * represented in shiro.ini in the following format: * urlPattern=roles[atLeastOneCommaSeperatedRole] * * RBACRules are immutable; that is, you cannot change the url pattern or the * roles after creation. This is done for security purposes. RBACRules are * created through utilizing a static factory method: * RBACRule.createRBACRule() * * @author Ryan Goulding (ryandgoulding@gmail.com) * */ public class RBACRule { private static final Logger LOG = LoggerFactory.getLogger(RBACRule.class); /** * a url pattern that can optional contain asterisk characters (*) */ private String urlPattern; /** * a collection of role names, such as "admin" and "user" */ private Collection roles = new HashSet(); /** * Creates an RBAC Rule. Made private for static factory method. * * @param urlPattern * Cannot be null or the empty string. * @param roles * Must contain at least one role. * @throws NullPointerException * if urlPattern or roles is null * @throws IllegalArgumentException * if urlPattern is an empty string or * roles is an empty collection. */ private RBACRule(final String urlPattern, final Collection roles) throws NullPointerException, IllegalArgumentException { this.setUrlPattern(urlPattern); this.setRoles(roles); } /** * The static factory method used to create RBACRules. * * @param urlPattern * Cannot be null or the empty string. * @param roles * Cannot be null or an emtpy collection. * @return An immutable RBACRule */ public static RBACRule createAuthorizationRule(final String urlPattern, final Collection roles) { RBACRule authorizationRule = null; try { authorizationRule = new RBACRule(urlPattern, roles); } catch (Exception e) { LOG.error("Cannot instantiate the AuthorizationRule", e); } return authorizationRule; } /** * * @return the urlPattern for the RBACRule */ public String getUrlPattern() { return urlPattern; } /* * helper to ensure the url pattern is not the empty string */ private static void checkUrlPatternLength(final String urlPattern) throws IllegalArgumentException { final String EXCEPTION_MESSAGE = "Empty String is not allowed for urlPattern"; if (urlPattern.isEmpty()) { throw new IllegalArgumentException(EXCEPTION_MESSAGE); } } private void setUrlPattern(final String urlPattern) throws NullPointerException, IllegalArgumentException { Preconditions.checkNotNull(urlPattern); checkUrlPatternLength(urlPattern); this.urlPattern = urlPattern; } /** * * @return a copy of the rule, so any modifications to the returned * reference do not affect the immutable RBACRule. */ public Collection getRoles() { // Returns a copy of the roles collection such that the original set // keeps // its contract of remaining immutable. // // Since this method is only called at shiro initialiation time, // memory consumption of creating a new set is a non-issue. return Sets.newHashSet(roles); } /* * check to ensure the roles collection is not empty */ private static void checkRolesCollectionSize(final Collection roles) throws IllegalArgumentException { final String EXCEPTION_MESSAGE = "roles must contain at least 1 role"; if (roles.isEmpty()) { throw new IllegalArgumentException(EXCEPTION_MESSAGE); } } private void setRoles(final Collection roles) throws NullPointerException, IllegalArgumentException { Preconditions.checkNotNull(roles); checkRolesCollectionSize(roles); this.roles = roles; } /** * Generates a string representation of the RBACRule roles in * shiro form. * * @return roles string representation in the form * roles[roleOne,roleTwo] */ public String getRolesInShiroFormat() { final String ROLES_STRING = "roles"; return ROLES_STRING + Arrays.toString(roles.toArray()); } /** * Generates the string representation of the RBACRule in shiro * form. For example: urlPattern=roles[admin,user] */ @Override public String toString() { return String.format("%s=%s", urlPattern, getRolesInShiroFormat()); } }