This is a very simple app, only demonstrates the usage of Interceptor, Mixin and Pointcut of each type. Please refer to the tutorial
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);
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.