(no commit message)
authorErik Brakkee <erik@brakkee.org>
Mon, 10 May 2010 21:57:53 +0000 (21:57 +0000)
committerErik Brakkee <erik@brakkee.org>
Mon, 10 May 2010 21:57:53 +0000 (21:57 +0000)
security/impl/src/main/java/org/wamblee/security/authorization/jpa/JpaAuthorizationService.java

index 4bce7aef3e60a55d3c7ed80afdafc4d81a556d96..333781c62e19bfa40ce0f2195d302bd870dfce88 100644 (file)
@@ -19,6 +19,8 @@ import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
 import javax.persistence.NonUniqueResultException;
 
+import org.wamblee.cache.ComputedValue;
+import org.wamblee.cache.ComputedValue.Computation;
 import org.wamblee.persistence.JpaMergeSupport;
 import org.wamblee.security.authentication.UserAccessor;
 import org.wamblee.security.authentication.UserAdministration;
@@ -41,7 +43,7 @@ public class JpaAuthorizationService implements AuthorizationService {
     /**
      * Authorization service to use.
      */
-    private AuthorizationService service;
+    private ComputedValue<AuthorizationService> service;
 
     /**
      * Hibernate template to use.
@@ -52,7 +54,7 @@ public class JpaAuthorizationService implements AuthorizationService {
      * User accessor.
      */
     private UserAccessor userAccessor;
-    
+
     /**
      * User administration.
      */
@@ -82,41 +84,56 @@ public class JpaAuthorizationService implements AuthorizationService {
      *            Entity manager.
      * @param aAccessor
      *            User accessor.
-     * @param aUserAdmin  User administration.
+     * @param aUserAdmin
+     *            User administration.
      * @param aRefresh
      *            Whether or not to refresh the state of the service at the
      *            start of every operation.
      */
     public JpaAuthorizationService(String aName, EntityManager aEntityManager,
-        UserAccessor aAccessor, UserAdministration aUserAdmin, long aRefreshInterval) {
+        UserAccessor aAccessor, UserAdministration aUserAdmin,
+        long aRefreshInterval) {
         entityManager = aEntityManager;
         refreshInterval = aRefreshInterval;
         lastRefreshTime = System.currentTimeMillis();
         userAccessor = aAccessor;
         userAdmin = aUserAdmin;
         name = aName;
+        Computation<AuthorizationService> computation = new Computation<AuthorizationService>() {
+            @Override
+            public boolean isOutOfDate() {
+                long time = System.currentTimeMillis();
+                return service.getCached() == null ||
+                    (time - lastRefreshTime) > refreshInterval;
+            }
+
+            @Override
+            public AuthorizationService compute() {
+                AuthorizationService svc = refreshByReload();
+                lastRefreshTime = System.currentTimeMillis();
+                return svc;
+            }
+        };
+        service = new ComputedValue<AuthorizationService>(this, computation);
     }
-    
+
     @Override
     public void setUserAccessor(UserAccessor aUserAccessor) {
-        userAccessor = aUserAccessor;   
+        userAccessor = aUserAccessor;
     }
-    
+
     @Override
     public void setUserAdministration(UserAdministration aUserAdmin) {
-        userAdmin = aUserAdmin;   
+        userAdmin = aUserAdmin;
     }
 
     private AuthorizationService refreshByReload() {
-        if ( userAdmin == null ) { 
-            throw new IllegalArgumentException("useradmin is null");
-        }
-        AuthorizationService svc; 
+        AuthorizationService svc;
         try {
             svc = entityManager.createNamedQuery(
                 AbstractAuthorizationService.QUERY_FIND_BY_NAME,
                 AbstractAuthorizationService.class).setParameter(
-                    DefaultAuthorizationService.NAME_PARAM, name).getSingleResult();
+                DefaultAuthorizationService.NAME_PARAM, name).getSingleResult();
             svc.setUserAccessor(userAccessor);
             svc.setUserAdministration(userAdmin);
         } catch (NonUniqueResultException e) {
@@ -137,9 +154,7 @@ public class JpaAuthorizationService implements AuthorizationService {
      * .lang.Object, org.wamblee.security.authorization.Operation)
      */
     public boolean isAllowed(Object aResource, Operation aOperation) {
-        refresh();
-
-        return service.isAllowed(aResource, aOperation);
+        return service.get().isAllowed(aResource, aOperation);
     }
 
     /*
@@ -149,9 +164,7 @@ public class JpaAuthorizationService implements AuthorizationService {
      * org.wamblee.security.authorization.Operation)
      */
     public <T> T check(T aResource, Operation aOperation) {
-        refresh();
-
-        return service.check(aResource, aOperation);
+        return service.get().check(aResource, aOperation);
     }
 
     /*
@@ -160,9 +173,7 @@ public class JpaAuthorizationService implements AuthorizationService {
      * @see org.wamblee.security.authorization.AuthorizationService#getRules()
      */
     public AuthorizationRule[] getRules() {
-        refresh();
-
-        return service.getRules();
+        return service.get().getRules();
     }
 
     /*
@@ -175,18 +186,11 @@ public class JpaAuthorizationService implements AuthorizationService {
     public void appendRule(AuthorizationRule aRule) {
         AuthorizationService svc = refreshByReload();
         svc.appendRule(aRule);
-        // Setting service to null will force reload the next time the 
-        // service is used. This deals effectively with the case where the 
-        // current transaction would roll back and the change would not have been made. 
-        setService(null);
-    }
-    
-    private synchronized AuthorizationService getService() { 
-        return service; 
-    }
-    
-    private synchronized void setService(AuthorizationService aSvc) { 
-        service = aSvc; 
+        // Setting service to null will force reload the next time the
+        // service is used. This deals effectively with the case where the
+        // current transaction would roll back and the change would not have
+        // been made.
+        service.set(null);
     }
     
     /*
@@ -196,9 +200,9 @@ public class JpaAuthorizationService implements AuthorizationService {
      * org.wamblee.security.authorization.AuthorizationService#removeRule(int)
      */
     public void removeRule(int aIndex) {
-        AuthorizationService svc = refreshByReload(); 
+        AuthorizationService svc = refreshByReload();
         svc.removeRule(aIndex);
-        setService(null); 
+        service.set(null);
     }
 
     /*
@@ -209,20 +213,8 @@ public class JpaAuthorizationService implements AuthorizationService {
      * (int, org.wamblee.security.authorization.AuthorizationRule)
      */
     public void insertRuleAfter(int aIndex, AuthorizationRule aRule) {
-        AuthorizationService svc = refreshByReload(); 
+        AuthorizationService svc = refreshByReload();
         svc.insertRuleAfter(aIndex, aRule);
-        setService(null);
-    }
-
-    /**
-     * Refreshes the state of the service through hibernate.
-     */
-    private synchronized void refresh() {
-        long time = System.currentTimeMillis();
-
-        if (service == null || (time - lastRefreshTime) > refreshInterval) {
-            service = refreshByReload();
-            lastRefreshTime = time;
-        }
+        service.set(null);
     }
 }