[seam-commits] Seam SVN: r8121 - trunk/src/main/org/jboss/seam/security/permission.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Wed May 7 01:27:11 EDT 2008


Author: shane.bryzak at jboss.com
Date: 2008-05-07 01:27:11 -0400 (Wed, 07 May 2008)
New Revision: 8121

Added:
   trunk/src/main/org/jboss/seam/security/permission/PermissionMetadata.java
Modified:
   trunk/src/main/org/jboss/seam/security/permission/JpaPermissionStore.java
Log:
helper class for manipulating permission action sets

Modified: trunk/src/main/org/jboss/seam/security/permission/JpaPermissionStore.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/permission/JpaPermissionStore.java	2008-05-07 03:10:20 UTC (rev 8120)
+++ trunk/src/main/org/jboss/seam/security/permission/JpaPermissionStore.java	2008-05-07 05:27:11 UTC (rev 8121)
@@ -25,6 +25,7 @@
 import org.jboss.seam.annotations.security.permission.PermissionRole;
 import org.jboss.seam.annotations.security.permission.PermissionTarget;
 import org.jboss.seam.annotations.security.permission.PermissionUser;
+import org.jboss.seam.annotations.security.permission.Permissions;
 import org.jboss.seam.core.Expressions;
 import org.jboss.seam.core.Expressions.ValueExpression;
 import org.jboss.seam.log.LogProvider;
@@ -67,10 +68,14 @@
    private Map<Integer,String> queryCache = new HashMap<Integer,String>();
    
    private IdentifierPolicy identifierPolicy;
+   
+   private PermissionMetadata metadata;
 
    @Create
    public void init()
    {
+      metadata = new PermissionMetadata();
+      
       // TODO see if we can scan for this automatically      
       if (userPermissionClass == null)
       {
@@ -433,8 +438,7 @@
    
    public List<String> listAvailableActions(Object target)
    {
-      // TODO implement
-      return null;
+      return metadata.listAllowableActions(target.getClass());
    }
 
    private EntityManager lookupEntityManager()

Added: trunk/src/main/org/jboss/seam/security/permission/PermissionMetadata.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/permission/PermissionMetadata.java	                        (rev 0)
+++ trunk/src/main/org/jboss/seam/security/permission/PermissionMetadata.java	2008-05-07 05:27:11 UTC (rev 8121)
@@ -0,0 +1,180 @@
+package org.jboss.seam.security.permission;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.seam.annotations.security.permission.Permissions;
+
+/**
+ * Permission actions can either be persisted as a comma-separated list of values, or as a
+ * bit-masked numerical value where certain bits represent specific actions for that class. This
+ * is a helper class that handles the conversion automatically and presents a unified API for 
+ * dealing with these persistent actions.  
+ *  
+ * @author Shane Bryzak
+ */
+public class PermissionMetadata
+{
+   private Map<Class,Boolean> usesActionMask = new HashMap<Class,Boolean>();
+   private Map<Class,Map<String,Long>> classActions = new HashMap<Class,Map<String,Long>>();
+   
+   private synchronized void initClassActions(Class cls)
+   {
+      if (!classActions.containsKey(cls))
+      {
+         Map<String,Long> actions = new HashMap<String,Long>();
+         
+         boolean useMask = false;
+         
+         Permissions p = (Permissions) cls.getAnnotation(Permissions.class);
+         if (p != null)
+         {
+            org.jboss.seam.annotations.security.permission.Permission[] permissions = p.value();
+            if (permissions != null)
+            {
+               for (org.jboss.seam.annotations.security.permission.Permission permission : permissions)
+               {
+                  actions.put(permission.action(), permission.mask());
+                  
+                  if (permission.mask() != 0)
+                  {
+                     useMask = true;
+                  }
+               }
+            }            
+         }
+         
+         // Validate that all actions have a proper mask
+         if (useMask)
+         {
+            Set<Long> masks = new HashSet<Long>();
+            
+            for (String action : actions.keySet())
+            {
+               Long mask = actions.get(action);
+               if (masks.contains(mask))
+               {
+                  throw new IllegalArgumentException("Class " + cls.getName() + 
+                        " defines a duplicate mask for permission action [" + action + "]");
+               }
+                              
+               if (mask == 0)
+               {
+                  throw new IllegalArgumentException("Class " + cls.getName() +
+                        " must define a valid mask value for action [" + action + "]");
+               }
+               
+               if ((mask & (mask - 1)) != 0)
+               {
+                  throw new IllegalArgumentException("Class " + cls.getName() +
+                        " must define a mask value that is a power of 2 for action [" + action + "]");
+               }
+               
+               masks.add(mask);               
+            }
+         }
+
+         usesActionMask.put(cls, useMask);
+         classActions.put(cls, actions);
+      }
+   }
+   
+   private class ActionSet
+   {
+      private Set<String> members = new HashSet<String>();
+      private Class targetClass;
+      
+      public ActionSet(Class targetClass, String members)
+      {
+         this.targetClass = targetClass;
+         
+         if (usesActionMask.get(targetClass))
+         {
+            // bit mask-based actions
+            long vals = Long.valueOf(members);
+            
+            Map<String,Long> actions = classActions.get(targetClass);
+            for (String action : actions.keySet())
+            {
+               long mask = actions.get(action).longValue();
+               if ((vals & mask) != 0)
+               {
+                  this.members.add(action);
+               }
+            }            
+         }
+         else
+         {
+            // comma-separated string based actions
+            String[] actions = members.split(",");
+            for (String action : actions)
+            {
+               this.members.add(action);
+            }
+         }
+      }
+      
+      public ActionSet add(String action)
+      {
+         members.add(action);
+         return this;
+      }
+      
+      public ActionSet remove(String action)
+      {
+         members.remove(action);
+         return this;
+      }
+      
+      @Override
+      public String toString()
+      {        
+         if (usesActionMask.get(targetClass))
+         {
+            Map<String,Long> actions = classActions.get(targetClass);
+            long mask = 0;
+            
+            for (String member : members)
+            {
+               mask |= actions.get(member).longValue();
+            }
+            
+            return "" + mask;
+         }
+         else
+         {
+            StringBuilder sb = new StringBuilder();
+            for (String member : members)
+            {
+               if (sb.length() > 0) sb.append(',');
+               sb.append(member);
+            }
+            return sb.toString();            
+         }
+      }
+   }
+   
+   public ActionSet createActionSet(Class targetClass, String members)
+   {      
+      if (!classActions.containsKey(targetClass)) initClassActions(targetClass);
+      
+      return new ActionSet(targetClass, members);
+   }
+   
+   public List<String> listAllowableActions(Class targetClass)
+   {
+      if (!classActions.containsKey(targetClass)) initClassActions(targetClass);
+      
+      List<String> actions = new ArrayList<String>();
+      for (String action : classActions.get(targetClass).keySet())
+      {
+         actions.add(action);
+      }
+      
+      return actions;
+   }
+}




More information about the seam-commits mailing list