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

com.linkare.zas.aspectj.DepthController.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 org.aspectj.lang.annotation.SuppressAjWarnings;

import com.linkare.zas.annotation.AccessControlled;
import com.linkare.zas.annotation.Depth;
import com.linkare.zas.api.IJoinPoint;
import com.linkare.zas.aspectj.accessinfo.JoinPoint;
import com.linkare.zas.aspectj.utils.BaseZas;
import com.linkare.zas.config.AccessRequirementSpecificationMode;
import com.linkare.zas.config.Configuration;
import com.linkare.zas.metainfo.DepthRequirement;
import com.linkare.zas.metainfo.ZasBaseRequirement;

/**
 * This aspect controls the stack of depth of access control for the current thread, by registering the depth in the SharedSecurityContext class.
 * 
 * @author Paulo Zenida
 */
@SuppressAjWarnings("adviceDidNotMatch")
public abstract aspect DepthController extends BaseZas {

    // ========================== Pointcuts ==========================
    /**
     * This pointcut defines the protected objects which do not have their requirements inherited. If the control should be performed in a deep
     * manner, then all accesses within the flow of control of that protected object should be checked everywhere, until another kind of access
     * control depth verification is defined. If the control should be performed in a shallow manner, then accesses within the flow of control of
     * that protected object should be skipped everywhere, until another kind of access control depth verification is defined.
     */
    public pointcut accessToControlledProtectedObjectsNotInherited(final AccessControlled accessControlled) : (execution(@AccessControlled(isInherited = false) * *..*.*(..)) || execution(@AccessControlled(isInherited = false) *..*.*.new(..))) && @annotation(accessControlled);

    /**
     * This pointcut defines the protected objects which have their requirements inherited. The way they should be controlled should be fetched from their type.
     */
    public pointcut accessToControlledProtectedObjectsInherited(final AccessControlled accessControlled) : (execution(@AccessControlled(isInherited = true) * *..*.*(..)) || execution(@AccessControlled(isInherited = true) *..*.*.new(..))) && @annotation(accessControlled);

    /**
     * This pointcut controls whether this aspect's behavior should be enabled or not. Its implementation depends on the AspectJ language being active, as
     * defined in BaseZas, and the method isDepthControlEnabled() method returning true.
     */
    public pointcut enabled() : BaseZas.enabled() && if(Configuration.isDepthControlEnabled());

    // ========================== Advices ==========================
    /**
     * Each time we have an access to a protected object in which we have declared deep as the policy, all accesses from that point on should be
     * made shallowly, as declared in the annotation, resulting in the true entry in the current thread stack, in class SharedSecurityContext.
     */
    before(final AccessControlled accessControlled) : accessToControlledProtectedObjectsNotInherited(accessControlled) && weavingContext() && enabled() {
	if (SharedSecurityContext.getCurrentThreadDepthAccessStack() == null) {
	    SharedSecurityContext.createAndInitializeDepthAccess();
	}
	final boolean isShallow = accessControlled.depth() == Depth.SHALLOW;
	addElementToStackDepthAccess(new JoinPoint(thisJoinPoint), isShallow);
    }

    before(final AccessControlled accessControlledOnType, final AccessControlled accessControlled) : ZasPointcuts.accessControlledTypes(accessControlledOnType) && accessToControlledProtectedObjectsInherited(accessControlled) && weavingContext() && enabled() {
	if (SharedSecurityContext.getCurrentThreadDepthAccessStack() == null) {
	    SharedSecurityContext.createAndInitializeDepthAccess();
	}
	final boolean isShallow = accessControlledOnType.depth() == Depth.SHALLOW;
	addElementToStackDepthAccess(new JoinPoint(thisJoinPoint), isShallow);
    }

    /**
     * After the access to a protected object in which we have declared the Deep or Shallow annotations, the current stack of access
     * depth should be updated, removing the element which had been registered at the beginning of this join point access.
     */
    after(final AccessControlled accessControlled) : (accessToControlledProtectedObjectsNotInherited(accessControlled) || accessToControlledProtectedObjectsInherited(accessControlled)) && (weavingContext() && enabled()) {
	if (SharedSecurityContext.getCurrentThreadDepthAccessStack() == null) {
	    SharedSecurityContext.createAndInitializeDepthAccess();
	}
	SharedSecurityContext.removeElementFromStackDepthAccess(new JoinPoint(thisJoinPoint));
    }

    // ========================== Methods ==========================
    /**
     * 
     * @param joinPoint
     * @param isShallow
     * @return Returns a new instance of a depth requirement, according to the joinPoint and isShallow boolean flag 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 boolean isShallow) {
	if (Configuration.getAccessRequirementSpecificationMode() == AccessRequirementSpecificationMode.IN_CODE_AND_EXTERNAL_FILE) {
	    final ZasBaseRequirement zasBaseRequirement = (ZasBaseRequirement) BaseZas.getExternalRequirement(joinPoint.getSignature().getFullyQualifiedName());
	    if (zasBaseRequirement != null) {
		return zasBaseRequirement;
	    }
	}
	return new DepthRequirement(joinPoint.getKind(), isShallow);
    }

    /**
     * It adds a new element to the stack of depth access in the SharedSecurityContext singleton class.
     * 
     * @param joinPoint
     * @param isShallow
     */
    private void addElementToStackDepthAccess(final IJoinPoint joinPoint, final boolean isShallow) {
	final ZasBaseRequirement depthRequirement = buildAccessControlRequirement(joinPoint, isShallow);
	SharedSecurityContext.addElementToStackDepthAccess(depthRequirement.getIsShallow(), joinPoint);
    }
}