Demo applications

Simple demo:

This is a very simple app, only demonstrates the usage of Interceptor, Mixin and Pointcut of each type. Please refer to the tutorial

Role based access control:

This one is much more complex, here use JoyAop to re-implement a real RBAC system. Besides, it demonstrates the usage of the extension libraries, include Hiberante(3), PicoContainer and JMock.

JDK5.0 annotation driven access control:

package net.sf.joyaop.demo.security;

import net.sf.joyaop.demo.security.annotation.Permission;

/**
 * @author Shen Li
 */
public class Facade {
    @Permission("create")
    public void create() {
        System.out.println("Create successfully.");
    }

    @Permission("delete")
    public void delete() {
        System.out.println("Delete successfully.");
    }
}
                

Model the domain objects using the AOP mixins. With the extension library, the mixin-style domain objects could work with Hibernate3.

Configuration configuration = new Configuration().configure();
// Simplely add a custom Interceptor of Hibernate to the Configuration instance.
Interceptor interceptor = new JoyInterceptor(objectFactory, configuration);
configuration.setInterceptor(interceptor);
                

uml

Principle_User_Group

uml

Role_Permission

Dependency injection for the aspects (Constructor Injection by PicoContainer: because the interceptor is an abstract class here, it's constructor should be declared as protected.

package net.sf.joyaop.demo.security;

import net.sf.joyaop.AroundAdvice;
import net.sf.joyaop.demo.security.annotation.Permission;

/**
 * @author Shen Li
 */
public abstract class AcessControlInterceptor implements AbstractInterceptor {
    private AccessController accessController;

    // Use constructor to obtain the dependent components
    protected AcessControlInterceptor(AccessController accessController) {
        this.accessController = accessController;
    }

    public Object execute() throws Throwable {
        Permission permissionAnnotation = getMethod().getAnnotation(Permission.class);
        if (permissionAnnotation == null) {
            throw new RuntimeException(
                    "Method " + getMethod().getName() + " doesn't have the permission annotation.");
        } else {
            accessController.checkPermission(permissionAnnotation.value());
        }
        return proceed();
    }
}
                

JoyAop could transparently aspectize the components in a PicoContainer by using the custom ComponentAdapterFactory. The interceptors, mixins and ObjectFactory/AspectRuntime don't need to be registered by youself, JoyAop will automatically register them.

// Build a PicoContainer
JoyXmlContainerBuilder containerBuilder = new JoyXmlContainerBuilder(
        "net/sf/joyaop/demo/rbac/components.xml", "net/sf/joyaop/demo/rbac/aspects.xml");
PicoContainer container = containerBuilder.buildContainer();
// It will be automatically weaved
Facade testFacadecade = (Facade) container.getComponentInstance(Facade.class);
                
<!-- XML config of NanoContainer, note the custom ComponentAdapterFactory -->
<container component-adapter-factory="net.sf.joyaop.extension.picocontainer.AspectizedComponentAdapterFactory">
    <component-implementation class="net.sf.joyaop.demo.security.persistence.EntityHomeImpl"/>
    <component-implementation class="net.sf.joyaop.demo.security.persistence.SessionManagerImpl"/>
    <component-implementation class="net.sf.joyaop.demo.security.SimpleSecurityContext"/>
    <component-implementation class="net.sf.joyaop.demo.security.AccessControllerImpl"/>
    <component-implementation class="net.sf.joyaop.demo.security.TestFacadeImpl"/>
</container>
                

Test abstract mixin (Mock the abstract methods with the the extension mock library of JoyAop):

package net.sf.joyaop.demo.security.model;

import net.sf.joyaop.extension.mock.MockObjectTestCase;
import org.jmock.Mock;

import java.util.HashSet;
import java.util.Set;

/**
 * @author Shen Li
 */
public class RoleOwnerTest extends MockObjectTestCase {
    public void testGetAllRoles() {
    
        // mock the abstract mixin using the extension library.
        // the usage is the same as JMock, except it only overrides the abstract methods.
        
        Mock mockRoleOwner = mockAbstactMethods(RoleOwnerImpl.class);
        Mock mockParentRoleOwner = mock(RoleOwnerImpl.class);
        RoleOwner roleOwner = (RoleOwner) mockRoleOwner.proxy();
        RoleOwner parentRoleOwner = (RoleOwner) mockParentRoleOwner.proxy();
        Set parents = new HashSet();
        parents.add(parentRoleOwner);
        Set parentRoles = new HashSet();
        Role parentRole = (Role) mock(Role.class).proxy();
        parentRoles .add(parentRole);
        mockRoleOwner.expects(atLeastOnce()).method("getParents").will(returnValue(parents));
        mockParentRoleOwner.expects(atLeastOnce()).method("getAllRoles").will(returnValue(parentRoles));
        Role role = (Role) mock(Role.class).proxy();
        roleOwner.addRole(role);
        assertEquals(2, roleOwner.getAllRoles().size());
        assertTrue(roleOwner.getAllRoles().contains(role));
        assertTrue(roleOwner.getAllRoles().contains(parentRole));
        mockRoleOwner.verify();
        mockParentRoleOwner.verify();
    }
}
                

Very simple configuration file of the aspects.

<runtime>
    <!-- mixins -->
    <pointcut expr="interface(net.sf.joyaop.demo.security.model.Child)">
        <mixin interface="net.sf.joyaop.demo.security.model.Child" class="net.sf.joyaop.demo.security.model.ChildImpl"/>
    </pointcut>
    <pointcut expr="interface(net.sf.joyaop.demo.security.model.Parent)">
        <mixin interface="net.sf.joyaop.demo.security.model.Parent" class="net.sf.joyaop.demo.security.model.ParentImpl"/>
    </pointcut>
    <pointcut expr="interface(net.sf.joyaop.demo.security.model.RoleOwner) AND interface(net.sf.joyaop.demo.security.model.Child)">
        <mixin interface="net.sf.joyaop.demo.security.model.RoleOwner" class="net.sf.joyaop.demo.security.model.RoleOwnerImpl"/>
    </pointcut>
    <pointcut expr="interface(net.sf.joyaop.demo.security.model.EntityInfo)">
        <mixin interface="net.sf.joyaop.demo.security.model.EntityInfo" class="net.sf.joyaop.demo.security.model.EntityInfoImpl"/>
    </pointcut>
    <pointcut expr="interface(net.sf.joyaop.demo.security.model.UserInfo)">
        <mixin interface="net.sf.joyaop.demo.security.model.UserInfo" class="net.sf.joyaop.demo.security.model.UserInfoImpl"/>
    </pointcut>
    <pointcut expr="interface(net.sf.joyaop.demo.security.model.PermissionOwner)">
        <mixin interface="net.sf.joyaop.demo.security.model.PermissionOwner" class="net.sf.joyaop.demo.security.model.PermissionOwnerImpl"/>
    </pointcut>

    <!-- generic interceptors -->
    <pointcut expr="annotation(net.sf.joyaop.demo.security.annotation.Permission)">
        <interceptor class="net.sf.joyaop.demo.security.AcessControlInterceptor"/>
    </pointcut>

    <!-- docorators -->
    <pointcut expr="interface(net.sf.joyaop.demo.security.AccessController)">
        <interceptor class="net.sf.joyaop.demo.security.AccessControllerLoggingDecorator"/>
    </pointcut>
</runtime>
                

To run it, type "ant run:demo:rbac" in your console.