/*
* 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());
}
}