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

org.picketlink.idm.permission.acl.spi.BaseAbstractPermissionHandler Maven / Gradle / Ivy

There is a newer version: 5.0.0-2013Jan16
Show newest version
/*
 * JBoss, Home of Professional Open Source
 *
 * Copyright 2013 Red Hat, Inc. and/or its affiliates.
 *
 * 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.picketlink.idm.permission.acl.spi;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.picketlink.idm.permission.annotations.AllowedOperation;
import org.picketlink.idm.permission.annotations.AllowedOperations;

/**
 * Stored resource permissions can either be persisted as a comma-separated list of values, or as a
 * bit-masked numerical value where each bit represents a specific permission for that class. This
 * is a helper class that handles the conversion automatically and presents a unified API for
 * dealing with these persistent actions.
 *
 * @author Shane Bryzak
 */
public abstract class BaseAbstractPermissionHandler implements PermissionHandler {
    private Map, Boolean> usesMask = new HashMap, Boolean>();

    private Map, Map> instanceOperations = new ConcurrentHashMap, Map>();

    private Map, Map> classOperations = new ConcurrentHashMap, Map>();

    private synchronized void initOperations(Class cls) {
        if (!instanceOperations.containsKey(cls)) {

            Map instanceOps = new HashMap();
            Map classOps = new HashMap();

            boolean useMask = false;

            AllowedOperations p = (AllowedOperations) cls.getAnnotation(AllowedOperations.class);

            if (p != null) {
                AllowedOperation[] operations = p.value();
                if (operations != null) {
                    for (AllowedOperation operation : operations) {

                        if (operation.classOperation()) {
                            classOps.put(operation.value(), operation.mask());
                        } else {
                            instanceOps.put(operation.value(), operation.mask());
                        }

                        if (operation.mask() != 0) {
                            useMask = true;
                        }
                    }
                }
            }

            // Validate that all actions have a proper mask
            if (useMask) {
                Set masks = new HashSet();

                Set ops = new HashSet();
                ops.addAll(instanceOps.keySet());
                ops.addAll(classOps.keySet());

                for (String op : ops) {

                    Long mask = instanceOps.containsKey(op) ? instanceOps.get(op) : classOps.get(op);
                    if (masks.contains(mask)) {
                        throw new IllegalArgumentException("Class " + cls.getName() +
                                " defines a duplicate mask for permission operation [" + op + "]");
                    }

                    if (mask == 0) {
                        throw new IllegalArgumentException("Class " + cls.getName() +
                                " must define a valid mask value for operation [" + op + "]");
                    }

                    if ((mask & (mask - 1)) != 0) {
                        throw new IllegalArgumentException("Class " + cls.getName() +
                                " must define a mask value that is a power of 2 for operation [" + op + "]");
                    }

                    masks.add(mask);
                }
            }

            usesMask.put(cls, useMask);
            instanceOperations.put(cls, instanceOps);
        }
    }

    protected class PermissionSet {
        private Set permissions = new HashSet();

        private Class resourceClass;

        public PermissionSet(Class resourceClass, String members) {
            this.resourceClass = resourceClass;
            addMembers(members);
        }

        public void addMembers(String members) {
            if (members == null) {
                return;
            }

            if (usesMask.get(resourceClass)) {
                // bit mask-based actions
                long vals = Long.valueOf(members);

                Map permissions = instanceOperations.get(resourceClass);
                for (String permission : permissions.keySet()) {
                    long mask = permissions.get(permission).longValue();
                    if ((vals & mask) != 0) {
                        this.permissions.add(permission);
                    }
                }
            }
            else {
                // comma-separated string based actions
                String[] permissions = members.split(",");
                for (String permission : permissions) {
                    this.permissions.add(permission);
                }
            }
        }

        public boolean contains(String action) {
            return permissions.contains(action);
        }

        public PermissionSet add(String action) {
            permissions.add(action);
            return this;
        }

        public PermissionSet remove(String action) {
            permissions.remove(action);
            return this;
        }

        public Set getPermissions() {
            return permissions;
        }

        public boolean isEmpty() {
            return permissions.isEmpty();
        }

        @Override
        public String toString() {
            if (usesMask.get(resourceClass)) {
                Map actions = instanceOperations.get(resourceClass);
                long mask = 0;

                for (String member : permissions) {
                    mask |= actions.get(member).longValue();
                }

                return "" + mask;
            } else {
                StringBuilder sb = new StringBuilder();
                for (String member : permissions) {
                    if (sb.length() > 0) {
                        sb.append(',');
                    }
                    sb.append(member);
                }
                return sb.toString();
            }
        }
    }

    public PermissionSet createPermissionSet(Class resourceClass, String members) {
        if (!instanceOperations.containsKey(resourceClass)) {
            initOperations(resourceClass);
        }

        return new PermissionSet(resourceClass, members);
    }

    @Override
    public Set listClassOperations(Class resourceClass) {
        if (!classOperations.containsKey(resourceClass)) {
            initOperations(resourceClass);
        }

        Set permissions = new HashSet();

        for (String permission : classOperations.get(resourceClass).keySet()) {
            permissions.add(permission);
        }

        return permissions;
    }

    @Override
    public Set listInstanceOperations(Class resourceClass) {
        if (!instanceOperations.containsKey(resourceClass)) {
            initOperations(resourceClass);
        }

        Set permissions = new HashSet();

        for (String permission : instanceOperations.get(resourceClass).keySet()) {
            permissions.add(permission);
        }

        return permissions;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy