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

com.linkare.zas.aspectj.Enforcer.aj Maven / Gradle / Ivy

Go to download

The AspectJ based implementation of the Zas project. This is the new version of the implementation of Zas which, initially, started as a M.Sc. thesis project by Paulo Zenida at ISCTE.

The newest version!
package com.linkare.zas.aspectj;

import static com.linkare.zas.aspectj.SharedSecurityContext.isAllowedInvokerResultTrueForJoinPointSignature;
import static com.linkare.zas.aspectj.SharedSecurityContext.isForced;
import static com.linkare.zas.aspectj.SharedSecurityContext.isTrustResultTrueForJoinPointSignature;
import static com.linkare.zas.aspectj.SharedSecurityContext.registerForcedJoinPoint;
import static com.linkare.zas.aspectj.SharedSecurityContext.shouldBeShallowlyVerified;
import static com.linkare.zas.aspectj.SharedSecurityContext.unregisterForcedJoinPoint;
import static com.linkare.zas.aspectj.utils.ReflectionUtils.getConstructorFrom;
import static com.linkare.zas.aspectj.utils.ReflectionUtils.getEquivalentConstructorsInTheHierarchy;
import static com.linkare.zas.aspectj.utils.ReflectionUtils.getEquivalentMethodsInTheHierarchy;
import static com.linkare.zas.aspectj.utils.ReflectionUtils.getFieldFrom;
import static com.linkare.zas.aspectj.utils.ReflectionUtils.getMethodFrom;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.aspectj.lang.annotation.SuppressAjWarnings;

import com.linkare.zas.annotation.AccessControlled;
import com.linkare.zas.annotation.AccessControls;
import com.linkare.zas.api.Decider;
import com.linkare.zas.api.EnforcerAdvise;
import com.linkare.zas.api.IAOPMetaData;
import com.linkare.zas.api.IJoinPoint;
import com.linkare.zas.api.UnauthorizedAccessImplementor;
import com.linkare.zas.api.ZasInitializer;
import com.linkare.zas.aspectj.accessinfo.AOPMetaData;
import com.linkare.zas.aspectj.accessinfo.JoinPoint;
import com.linkare.zas.aspectj.utils.BaseZas;
import com.linkare.zas.aspectj.utils.ReflectionUtils;
import com.linkare.zas.aspectj.utils.ZasUtils;
import com.linkare.zas.config.Configuration;
import com.linkare.zas.exception.AccessControlException;
import com.linkare.zas.exception.IllegalCallerException;
import com.linkare.zas.exception.NoAccessControlInheritedAllowedException;
import com.linkare.zas.metainfo.AccessControlInheritedRequirement;
import com.linkare.zas.metainfo.AccessControlledRequirement;
import com.linkare.zas.metainfo.ForcedRequirement;
import com.linkare.zas.metainfo.ZasBaseRequirement;

// TODO: Implement a list of allowed privileged classes.
/**
 * This aspect implements the enforcer function from Anderson's abstract reference monitor. This aspect is responsible for the interception of all access
 * attempts, for the collection of all information required for the decider to check the legitimacy of the access and enforce the decision taken by that decider
 * module.
 * 
 * @author Paulo Zenida
 * 
 * @param S
 *            the subject class on Zás clients. The subject is the entity who makes an access attempt to a protected object, such as the execution of a given
 *            method.
 */
