All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wildfly.security.permission.PermissionUtil Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show 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 java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
import java.security.AllPermission;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.IntFunction;
import java.util.function.LongFunction;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;

import org.wildfly.common.Assert;

/**
 * General permission utility methods and constants.
 *
 * @author David M. Lloyd
 */
public final class PermissionUtil {

    private PermissionUtil() {
    }

    /**
     * A shared {@link AllPermission} instance.
     */
    public static final Permission ALL_PERMISSION = new AllPermission();

    /**
     * A read-only permission collection which implies {@link AllPermission}.
     */
    public static final PermissionCollection ALL_PERMISSIONS;

    /**
     * A permission collection which is empty.
     */
    public static final PermissionCollection EMPTY_PERMISSION_COLLECTION;

    /**
     * An array with no permissions in it.
     */
    public static final Permission[] NO_PERMISSIONS = new Permission[0];

    static {
        Permissions permissions = new Permissions();
        permissions.add(ALL_PERMISSION);
        permissions.setReadOnly();
        ALL_PERMISSIONS = permissions;
        permissions = new Permissions();
        permissions.setReadOnly();
        EMPTY_PERMISSION_COLLECTION = permissions;
    }

    /**
     * Parse an actions string, using the given function to map action strings to bits.
     *
     * @param actionsString the actions string (must not be {@code null})
     * @param function the mapping function (must not be {@code null})
     * @return the union of all the action bits
     * @throws IllegalArgumentException if {@code function} throws this exception (indicating an invalid action string)
     */
    public static int parseActions(String actionsString, ToIntFunction function) throws IllegalArgumentException {
        Assert.checkNotNullParam("actionsString", actionsString);
        Assert.checkNotNullParam("function", function);
        int actions = 0;
        int pos = 0;
        int idx = actionsString.indexOf(',');
        for (;;) {
            String str;
            if (idx == -1) {
                str = actionsString.substring(pos, actionsString.length()).trim();
                if (! str.isEmpty()) actions |= function.applyAsInt(str);
                return actions;
            } else {
                str = actionsString.substring(pos, idx).trim();
                pos = idx + 1;
                if (! str.isEmpty()) actions |= function.applyAsInt(str);
                idx = actionsString.indexOf(',', pos);
            }
        }
    }

    /**
     * Parse an actions string, using the given function to map action strings to bits.
     *
     * @param actionsString the actions string (must not be {@code null})
     * @param function the mapping function (must not be {@code null})
     * @return the union of all the action bits
     * @throws IllegalArgumentException if {@code function} throws this exception (indicating an invalid action string)
     */
    public static long parseActions(String actionsString, ToLongFunction function) throws IllegalArgumentException {
        Assert.checkNotNullParam("actionsString", actionsString);
        Assert.checkNotNullParam("function", function);
        long actions = 0;
        int pos = 0;
        int idx = actionsString.indexOf(',');
        for (;;) {
            String str;
            if (idx == -1) {
                str = actionsString.substring(pos, actionsString.length()).trim();
                if (! str.isEmpty()) actions |= function.applyAsLong(str);
                return actions;
            } else {
                str = actionsString.substring(pos, idx).trim();
                pos = idx + 1;
                if (! str.isEmpty()) actions |= function.applyAsLong(str);
                idx = actionsString.indexOf(',', pos);
            }
        }
    }

    /**
     * Deparse an action bit set, using the given function to map action bits to strings.  If the bits are all clear,
     * the empty string {@code ""} is returned.
     *
     * @param actionBits the action bit set
     * @param mappingFunction the mapping function (must not be {@code null})
     * @return the actions string (not {@code null})
     */
    public static String toActionsString(int actionBits, IntFunction mappingFunction) {
        Assert.checkNotNullParam("mappingFunction", mappingFunction);
        final StringBuilder sb = new StringBuilder();
        if (actionBits == 0) return "";
        int lb = Integer.highestOneBit(actionBits);
        sb.append(mappingFunction.apply(lb));
        actionBits &= ~lb;
        while (actionBits != 0) {
            lb = Integer.highestOneBit(actionBits);
            sb.append(',').append(mappingFunction.apply(lb));
            actionBits &= ~lb;
        }
        return sb.toString();
    }

    /**
     * Deparse an action bit set, using the given function to map action bits to strings.  If the bits are all clear,
     * the empty string {@code ""} is returned.
     *
     * @param actionBits the action bit set
     * @param mappingFunction the mapping function (must not be {@code null})
     * @return the actions string (not {@code null})
     */
    public static String toActionsString(long actionBits, LongFunction mappingFunction) {
        Assert.checkNotNullParam("mappingFunction", mappingFunction);
        final StringBuilder sb = new StringBuilder();
        if (actionBits == 0) return "";
        long lb = Long.highestOneBit(actionBits);
        sb.append(mappingFunction.apply(lb));
        actionBits &= ~lb;
        while (actionBits != 0) {
            lb = Long.highestOneBit(actionBits);
            sb.append(',').append(mappingFunction.apply(lb));
            actionBits &= ~lb;
        }
        return sb.toString();
    }

