taylor      2004/09/17 22:26:28

  Modified:    commons/src/java/org/apache/jetspeed/security
                        FolderPermission.java
  Log:
  Enhanced the FolderPermission to support inherited permissions a la Java File 
Permission
  supporting pathnames ending in /- (recursive), /* all contents of the folder
  Patch provided by Christophe Lombard
  
  CVS: ----------------------------------------------------------------------
  CVS: PR:
  CVS:   If this change addresses a PR in the problem report tracking
  CVS:   database, then enter the PR number(s) here.
  CVS: Obtained from:
  CVS:   If this change has been taken from another system, such as NCSA,
  CVS:   then name the system in this line, otherwise delete it.
  CVS: Submitted by:
  CVS:   If this code has been contributed to Apache by someone else; i.e.,
  CVS:   they sent us a patch or a new module, then include their name/email
  CVS:   address here. If this is your work then delete this line.
  CVS: Reviewed by:
  CVS:   If we are doing pre-commit code reviews and someone else has
  CVS:   reviewed your changes, include their name(s) here.
  CVS:   If you have not had it reviewed then delete this line.
  
  Revision  Changes    Path
  1.2       +262 -76   
jakarta-jetspeed-2/commons/src/java/org/apache/jetspeed/security/FolderPermission.java
  
  Index: FolderPermission.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-jetspeed-2/commons/src/java/org/apache/jetspeed/security/FolderPermission.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- FolderPermission.java     3 Sep 2004 18:22:26 -0000       1.1
  +++ FolderPermission.java     18 Sep 2004 05:26:28 -0000      1.2
  @@ -14,93 +14,279 @@
   */
   package org.apache.jetspeed.security;
   
  -import java.security.AccessControlContext;
  -import java.security.AccessController;
   import java.security.Permission;
   import java.security.PermissionCollection;
  +import java.util.StringTokenizer;
   
   import javax.security.auth.Subject;
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.jetspeed.JetspeedActions;
  +import org.apache.jetspeed.security.PortalResourcePermission;
  +import org.apache.jetspeed.security.PortalResourcePermissionCollection;
  +
   /**
    * <p>Folder permission.</p>
  - * <p>This code was partially inspired from articles from:</p>
  + * <p>This code was partially inspired from:</p>
    * <ul>
  - *    <li><a href="http://www-106.ibm.com/developerworks/library/j-jaas/";>
  + *    <li>The article : <a 
href="http://www-106.ibm.com/developerworks/library/j-jaas/";>
    *    Extend JAAS for class instance-level authorization.</a></li>
  + *    <li>The FilePermission implementation from the JDK in order to support 
recursive permissions & wild card</li>
    * </ul>
  + * 
  + * This class represents access to a portal content/folder or document.  A 
FolderPermission consists
  + * of a pathname and a set of actions valid for that pathname.
  + * <P>
  + * Pathname is the pathname of the folder or document granted the specified
  + * actions. A pathname that ends in "/*" (where "/" is
  + * the  separator character) indicates all the folders and documents contained in 
that folder. 
  + * A pathname that ends with "/-" indicates (recursively) all documents
  + * and subfolders contained in that directory. A pathname consisting of
  + * the special token "&lt;&lt;ALL FILES&gt;&gt;" matches <b>any</b> folder or 
document.
  + * <P>
  + *
    * @author <a href="mailto:[EMAIL PROTECTED]">David Sean Taylor</a>
  + * @author <a href="mailto:[EMAIL PROTECTED]">Christophe Lombart</a>
  + * @version $Id$
    */
   public class FolderPermission extends PortalResourcePermission
  -{    
  -    /**
  -     * <p>Constructor for FolderPermission.</p>
  -     * @param name The portlet name.
  -     * @param actions The actions on the portlet.
  -     */
  -    public FolderPermission(String name, String actions)
  -    {
  -        this(name, actions, null);
  -    }
  -
  -    /**
  -     * <p>Constructor for FolderPermission.</p>
  -     * @param name The portlet name.
  -     * @param actions The actions on the portlet.
  -     */
  -    public FolderPermission(String name, String actions, Subject subject)
  -    {
  -        super(name, actions, subject);
  -    }
  -
  -    public boolean implies(Permission permission)
  -    {
  -        // The permission must be an instance 
  -        // of the PortletPermission.
  -        if (!(permission instanceof FolderPermission))
  -        {
  -            return false;
  -        }
  -
  -        // The portlet name must be the same.
  -        if (!(permission.getName().equals(getName())))
  -        {
  -            return false;
  -        }
  -
  -        FolderPermission folderPerm = (FolderPermission) permission;
  -
  -        // Get the subject.
  -        // It was either provide in the constructor.
  -        Subject user = folderPerm.getSubject();
  -        // Or we get it from the AccessControlContext.
  -        if (null == user)
  -        {
  -            AccessControlContext context = AccessController.getContext();
  -            user = Subject.getSubject(context);
  -        }
  -        // No user was passed.  The permission must be denied.
  -        if (null == user)
  -        {
  -            return false;
  -        }
  -
  -        // The action bits in FolderPerm (permission) 
  -        // must be set in the current mask permission.
  -        if ((mask & folderPerm.mask) != folderPerm.mask)
  -        {
  -            return false;
  -        }
  -
  -        return true;
  -    }
  -
  -    /**
  -     * <p>Overrides <code>Permission.newPermissionCollection()</code>.</p>
  -     * @see java.security.Permission#newPermissionCollection()
  -     */
  -    public PermissionCollection newPermissionCollection()
  -    {
  -        return new PortalResourcePermissionCollection();
  -    }
  +{
  +
  +   private final static Log log = LogFactory.getLog(FolderPermission.class);
  +
  +   // does path indicate a folder? (wildcard or recursive)
  +   private transient boolean folder;
  +
  +   // is it a recursive directory specification?
  +   private transient boolean recursive;
  +
  +   private static final char RECURSIVE_CHAR = '-';
  +   private static final char WILD_CHAR = '*';
  +   private static final char FOLDER_SEPARATOR = '/';
  +
  +   private transient String cpath;
  +
  +   /**
  +    * <p>Constructor for FolderPermission.</p>
  +    * @param name The portlet name.
  +    * @param actions The actions on the portlet.
  +    */
  +   public FolderPermission(String name, String actions)
  +   {
  +       this(name, actions, null);
  +   }
  +
  +   /**
  +    * <p>Constructor for FolderPermission.</p>
  +    * @param name The portlet name.
  +    * @param actions The actions on the portlet.
  +    */
  +   public FolderPermission(String name, String actions, Subject subject)
  +   {
  +       super(name, actions, subject);
  +       parseActions(actions);
  +       this.subject = subject;
  +   }
  +
  +
  +   /**
  +    * <p>Overrides <code>Permission.newPermissionCollection()</code>.</p>
  +    * @see java.security.Permission#newPermissionCollection()
  +    */
  +   public PermissionCollection newPermissionCollection()
  +   {
  +       return new PortalResourcePermissionCollection();
  +   }
  +
  +   /**
  +    * <p>Parses the actions string.</p>
  +    * <p>Actions are separated by commas or white space.</p>
  +    * @param actions The actions
  +    */
  +   private void parseActions(String actions)
  +   {
  +       mask = 0;
  +       if (actions != null)
  +       {
  +           StringTokenizer tokenizer = new StringTokenizer(actions, ",\t ");
  +           while (tokenizer.hasMoreTokens())
  +           {
  +               String token = tokenizer.nextToken();
  +               if (token.equals(JetspeedActions.VIEW))
  +                   mask |= JetspeedActions.MASK_VIEW;
  +               else if (token.equals(JetspeedActions.VIEW) || 
token.equals(JetspeedActions.RESTORE))
  +                   mask |= JetspeedActions.MASK_VIEW;
  +               else if (token.equals(JetspeedActions.EDIT))
  +                   mask |= JetspeedActions.MASK_EDIT;
  +               else if (token.equals(JetspeedActions.MINIMIZE))
  +                   mask |= JetspeedActions.MASK_MINIMIZE;
  +               else if (token.equals(JetspeedActions.MAXIMIZE))
  +                   mask |= JetspeedActions.MASK_MAXIMIZE;
  +               else if (token.equals(JetspeedActions.HELP))
  +                   mask |= JetspeedActions.MASK_HELP;
  +               else if (token.equals(JetspeedActions.SECURE))
  +                   mask |= JetspeedActions.MASK_SECURE;
  +               else
  +                   throw new IllegalArgumentException("Unknown action: " + token);
  +           }
  +       }
  +
  +       if ((cpath = getName()) == null)
  +           throw new NullPointerException("name can't be null");
  +
  +       if (cpath.equals("<<ALL FILES>>"))
  +       {
  +           folder = true;
  +           recursive = true;
  +           cpath = "";
  +           return;
  +       }
  +       int len = cpath.length();
  +
  +       if (len == 0)
  +       {
  +           throw new IllegalArgumentException("invalid folder reference");
  +       }
  +
  +       char last = cpath.charAt(len - 1);
  +
  +       if (last == RECURSIVE_CHAR && (len == 1 || cpath.charAt(len - 2) == 
FOLDER_SEPARATOR))
  +       {
  +           folder = true;
  +           recursive = true;
  +           cpath = cpath.substring(0, --len);
  +       }
  +       else if (last == WILD_CHAR && (len == 1 || cpath.charAt(len - 2) == 
FOLDER_SEPARATOR))
  +       {
  +           folder = true;
  +           //recursive = false;
  +           cpath = cpath.substring(0, --len);
  +       }
  +
  +   }
  +
  +   /**
  +    * Checks if this FolderPermission object "implies" the specified permission.
  +    * <P>
  +    * More specifically, this method returns true if:<p>
  +    * <ul>
  +    * <li> <i>p</i> is an instanceof FolderPermission,<p>
  +    * <li> <i>p</i>'s actions are a proper subset of this
  +    * object's actions, and <p>
  +    * <li> <i>p</i>'s pathname is implied by this object's
  +    *      pathname. For example, "/tmp/*" implies "/tmp/foo", since
  +    *      "/tmp/*" encompasses the "/tmp" folder and all subfolders or documents 
in that
  +    *      directory, including the one named "foo".
  +    * </ul>
  +    * @param p the permission to check against.
  +    *
  +    * @return true if the specified permission is implied by this object,
  +    * false if not.  
  +    */
  +   public boolean implies(Permission p)
  +   {
  +       if (!(p instanceof FolderPermission))
  +       {
  +           return false;
  +       }
  +
  +       FolderPermission that = (FolderPermission) p;
  +       return ((this.mask & that.mask) == that.mask) && impliesIgnoreMask(that);
  +   }
  +
  +   /**
  +    * Checks if the Permission's actions are a proper subset of the
  +    * this object's actions. Returns the effective mask iff the
  +    * this FolderPermission's path also implies that FolderPermission's path.
  +    * 
  +    * @param that the FolderPermission to check against.
  +    * @return the effective mask
  +    */
  +   boolean impliesIgnoreMask(FolderPermission that)
  +   {
  +       if (this.folder)
  +       {
  +           if (this.recursive)
  +           {
  +               // make sure that.path is longer then path so
  +               // something like /foo/- does not imply /foo
  +               if (that.folder)
  +               {
  +                   return (that.cpath.length() >= this.cpath.length()) && 
that.cpath.startsWith(this.cpath);
  +               }
  +               else
  +               {
  +                   return ((that.cpath.length() > this.cpath.length()) && 
that.cpath.startsWith(this.cpath));
  +               }
  +           }
  +           else
  +           {
  +               if (that.folder)
  +               {
  +                   // if the permission passed in is a folder
  +                   // specification, make sure that a non-recursive
  +                   // permission (i.e., this object) can't imply a recursive
  +                   // permission.
  +                   if (that.recursive)
  +                       return false;
  +                   else
  +                       return (this.cpath.equals(that.cpath));
  +               }
  +               else
  +               {
  +                   int last = that.cpath.lastIndexOf(FOLDER_SEPARATOR);
  +                   if (last == -1)
  +                       return false;
  +                   else
  +                   {
  +                       // this.cpath.equals(that.cpath.substring(0, last+1));
  +                       // Use regionMatches to avoid creating new string
  +
  +                       return (this.cpath.length() == (last + 1)) && 
this.cpath.regionMatches(0, that.cpath, 0, last + 1);
  +                   }
  +               }
  +           }
  +       }
  +       else
  +       {
  +           return (this.cpath.equals(that.cpath));
  +       }
  +   }
  +
  +   /**
  +    * Checks two FolderPermission objects for equality. Checks that <i>obj</i> is
  +    * a FolderPermission, and has the same pathname and actions as this object.
  +    * <P>
  +    * @param obj the object we are testing for equality with this object.
  +    * @return true if obj is a FolderPermission, and has the same pathname and
  +    * actions as this FolderPermission object.
  +    */
  +   public boolean equals(Object obj)
  +   {
  +       if (obj == this)
  +           return true;
  +
  +       if (!(obj instanceof FolderPermission))
  +           return false;
  +
  +       FolderPermission that = (FolderPermission) obj;
  +
  +       return (this.mask == that.mask) && this.cpath.equals(that.cpath) && 
(this.folder == that.folder)
  +               && (this.recursive == that.recursive);
  +   }
  +
  +   /**
  +    * Returns the hash code value for this object.
  +    * 
  +    * @return a hash code value for this object.
  +    */
  +
  +   public int hashCode()
  +   {
  +       return this.cpath.hashCode();
  +   }
  +   
  +   
   
  -}
  +}
  \ No newline at end of file
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to