@SuppressAjWarnings("adviceDidNotMatch")
public abstract aspect Enforcer extends BaseZas {

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private Map, UnauthorizedAccessImplementor> unauthorizedAccessImplementorClassInstancesMap = new Hashtable, UnauthorizedAccessImplementor>();

    // ========================== Constructors ==========================
    @ZasInitializer
    protected Enforcer() {
    }

    // ========================== Advices ==========================
    /**
     * This is for the registration of a forced context in the SharedSecurityContext singleton. This information is later on used by Zás to check
     * whether an access control attempt should be verified or not. This advice must execute before the access control attempt checking. This advice will be
     * active only if the the method isForcedEnabled() returns true.
     * 
     * @see pointcut enabled()
     */
    @EnforcerAdvise
    @SuppressAjWarnings("adviceDidNotMatch")
    before() : enabled() && ZasPointcuts.forcedContext() && weavingContext() && if(Configuration.isForcedEnabled()) {
	final IJoinPoint joinPoint = new JoinPoint(thisJoinPoint);
	final ZasBaseRequirement forcedRequirement = buildForcedRequirement(joinPoint, true);
	if (forcedRequirement.isForced()) {
	    registerForcedJoinPoint(joinPoint);
	}
    }

    /**
     * This is for objects having the annotation AccessControlled(isInherited = true) inside types having the annotation
     * AccessControlled only.
     * 
     * It inserts an advice before all accesses to protected objects, checking the current subject privileges against the current protected object. It throws an
     * AccessControlException when the decider module associated to this joinpoint returns false, when verifying the current subject privileges for
     * the current protected object. It returns quietly, otherwise. It also may return quietly, when the protected object has declared its trust on the class or
     * method who has invoked it.
     * 
     * @param accessControlledOnType
     *            The accessControlledOnType annotation associated to the parent type of this joinpoint.
     * @param accessControlledOnObject
     *            The accessControlledOnObject annotation associated to this joinpoint.
     * 
     */
    @EnforcerAdvise
    @SuppressWarnings("unchecked")
    @SuppressAjWarnings("adviceDidNotMatch")
    before(final AccessControlled accessControlledOnType, final AccessControlled accessControlledOnObject) : 
	enabled() && 
	ZasPointcuts.accessControlledTypes(accessControlledOnType) &&
	ZasPointcuts.accessToControlledObjects(accessControlledOnObject) && 
	!ZasPointcuts.privilegedAccess() && 
	ZasPointcuts.accessControlledInheritedAccess() && 
	weavingContext() {

	final IJoinPoint joinPoint = new JoinPoint(thisJoinPoint);
	final ZasBaseRequirement accessControlInheritedRequirement = buildAccessControlInheritedRequirement(joinPoint, true);
	final AccessControlled accessControlled = getAccessControlledAnnotationInObjectOrType(accessControlInheritedRequirement.isAccessControlInherited(),
											      accessControlledOnObject, accessControlledOnType, joinPoint);

	checkAuthorization(AOPMetaData.create(thisJoinPoint, thisEnclosingJoinPointStaticPart), accessControlled);
    }

    @EnforcerAdvise
    @SuppressWarnings("unchecked")
    @SuppressAjWarnings("adviceDidNotMatch")
    before(final AccessControls accessControlsOnType, final AccessControls accessControlsOnObject) :
	enabled() && 
	ZasPointcuts.accessControlsInTypes(accessControlsOnType) &&
	ZasPointcuts.accessControlsInObjects(accessControlsOnObject) && 
	!ZasPointcuts.privilegedAccess() && 
	ZasPointcuts.accessControlsInheritedAccess() && 
	weavingContext() {

	final IJoinPoint joinPoint = new JoinPoint(thisJoinPoint);
	final ZasBaseRequirement accessControlInheritedRequirement = buildAccessControlInheritedRequirement(joinPoint, true);
	final AccessControls accessControls = getAccessControlsAnnotationInObjectOrType(accessControlInheritedRequirement.isAccessControlInherited(),
											accessControlsOnObject, accessControlsOnType, joinPoint);
	checkAuthorization(AOPMetaData.create(thisJoinPoint, thisEnclosingJoinPointStaticPart), accessControls);
    }

    /**
     * It inserts an advice before all accesses to protected objects, checking the current subject privileges against the current protected object. It throws an
     * AccessControlException when the decider module associated to this joinpoint returns false, when verifying the current subject privileges for
     * the current protected object. It returns quietly, otherwise. It also may return quietly, when the protected object has declared its trust on the class or
     * method who has invoked it.
     * 
     * @param accessControlledOnObject
     *            the accessControlled annotation associated to this joinpoint.
     */
    @EnforcerAdvise
    @SuppressWarnings("unchecked")
    @SuppressAjWarnings("adviceDidNotMatch")
    before(final AccessControlled accessControlledOnObject) : 
	enabled() && 
	ZasPointcuts.accessToControlledObjects(accessControlledOnObject) && 
	!ZasPointcuts.privilegedAccess() && 
	!ZasPointcuts.accessControlledInheritedAccess() && 
	weavingContext() {

	final IJoinPoint joinPoint = new JoinPoint(thisJoinPoint);
	final ZasBaseRequirement accessControlInheritedRequirement = buildAccessControlInheritedRequirement(joinPoint, false);

	final AccessControlled accessControlled = getAccessControlledAnnotationInObjectOrType(accessControlInheritedRequirement.isAccessControlInherited(),
											      accessControlledOnObject, null, joinPoint);

	checkAuthorization(AOPMetaData.create(thisJoinPoint, thisEnclosingJoinPointStaticPart), accessControlled);
    }

    @EnforcerAdvise
    @SuppressWarnings("unchecked")
    @SuppressAjWarnings("adviceDidNotMatch")
    before(final AccessControls accessControlsOnObject) : 
	enabled() && 
	ZasPointcuts.accessControlsInObjects(accessControlsOnObject) && 
	!ZasPointcuts.privilegedAccess() && 
	!ZasPointcuts.accessControlsInheritedAccess() && 
	weavingContext() {

	final IJoinPoint joinPoint = new JoinPoint(thisJoinPoint);
	final ZasBaseRequirement accessControlInheritedRequirement = buildAccessControlInheritedRequirement(joinPoint, false);
	final AccessControls accessControls = getAccessControlsAnnotationInObjectOrType(accessControlInheritedRequirement.isAccessControlInherited(),
											accessControlsOnObject, null, joinPoint);
	checkAuthorization(AOPMetaData.create(thisJoinPoint, thisEnclosingJoinPointStaticPart), accessControls);
    }

    /**
     * This advice removes the registration of a forced context. This advice executes after the execution of any method, constructor, or field having finished,
     * and simply removes what has been registered previously, so that in other access attempts this information is not taken into account. This advice will be
     * active only if the the method isForcedEnabled() returns true.
     * 
     * @see pointcut enabled()
     */
    @EnforcerAdvise
    @SuppressAjWarnings("adviceDidNotMatch")
    after() : enabled() && ZasPointcuts.forcedContext() && weavingContext() && if(Configuration.isForcedEnabled()) {
	final IJoinPoint joinPoint = new JoinPoint(thisJoinPoint);
	final ZasBaseRequirement forcedRequirement = buildForcedRequirement(joinPoint, true);
	if (forcedRequirement.isForced()) {
	    unregisterForcedJoinPoint(joinPoint);
	}
    }

    // ========================== Methods ==========================
    /**
     * @return It returns the current subject. This method must be implemented in the client code, and it must return an instance of the subject class specific
     *         for a given client application.
     */
    public abstract S currentSubject();

    /**
     * @return It returns the default decider class, i.e., the default class that decides about the legitimacy of an access attempt to a protected object. This
     *         method must be implemented in a given client application, returning the class that extends the Decider and which evaluates the
     *         legitimacy of an access by default. The client decider class cannot be abstract.
     */
    public abstract Class> defaultDeciderClass();

    /**
     * 
     * @return It returns an instance of the decider class associated to the current protected object, and sets the current subject, to make it possible for the
     *         decider to decide about the subject's privileges in order to access a given protected object.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private List> buildDeciders(final List> deciderClasses) throws IllegalAccessException, NoSuchMethodException,
	    InvocationTargetException {
	final List> result = new ArrayList>(deciderClasses.size());
	for (final Class deciderClass : deciderClasses) {
	    try {
		final Decider decider = (Decider) instantiateDeciderClass(deciderClass);
		if (Configuration.canUseStackOfCodeSubjects()) {
		    //		    decider.setSubjects(StackOfSubjectsContext.getStackOfSubjects());
		}
		result.add(decider);
	    } catch (InstantiationException e) {
		System.err.println(e + ". It was not possible to instantiate the decider class " + deciderClass.getSimpleName());
	    }
	    //	    catch (IllegalCallerException e) {
	    //		System.out.println(e + ". You cannot invoke this method from outside Zás framework.");
	    //	    }

	}
	return result;
    }

    /**
     * This method returns an Object, since a decider class may be defined as a emmber class of any class. The argument, however, must be a class extending a
     * Decider class.
     * 
     * @param deciderClass
     * @throws InstantiationException
     *             , IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private Object instantiateDeciderClass(final Class deciderClass) throws InstantiationException, IllegalAccessException,
	    SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
	if (deciderClass.isMemberClass() && !Modifier.isStatic(deciderClass.getModifiers())) {
	    final Class enclosingClass = deciderClass.getEnclosingClass();
	    final Object obj = instantiateDeciderClass(enclosingClass);
	    final Constructor constructor = deciderClass.getConstructor(new Class[] { enclosingClass });
	    return constructor.newInstance(new Object[] { obj });
	} else {
	    return deciderClass.newInstance();
	}
    }

    /**
     * It checks whether the current subject has access to the protected object represented in aopMetaData, according to the
     * accessControlled annotation access control requirements.
     * 
     * @throws AccessControlException
     *             It throws an AccessControlException when the access to the protected object should be denied. It proceeds quietly otherwise.
     */
    @SuppressWarnings({ "unchecked", "unused" })
    private void checkAuthorization(final IAOPMetaData aopMetaData, final AccessControlled accessControlled) {
	final IJoinPoint joinPoint = aopMetaData.getJoinPoint();
	final boolean isShallow = !isForced(joinPoint) && shouldBeShallowlyVerified();
	final boolean isTrustable = isTrustResultTrueForJoinPointSignature(joinPoint.getSignature());
	final boolean isAllowedInvoker = isAllowedInvokerResultTrueForJoinPointSignature(joinPoint.getSignature());
	if (!isForced(joinPoint) && (isTrustable || isAllowedInvoker || isShallow)) {
	    return;
	}
	try {
	    final S subject = currentSubject();
	    final List decisionMetaInfo = getDecisionMetaInfos(joinPoint);

	    for (final AccessControlled ac : decisionMetaInfo) {
		if (ac != null) {
		    final ZasBaseRequirement accessControlRequirement = buildAccessControlRequirement(joinPoint, ac);
		    final int size = accessControlRequirement.getDeciderClasses().size();
		    @SuppressWarnings("rawtypes")
		    final List> deciderClasses = new ArrayList>(size);
		    if (size == 0) {
			deciderClasses.add(defaultDeciderClass());
		    } else {
			deciderClasses.addAll(accessControlRequirement.getDeciderClasses());
		    }
		    final List> deciders = buildDeciders(deciderClasses);
		    if (deciders.isEmpty()) {
			denyAccessBecauseOfEmptyDeciders(aopMetaData);
		    } else {
			for (final Decider decider : deciders) {
			    if (!decider.checkAccess(subject, accessControlRequirement.getAbstractAccessMode(), aopMetaData)) {
				denyAccess(accessControlRequirement, aopMetaData);
			    }
			}
		    }
		}
	    }
	} catch (AccessControlException e) {
	    throw e;
	} catch (RuntimeException e) {
	    throw e;
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

    @SuppressWarnings("unused")
    private void checkAuthorization(final IAOPMetaData aopMetaData, final AccessControls accessControls) {
	final IJoinPoint joinPoint = aopMetaData.getJoinPoint();
	final boolean isShallow = !isForced(joinPoint) && shouldBeShallowlyVerified();
	final boolean isTrustable = isTrustResultTrueForJoinPointSignature(joinPoint.getSignature());
	final boolean isAllowedInvoker = isAllowedInvokerResultTrueForJoinPointSignature(joinPoint.getSignature());
	if (!isForced(joinPoint) && (isTrustable || isAllowedInvoker || isShallow)) {
	    return;
	}
	try {
	    final S subject = currentSubject();
	    final AccessControlled[] decisionMetaInfo = accessControls.value();

	    for (final AccessControlled ac : decisionMetaInfo) {
		if (ac != null) {
		    final ZasBaseRequirement accessControlRequirement = buildAccessControlRequirement(joinPoint, ac);
		    final int size = accessControlRequirement.getDeciderClasses().size();
		    @SuppressWarnings("rawtypes")
		    final List> deciderClasses = new ArrayList>(size);
		    if (size == 0) {
			deciderClasses.add(defaultDeciderClass());
		    } else {
			deciderClasses.addAll(accessControlRequirement.getDeciderClasses());
		    }
		    final List> deciders = buildDeciders(deciderClasses);
		    if (deciders.isEmpty()) {
			denyAccessBecauseOfEmptyDeciders(aopMetaData);
		    } else {
			for (final Decider decider : deciders) {
			    if (!decider.checkAccess(subject, accessControlRequirement.getAbstractAccessMode(), aopMetaData)) {
				denyAccess(accessControlRequirement, aopMetaData);
			    }
			}
		    }
		}
	    }
	} catch (AccessControlException e) {
	    throw e;
	} catch (RuntimeException e) {
	    throw e;
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

    /**
     * This method handles the situation when an access should be denied. By default, it simply returns an AccessControlException with the details
     * about whose protected object's access was forbidden. The method invokes doBeforeDenyAccess() so that, when necessary, a specific enforcer
     * may specify additional behavior.
     * 
     * @param aopMetaData
     *            The protected object's information.
     */
    @SuppressWarnings("unchecked")
    private void denyAccess(final ZasBaseRequirement accessControlRequirement, final IAOPMetaData aopMetaData) {
	try {
	    final UnauthorizedAccessImplementor unauthorizedAccessImplementor = getOrRegisterUnauthorizedAccessImplementor(accessControlRequirement.getUnauthorizedAccessImplementorClass());
	    unauthorizedAccessImplementor.doBeforeDenyAccess(accessControlRequirement, aopMetaData, currentSubject());
	    try {
		unauthorizedAccessImplementor.denyAccess(accessControlRequirement, aopMetaData, currentSubject());
	    } catch (RuntimeException e) {
		throw e;
	    } finally {
		unauthorizedAccessImplementor.doAfterDenyAccess(accessControlRequirement, aopMetaData, currentSubject());
	    }
	} catch (InstantiationException e) {
	    e.printStackTrace();
	} catch (IllegalAccessException e) {
	    e.printStackTrace();
	}
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private UnauthorizedAccessImplementor getOrRegisterUnauthorizedAccessImplementor(
	    final Class unauthorizedAccessImplementorClass) throws InstantiationException, IllegalAccessException {
	if (unauthorizedAccessImplementorClassInstancesMap.get(unauthorizedAccessImplementorClass) == null) {
	    unauthorizedAccessImplementorClassInstancesMap.put(unauthorizedAccessImplementorClass, unauthorizedAccessImplementorClass.newInstance());
	}
	return unauthorizedAccessImplementorClassInstancesMap.get(unauthorizedAccessImplementorClass);
    }

    private void denyAccessBecauseOfEmptyDeciders(final IAOPMetaData aopMetaData) {
	throw new AccessControlException("Deciders were empty " + aopMetaData.getSignature().toString());
    }

    /**
     * 
     * @param joinPoint
     *            The meta data for the current protected object.
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws ClassNotFoundException
     * @throws NoSuchFieldException
     * @return Returns a list of AccessControlled annotations, to the joinPoint passed in as argument. This method builds the decision
     *         meta info for the current protected object, fetching possibly defined requirements in the super protected objects.
     * @see ReflectionUtils#getMethodFrom(net.sourceforge.zas.aop.bridge.IJoinPoint)
     * @see ReflectionUtils#getConstructorFrom(net.sourceforge.zas.aop.bridge.IJoinPoint)
     * @see ReflectionUtils#getFieldFrom(net.sourceforge.zas.aop.bridge.IJoinPoint)
     */
    private List getDecisionMetaInfos(final IJoinPoint joinPoint) throws SecurityException, NoSuchMethodException, ClassNotFoundException,
	    NoSuchFieldException {
	if (joinPoint.getKind().isMethod()) {
	    final Method method = getMethodFrom(joinPoint);
	    return ZasUtils.buildDecisionMetaInfoForMethods(getEquivalentMethodsInTheHierarchy(method));
	} else if (joinPoint.getKind().isConstructor()) {
	    final Constructor constructor = getConstructorFrom(joinPoint);
	    return ZasUtils.buildDecisionMetaInfoForConstructors(getEquivalentConstructorsInTheHierarchy(constructor));
	} else if (joinPoint.getKind().isField()) {
	    final Field field = getFieldFrom(joinPoint);
	    return ZasUtils.buildDecisionMetaInfoForField(field);
	}
	return null;
    }

    /**
     * 
     * @param joinPoint
     * @param accessControlled
     * @return Returns a new instance of an access control requirement, according to the joinPoint and accessControlled annotation
     *         passed in as arguments. An instance of ZasBaseRequirement is necessary so that, if the requirements were specified through XML, a
     *         representation of those requirements may be created. When the requirements were specified in Java code, the returned instance is a representation
     *         of the fields specified in the access control annotations.
     */
    private ZasBaseRequirement buildAccessControlRequirement(final IJoinPoint joinPoint, final AccessControlled accessControlled) {
	if (Configuration.getAccessRequirementSpecificationMode().isFileReadingEnabled()) {
	    final ZasBaseRequirement zasBaseRequirement = BaseZas.getExternalRequirement(joinPoint.getSignature().getFullyQualifiedName());
	    if (zasBaseRequirement != null) {
		return zasBaseRequirement;
	    }
	}
	return new AccessControlledRequirement(accessControlled);
    }

    /**
     * 
     * @param joinPoint
     * @param isForced
     * @return Returns a new instance of a forced requirement, according to the joinPoint and isForced passed in as arguments. An
     *         instance of ZasBaseRequirement is necessary so that, if the requirements were specified through XML, a representation of those
     *         requirements may be created. When the requirements were specified in Java code, the returned instance is a representation of the fields specified
     *         in the access control annotations.
     */
    private ZasBaseRequirement buildForcedRequirement(final IJoinPoint joinPoint, final boolean isForced) {
	if (Configuration.getAccessRequirementSpecificationMode().isFileReadingEnabled()) {
	    final ZasBaseRequirement zasBaseRequirement = BaseZas.getExternalRequirement(joinPoint.getSignature().getFullyQualifiedName());
	    if (zasBaseRequirement != null) {
		return zasBaseRequirement;
	    }
	}
	return new ForcedRequirement(isForced, joinPoint.getKind());
    }

    /**
     * 
     * @param joinPoint
     * @param isAccessControlInherited
     * @return Returns a new instance of an access control inherited requirement, according to the joinPoint and
     *         isAccessControlInherited passed in as arguments. An instance of ZasBaseRequirement is necessary so that, if the
     *         requirements were specified through XML, a representation of those requirements may be created. When the requirements were specified in Java
     *         code, the returned instance is a representation of the fields specified in the access control annotations.
     */
    private ZasBaseRequirement buildAccessControlInheritedRequirement(final IJoinPoint joinPoint, final boolean isAccessControlInherited) {
	if (Configuration.getAccessRequirementSpecificationMode().isFileReadingEnabled()) {
	    final ZasBaseRequirement zasBaseRequirement = BaseZas.getExternalRequirement(joinPoint.getSignature().getFullyQualifiedName());
	    if (zasBaseRequirement != null) {
		return zasBaseRequirement;
	    }
	}
	return new AccessControlInheritedRequirement(isAccessControlInherited, joinPoint.getKind());
    }

    /**
     * @param shouldCheckOnType
     *            This parameter controls whether the access control requirements should be fetched from those of the access control annotation defined in this
     *            object's type. When this flag is set to false, the requirements defined on the protected object's type, if any, are ignored. Those
     *            requirements will be considered, otherwise.
     * @param accessControlledOnObject
     *            The access control annotation declared in this protected object.
     * @param accessControlledOnType
     *            THe access control annotation declared in this protected object's type. When this parameter is null and the flag
     *            shouldCheckOnType is true, the annotation on the protected object's type is fetched through reflection based code.
     * @param joinPoint
     *            The protected object's information.
     * @throws NoAccessControlInheritedAllowedException
     *             When the protected object declares itself as getting the access control requirements from a type which has no access control requirements
     *             declared.
     * @see ReflectionUtils#getAnnotation(Class, Class)
     */
    private AccessControlled getAccessControlledAnnotationInObjectOrType(final boolean shouldCheckOnType, final AccessControlled accessControlledOnObject,
	    final AccessControlled accessControlledOnType, final IJoinPoint joinPoint) {
	if (!shouldCheckOnType) {
	    return accessControlledOnObject;
	}
	final AccessControlled accessControlledOnTypeAux = accessControlledOnType == null ? (AccessControlled) ReflectionUtils.getAnnotation(joinPoint.getSignature()
																		      .getDeclaringType(),
																	     AccessControlled.class)
		: accessControlledOnType;
	if (accessControlledOnTypeAux == null) {
	    throw new NoAccessControlInheritedAllowedException(joinPoint.getSignature().toString());
	}
	return (accessControlledOnObject.value().equals("false") && (accessControlledOnObject.deciderClasses().length == 0) ? accessControlledOnTypeAux
		: accessControlledOnObject);
    }

    private AccessControls getAccessControlsAnnotationInObjectOrType(final boolean shouldCheckOnType, final AccessControls accessControlsOnObject,
	    final AccessControls accessControlsOnType, final IJoinPoint joinPoint) {
	if (!shouldCheckOnType) {
	    return accessControlsOnObject;
	}
	final AccessControls accessControlsOnTypeAux = accessControlsOnType == null ? (AccessControls) ReflectionUtils.getAnnotation(joinPoint.getSignature()
																	      .getDeclaringType(),
																     AccessControls.class)
		: accessControlsOnType;
	if (accessControlsOnTypeAux == null) {
	    throw new NoAccessControlInheritedAllowedException(joinPoint.getSignature().toString());
	}
	return (accessControlsOnObject.isInherited() && accessControlsOnObject.value().length == 0 ? accessControlsOnTypeAux : accessControlsOnObject);
    }
}