org.wildfly.security.permission.AbstractActionSetPermission Maven / Gradle / Ivy
The newest version!
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.
*/
package org.wildfly.security.permission;
import org.wildfly.security.util.StringEnumeration;
/**
* An abstract base class for permissions which use a bit set to represent actions.
*
* @author David M. Lloyd
*/
public abstract class AbstractActionSetPermission> extends AbstractActionPermission {
private static final long serialVersionUID = 897239118282921196L;
private final StringEnumeration actionEnumeration;
private final int actionBits;
private String actions;
/**
* Construct a new instance. The given bits are masked by {@link #actionsMask()} before being stored in the object
* instance.
*
* @param name the permission name
* @param actionBits the permission action bits
* @param actionEnumeration the permission actions enumeration
*/
protected AbstractActionSetPermission(final String name, final int actionBits, final StringEnumeration actionEnumeration) {
super(name);
this.actionEnumeration = actionEnumeration;
this.actionBits = actionBits & actionsMask();
if (actionBits == actionsMask()) actions = "*";
}
/**
* Construct a new instance.
*
* @param name the permission name
* @param actions the permission actions string
* @param actionEnumeration the permission actions enumeration
*/
protected AbstractActionSetPermission(final String name, final String actions, final StringEnumeration actionEnumeration) {
super(name);
this.actionEnumeration = actionEnumeration;
final int actionBits = parseActions(actions);
this.actionBits = actionBits & actionsMask();
if (actionBits == actionsMask()) this.actions = "*";
}
/**
* Get the action bits of this permission.
*
* @return the action bits
*/
public final int getActionBits() {
return actionBits;
}
public final boolean actionsEquals(final This permission) {
return permission != null && actionBits == permission.getActionBits();
}
public final boolean impliesActions(final This permission) {
return permission != null && isSet(actionBits, permission.getActionBits());
}
public final boolean impliesActions(final String actions) {
return impliesActionBits(parseActions(actions));
}
/**
* Determine whether this permission's actions value implies the given action bits.
*
* @param actionBits the actions bits to test
* @return {@code true} if this permission implies the given action bits; {@code false} otherwise
*/
public final boolean impliesActionBits(final int actionBits) {
return isSet(this.actionBits, actionBits & actionsMask());
}
private int actionsMask() {
return (1 << actionEnumeration.size()) - 1;
}
private int getActionBit(final String actionName) throws IllegalArgumentException {
return 1 << actionEnumeration.indexOf(actionName);
}
private String getActionName(final int bit) throws IllegalArgumentException {
return actionEnumeration.nameOf(Integer.numberOfTrailingZeros(bit));
}
protected final int actionsHashCode() {
return actionBits;
}
/**
* Get the actions string. The string is computed the first time this method is called, and cached thereafter.
*
* @return the actions string (not {@code null})
*/
public final String getActions() {
final String actions = this.actions;
if (actions != null) {
return actions;
}
return this.actions = PermissionUtil.toActionsString(actionBits, this::getActionName);
}
/**
* Parse the actions string into a bit set.
*
* @param actionsString the actions string
* @return the bit set
* @throws IllegalArgumentException if the actions string contained an invalid name or invalid syntax
*/
public final int parseActions(final String actionsString) throws IllegalArgumentException {
return PermissionUtil.parseActions(actionsString, this::getActionBit);
}
public final This withActions(final String actionsString) {
return withActionBits(parseActions(actionsString));
}
public final This withActionsFrom(final This permission) {
return withActionBits(permission.getActionBits());
}
/**
* Get a permission which is identical to this one, but with new actions which consist of the union of the actions
* from this permission and the action bits from the given value. The returned permission may or may not be a new
* instance, and may be equal to this instance.
*
* @param actionBits the action bits
* @return the permission (not {@code null})
*/
public final This withActionBits(int actionBits) {
return withNewActionBits(this.actionBits | actionBits & actionsMask());
}
public final This withoutActions(String actionsString) {
return withoutActionBits(parseActions(actionsString));
}
public final This withoutActionsFrom(final This permission) {
return withoutActionBits(permission.getActionBits());
}
/**
* Get a permission which is identical to this one, but with new actions which consist of the actions
* from this permission without the action bits from the given value. The returned permission may or may not be a new
* instance, and may be equal to this instance.
*
* @param actionBits the action bits
* @return the permission (not {@code null})
*/
public final This withoutActionBits(int actionBits) {
return withNewActionBits(this.actionBits & ~actionBits);
}
public final This withNewActions(String actionsString) {
return withNewActionBits(parseActions(actionsString));
}
public final This withNewActionsFrom(final This permission) {
return withNewActionBits(permission.getActionBits());
}
/**
* Get a permission which is identical to this one, but with new action bits as given by {@code actionBits}.
* The returned permission may or may not be a new instance, and may be equal to this instance.
*
* @param actionBits the action bits
* @return the permission (not {@code null})
*/
@SuppressWarnings("unchecked")
public final This withNewActionBits(int actionBits) {
final int masked = actionBits & actionsMask();
if (masked == this.actionBits) {
return (This) this;
} else {
return constructWithActionBits(masked);
}
}
/**
* Construct or return a permission of this type with the same name as this one but with the given action bits.
*
* @param actionBits the action bits
* @return the permission
*/
protected abstract This constructWithActionBits(int actionBits);
// private
private static boolean isSet(final int bits, final int test) {
return (bits & test) == test;
}
}