    /**
     * Create an iterable view over a permission collection.
     *
     * @param pc the permission collection (must not be {@code null})
     * @return the iterable view (not {@code null})
     */
    public static Iterable iterable(PermissionCollection pc) {
        return () -> {
            final Enumeration elements = pc.elements();
            return new Iterator() {
                public boolean hasNext() {
                    return elements.hasMoreElements();
                }

                public Permission next() {
                    return elements.nextElement();
                }
            };
        };
    }

    /**
     * Perform an action for each permission in the given collection.
     *
     * @param collection the collection (must not be {@code null})
     * @param consumer the consumer to which each permission should be passed (must not be {@code null})
     */
    public static void forEachIn(PermissionCollection collection, Consumer consumer) {
        Assert.checkNotNullParam("collection", collection);
        Assert.checkNotNullParam("consumer", consumer);
        final Enumeration elements = collection.elements();
        while (elements.hasMoreElements()) {
            consumer.accept(elements.nextElement());
        }
    }

    /**
     * Perform an action for each permission in the given collection.
     *
     * @param collection the collection (must not be {@code null})
     * @param parameter the parameter to pass to the consumer
     * @param consumer the consumer to which each permission should be passed (must not be {@code null})
     * @param 

the type of the parameter * @return the {@code parameter} that was passed in */ public static

P forEachIn(PermissionCollection collection, BiConsumer consumer, P parameter) { Assert.checkNotNullParam("collection", collection); Assert.checkNotNullParam("consumer", consumer); final Enumeration elements = collection.elements(); while (elements.hasMoreElements()) { consumer.accept(parameter, elements.nextElement()); } return parameter; } /** * Run a test for each permission in the given collection. If the predicate returns {@code false} for any element, * {@code false} is returned; otherwise, {@code true} is returned. * * @param collection the collection (must not be {@code null}) * @param predicate the predicate to apply to each element (must not be {@code null}) * @return {@code true} if the predicate matched all the permissions in the collection, {@code false} otherwise */ public static boolean forEachIn(PermissionCollection collection, Predicate predicate) { Assert.checkNotNullParam("collection", collection); Assert.checkNotNullParam("predicate", predicate); final Enumeration elements = collection.elements(); while (elements.hasMoreElements()) { if (! predicate.test(elements.nextElement())) { return false; } } return true; } /** * Run a test for each permission in the given collection. If the predicate returns {@code false} for any element, * {@code false} is returned; otherwise, {@code true} is returned. * * @param collection the collection (must not be {@code null}) * @param parameter the parameter to pass to the consumer * @param predicate the predicate to apply to each element (must not be {@code null}) * @param

the type of the parameter * @return {@code true} if the predicate matched all the permissions in the collection, {@code false} otherwise */ public static

boolean forEachIn(PermissionCollection collection, BiPredicate predicate, P parameter) { Assert.checkNotNullParam("collection", collection); Assert.checkNotNullParam("predicate", predicate); final Enumeration elements = collection.elements(); while (elements.hasMoreElements()) { if (! predicate.test(parameter, elements.nextElement())) { return false; } } return true; } /** * Create a permission collection that is the union of two permission collections. The permission * collections must be read-only. * * @param pc1 the first permission collection (must not be {@code null}) * @param pc2 the second permission collection (must not be {@code null}) * @return a new permission collection that is the union of the two collections (not {@code null}) */ public static PermissionCollection union(PermissionCollection pc1, PermissionCollection pc2) { Assert.checkNotNullParam("pc1", pc1); Assert.checkNotNullParam("pc2", pc2); if (! pc1.isReadOnly() || ! pc2.isReadOnly()) { throw ElytronMessages.log.permissionCollectionMustBeReadOnly(); } if (pc1.implies(ALL_PERMISSION) || pc2.implies(ALL_PERMISSION)) { return ALL_PERMISSIONS; } else { return new UnionPermissionCollection(pc1, pc2); } } /** * Create a permission collection that is the intersection of two permission collections. The permission * collections must be read-only. * * @param pc1 the first permission collection (must not be {@code null}) * @param pc2 the second permission collection (must not be {@code null}) * @return a new permission collection that is the intersection of the two collections (not {@code null}) */ public static PermissionCollection intersection(PermissionCollection pc1, PermissionCollection pc2) { Assert.checkNotNullParam("pc1", pc1); Assert.checkNotNullParam("pc2", pc2); if (! pc1.isReadOnly() || ! pc2.isReadOnly()) { throw ElytronMessages.log.permissionCollectionMustBeReadOnly(); } if (pc1.implies(ALL_PERMISSION)) { return pc2; } else if (pc2.implies(ALL_PERMISSION)) { return pc1; } else { return new IntersectionPermissionCollection(pc1, pc2); } } /** * Determine if one collection implies all the permissions in the other collection. * * @param collection the collection to check against (must not be {@code null}) * @param testCollection the collection whose permissions are to be tested (must not be {@code null}) * @return {@code true} if {@code collection} implies all of the permissions in {@code testCollection}, {@code false} otherwise */ public static boolean impliesAll(PermissionCollection collection, PermissionCollection testCollection) { return forEachIn(collection, PermissionCollection::implies, testCollection); } /** * Determine if two permission collections are equal, that is, each collection implies all of the permissions in the * other collection. * * @param pc1 the first collection (must not be {@code null}) * @param pc2 the second collection (must not be {@code null}) * @return {@code true} if the collections imply one another, {@code false} otherwise */ public static boolean equals(PermissionCollection pc1, PermissionCollection pc2) { return impliesAll(pc1, pc2) && impliesAll(pc2, pc1); } /** * Add all of the permissions from the source collection to the target collection. * * @param target the target collection (must not be {@code null}) * @param source the source collection (must not be {@code null}) * @return the target collection (not {@code null}) */ public static PermissionCollection addAll(PermissionCollection target, PermissionCollection source) { return forEachIn(source, PermissionCollection::add, target); } /** * Add all of the permissions from the source collection to the target collection. * * @param target the target collection (must not be {@code null}) * @param source the source collection (must not be {@code null}) * @return the target collection (not {@code null}) */ public static PermissionCollection addAll(PermissionCollection target, Collection source) { source.forEach(target::add); return target; } /** * Add a permission to a collection, returning the target collection. If the permission is {@code null}, it is * not added. * * @param target the target collection (must not be {@code null}) * @param source the permission to add * @return the target collection (not {@code null}) */ public static PermissionCollection add(PermissionCollection target, Permission source) { Assert.checkNotNullParam("target", target); if (source != null) target.add(source); return target; } /** * Instantiate a permission with the given class name, permission name, and actions. * * @param classLoader the class loader to search in ({@code null} indicates the system class loader) * @param className the name of the permission class to instantiate (must not be {@code null}) * @param name the permission name (may be {@code null} if allowed by the permission class) * @param actions the permission actions (may be {@code null} if allowed by the permission class) * @return the permission object (not {@code null}) * @throws InvalidPermissionClassException if the permission class does not exist or is not valid * @throws ClassCastException if the class name does not refer to a subclass of {@link Permission} */ public static Permission createPermission(final ClassLoader classLoader, final String className, final String name, final String actions) { Assert.checkNotNullParam("className", className); final Class permissionClass; try { permissionClass = Class.forName(className, true, classLoader).asSubclass(Permission.class); } catch (ClassNotFoundException e) { throw ElytronMessages.log.permissionClassMissing(className, e); } return createPermission(permissionClass, name, actions); } /** * Instantiate a permission with the given class, permission name, and actions. * * @param permissionClass the permission class to instantiate (must not be {@code null}) * @param name the permission name (may be {@code null} if allowed by the permission class) * @param actions the permission actions (may be {@code null} if allowed by the permission class) * @return the permission object (not {@code null}) * @throws InvalidPermissionClassException if the permission class does not exist or is not valid */ public static Permission createPermission(final Class permissionClass, final String name, final String actions) { Assert.checkNotNullParam("permissionClass", permissionClass); Constructor noArgs = null; Constructor oneArg = null; Constructor twoArg = null; for (Constructor raw : permissionClass.getConstructors()) { @SuppressWarnings("unchecked") Constructor ctor = (Constructor) raw; final Class[] parameterTypes = ctor.getParameterTypes(); if (parameterTypes.length == 2 && parameterTypes[0] == String.class && parameterTypes[1] == String.class) { twoArg = ctor; } else if (parameterTypes.length == 1 && parameterTypes[0] == String.class) { oneArg = ctor; } else if (parameterTypes.length == 0) { noArgs = ctor; } } try { if (twoArg != null) { return twoArg.newInstance(name, actions); } else if (oneArg != null) { return oneArg.newInstance(name); } else if (noArgs != null) { return noArgs.newInstance(); } else { throw ElytronMessages.log.noPermissionConstructor(permissionClass.getName()); } } catch (IllegalAccessException e) { throw new IllegalAccessError(e.getMessage()); } catch (InstantiationException e) { throw ElytronMessages.log.permissionInstantiation(permissionClass.getName(), e); } catch (InvocationTargetException e) { try { throw e.getCause(); } catch (Error | RuntimeException cause) { throw cause; } catch (Throwable cause) { throw new UndeclaredThrowableException(cause); } } } /** * Get a read-only collection of the given permissions. * * @param permissions the permissions to assign * @return the read-only collection */ public static PermissionCollection readOnlyCollectionOf(Permission... permissions) { final int length = permissions.length; if (length == 0) { return EMPTY_PERMISSION_COLLECTION; } else { Permissions collection = new Permissions(); addAll(collection, Arrays.asList(permissions)); collection.setReadOnly(); return collection; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy