Package org.jboss.as.ejb3.security

Source Code of org.jboss.as.ejb3.security.EJBMethodSecurityMetaData

/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.as.ejb3.security;

import org.jboss.as.ee.component.ComponentConfiguration;
import org.jboss.as.ejb3.EJBMethodIdentifier;
import org.jboss.as.ejb3.component.EJBComponentDescription;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import static org.jboss.as.ejb3.EjbMessages.MESSAGES;

/**
* Holds security metadata of a method corresponding to a EJB's view.
* <p/>
* For security metadata that's applicable at EJB component level (for ex: security domain) take a look at {@link EJBSecurityMetaData}
* <p/>
* User: Jaikiran Pai
*/
public class EJBMethodSecurityMetaData {

    /**
     * True if access to the method is denied for all roles
     */
    private final boolean denyAll;

    /**
     * True if access to the method is permitted for all roles
     */
    private final boolean permitAll;

    /**
     * Set of roles allowed to access the method.
     */
    private final Set<String> rolesAllowed;

    /**
     * @param componentConfiguration The component configuration of a EJB
     * @param viewClassName          The view class name
     * @param viewMethod             The view method
     */
    public EJBMethodSecurityMetaData(final ComponentConfiguration componentConfiguration, final String viewClassName, final Method viewMethod) {
        if (componentConfiguration.getComponentDescription() instanceof EJBComponentDescription == false) {
            throw MESSAGES.invalidComponentIsNotEjbComponent(componentConfiguration.getComponentName());
        }
        final EJBComponentDescription ejbComponentDescription = (EJBComponentDescription) componentConfiguration.getComponentDescription();

        // process @DenyAll/exclude-list
        this.denyAll = this.isAccessDenied(componentConfiguration, viewClassName, viewMethod);
        // process @PermitAll list
        this.permitAll = this.isPermitAll(componentConfiguration, viewClassName, viewMethod);
        // process @RolesAllowed/method-permission
        this.rolesAllowed = Collections.unmodifiableSet(this.getRolesAllowed(componentConfiguration, viewClassName, viewMethod));

    }

    /**
     * Returns true if access to the method corresponding to this {@link EJBMethodSecurityMetaData} is denied
     * for all roles. Else returns false
     *
     * @return
     */
    public boolean isAccessDenied() {
        return this.denyAll;
    }

    /**
     * Returns true if access to the method corresponding to this {@link EJBMethodSecurityMetaData} is permitted for
     * all roles. Else returns false.
     *
     * @return
     */
    public boolean isPermitAll() {
        return this.permitAll;
    }

    /**
     * Returns a set of roles which are allowed to access the method corresponding to this {@link EJBMethodSecurityMetaData}.
     * The returned set may be empty if there's no specific role assigned to the method.
     *
     * @return
     */
    public Set<String> getRolesAllowed() {
        return this.rolesAllowed;
    }


    private boolean isAccessDenied(final ComponentConfiguration componentConfiguration, final String viewClassName, final Method viewMethod) {
        final EJBComponentDescription ejbComponentDescription = (EJBComponentDescription) componentConfiguration.getComponentDescription();
        // find the component method corresponding to this view method
        final Method componentMethod = this.findComponentMethod(componentConfiguration, viewMethod);
        final EJBMethodIdentifier ejbMethodIdentifier = EJBMethodIdentifier.fromMethod(componentMethod);
        final Set<String> rolesAllowed = ejbComponentDescription.getRolesAllowed(viewClassName, ejbMethodIdentifier);
        final boolean methodMarkedForDenyAll = this.isMethodMarkedForDenyAll(ejbComponentDescription, viewClassName, ejbMethodIdentifier);
        final boolean methodMarkedForPermitAll = this.isMethodMarkedForPermitAll(ejbComponentDescription, viewClassName, ejbMethodIdentifier);
        if (methodMarkedForDenyAll) {
            // make sure the method isn't marked for @PermitAll
            if (methodMarkedForPermitAll) {
               throw MESSAGES.invalidSecurityAnnotation(componentMethod,viewClassName,"@PemitAll","@DenyAll");
            }
            // make sure @RolesAllowed isn't applied to the method explicitly
            if (!rolesAllowed.isEmpty()) {
                throw MESSAGES.invalidSecurityAnnotation(componentMethod,viewClassName,"@RolesAllowed","@DenyAll");
            }
            // only @DenyAll is applied on the method, so return true
            return true;
        }
        // check on class level for @DenyAll *only* if the method isn't marked with @PermitAll and @RolesAllowed (in which case,
        // it doesn't qualify for @DenyAll)
        if (!rolesAllowed.isEmpty()) {
            return false;
        }
        if (methodMarkedForPermitAll) {
            return false;
        }
        final Class<?> declaringClass = componentMethod.getDeclaringClass();
        if (ejbComponentDescription.isDenyAllApplicableToClass(viewClassName, declaringClass.getName())) {
            return true;
        }
        return false;
    }

    private boolean isPermitAll(final ComponentConfiguration componentConfiguration, final String viewClassName, final Method viewMethod) {
        final EJBComponentDescription ejbComponentDescription = (EJBComponentDescription) componentConfiguration.getComponentDescription();
        // find the component method corresponding to this view method
        final Method componentMethod = this.findComponentMethod(componentConfiguration, viewMethod);
        final EJBMethodIdentifier ejbMethodIdentifier = EJBMethodIdentifier.fromMethod(componentMethod);
        final Set<String> rolesAllowed = ejbComponentDescription.getRolesAllowed(viewClassName, ejbMethodIdentifier);
        final boolean methodMarkedForDenyAll = this.isMethodMarkedForDenyAll(ejbComponentDescription, viewClassName, ejbMethodIdentifier);
        final boolean methodMarkedForPermitAll = this.isMethodMarkedForPermitAll(ejbComponentDescription, viewClassName, ejbMethodIdentifier);
        if (methodMarkedForPermitAll) {
            // make sure the method isn't marked for @DenyAll
            if (methodMarkedForDenyAll) {
                throw MESSAGES.invalidSecurityAnnotation(componentMethod,viewClassName,"@PemitAll","@DenyAll");
            }
            // make sure @RolesAllowed isn't applied to the method explicitly
            if (!rolesAllowed.isEmpty()) {
                 throw MESSAGES.invalidSecurityAnnotation(componentMethod,viewClassName,"@RolesAllowed","@PermitAll");
            }
            // only @PermitAll is applied on the method, so return true
            return true;
        }
        // check on class level for @PermitAll *only* if the method isn't marked with @DenyAll and @RolesAllowed (in which case,
        // it doesn't qualify for @PermitAll)
        if (!rolesAllowed.isEmpty()) {
            return false;
        }
        if (methodMarkedForPermitAll) {
            return false;
        }
        final Class<?> declaringClass = componentMethod.getDeclaringClass();
        if (ejbComponentDescription.isPermitAllApplicableToClass(viewClassName, declaringClass.getName())) {
            return true;
        }
        return false;
    }

    private Set<String> getRolesAllowed(final ComponentConfiguration componentConfiguration, final String viewClassName, final Method viewMethod) {
        final EJBComponentDescription ejbComponentDescription = (EJBComponentDescription) componentConfiguration.getComponentDescription();
        // find the component method corresponding to this view method
        final Method componentMethod = this.findComponentMethod(componentConfiguration, viewMethod);
        final EJBMethodIdentifier ejbMethodIdentifier = EJBMethodIdentifier.fromMethod(componentMethod);
        final Set<String> rolesAllowed = ejbComponentDescription.getRolesAllowed(viewClassName, ejbMethodIdentifier);
        final boolean methodMarkedForDenyAll = this.isMethodMarkedForDenyAll(ejbComponentDescription, viewClassName, ejbMethodIdentifier);
        final boolean methodMarkedForPermitAll = this.isMethodMarkedForPermitAll(ejbComponentDescription, viewClassName, ejbMethodIdentifier);
        if (!rolesAllowed.isEmpty()) {
            return rolesAllowed;
        }
        // check on class level for @RolesAllowed *only* if the method isn't marked with @DenyAll and @PermitAll (in which case,
        // it doesn't qualify for @RolesAllowed)
        if (methodMarkedForDenyAll) {
            return Collections.emptySet();
        }
        if (methodMarkedForPermitAll) {
            return Collections.emptySet();
        }
        final Class<?> declaringClass = componentMethod.getDeclaringClass();
        final Set<String> classLevelRolesAllowed = ejbComponentDescription.getRolesAllowedForClass(viewClassName, declaringClass.getName());
        if (!classLevelRolesAllowed.isEmpty()) {
            return classLevelRolesAllowed;
        }
        return Collections.emptySet();
    }

    private boolean isMethodMarkedForDenyAll(final EJBComponentDescription ejbComponentDescription, final String viewClassName, final EJBMethodIdentifier ejbMethodIdentifier) {
        Collection<EJBMethodIdentifier> denyAllMethodsForView = ejbComponentDescription.getDenyAllMethodsForView(viewClassName);
        return denyAllMethodsForView.contains(ejbMethodIdentifier);
    }

    private boolean isMethodMarkedForPermitAll(final EJBComponentDescription ejbComponentDescription, final String viewClassName, final EJBMethodIdentifier ejbMethodIdentifier) {
        Collection<EJBMethodIdentifier> permitAllMethodsForView = ejbComponentDescription.getPermitAllMethodsForView(viewClassName);
        return permitAllMethodsForView.contains(ejbMethodIdentifier);
    }

    private Method findComponentMethod(final ComponentConfiguration componentConfiguration, final Method viewMethod) {
        final Class<?> componentClass = componentConfiguration.getComponentClass();
        try {
            return componentClass.getMethod(viewMethod.getName(), viewMethod.getParameterTypes());
        } catch (NoSuchMethodException e) {
            throw MESSAGES.failToFindComponentMethod(viewMethod.getName(),Arrays.toString(viewMethod.getParameterTypes()),componentClass);
        }

    }

}
TOP

Related Classes of org.jboss.as.ejb3.security.EJBMethodSecurityMetaData

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.