jspwiki-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ajaqu...@apache.org
Subject svn commit: r627255 [13/41] - in /incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src: ./ com/ com/ecyrd/ com/ecyrd/jspwiki/ com/ecyrd/jspwiki/action/ com/ecyrd/jspwiki/attachment/ com/ecyrd/jspwiki/auth/ com/ecyrd/jspwiki/auth/acl/ com/ecyrd/jspwiki...
Date Wed, 13 Feb 2008 05:54:24 GMT
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/WikiPrincipal.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/WikiPrincipal.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/WikiPrincipal.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/WikiPrincipal.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,155 @@
+/* 
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2004 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.auth;
+
+import java.security.Principal;
+import java.util.Comparator;
+
+/**
+ *  A lightweight, immutable Principal class. WikiPrincipals can be created with
+ *  and optional "type" to denote what type of user profile Principal it represents
+ *  (FULL_NAME, WIKI_NAME, LOGIN_NAME). Types are used to determine suitable
+ *  user and login Principals in classes like WikiSession. However, the type
+ *  property of a WikiPrincipal does not affect a WikiPrincipal's logical equality
+ *  or hash code; two WikiPrincipals with the same name but different types are still
+ *  considered equal.
+ *
+ *  @author Janne Jalkanen
+ *  @author Andrew Jaquith
+ *  @since  2.2
+ */
+public final class WikiPrincipal implements Principal
+{
+
+    /**
+     * Represents an anonymous user. WikiPrincipals may be
+     * created with an optional type designator: 
+     * LOGIN_NAME, WIKI_NAME, FULL_NAME or UNSPECIFIED.
+     */
+    public static final Principal GUEST = new WikiPrincipal( "Guest" );
+
+    /** WikiPrincipal type denoting a user's full name. */
+    public static final String FULL_NAME  = "fullName";
+    
+    /** WikiPrincipal type denoting a user's login name. */
+    public static final String LOGIN_NAME = "loginName";
+    
+    /** WikiPrincipal type denoting a user's wiki name. */
+    public static final String WIKI_NAME  = "wikiName";
+    
+    /** Generic WikiPrincipal of unspecified type. */
+    public static final String UNSPECIFIED  = "unspecified";
+    
+    /** Static instance of Comparator that allows Principals to be sorted. */
+    public static final Comparator<Principal> COMPARATOR = new PrincipalComparator();
+    
+    private final String          m_name;
+    private final String          m_type;
+
+    /**
+     * Constructs a new WikiPrincipal with a given name and a type of
+     * {@link #UNSPECIFIED}.
+     * @param name the name of the Principal
+     */
+    public WikiPrincipal( String name )
+    {
+        this( name, UNSPECIFIED );
+    }
+    
+    /**
+     * Constructs a new WikiPrincipal with a given name and optional type
+     * designator. If the supplied <code>type</code> parameter is not
+     * {@link #LOGIN_NAME}, {@link #FULL_NAME}, {@link #WIKI_NAME}
+     * or {@link #WIKI_NAME}, this method throws
+     * an {@link IllegalArgumentException}.
+     * @param name the name of the Principal
+     * @param type the type for this principal, which may be {@link #LOGIN_NAME},
+     *            {@link #FULL_NAME}, {@link #WIKI_NAME} or {@link #WIKI_NAME}.
+     */
+    public WikiPrincipal( String name, String type )
+    {
+        if ( name == null )
+        {
+            throw new IllegalArgumentException( "Name cannot be null" );
+        }
+        m_name = name;
+        if ( !FULL_NAME.equals(type) && !LOGIN_NAME.equals(type) &&
+              !WIKI_NAME.equals(type) && !UNSPECIFIED.equals(type) )
+        {
+            throw new IllegalArgumentException( "Principal type '" + type + "' is invalid.");
+        }
+        m_type = type;
+    }
+
+    /**
+     *  Returns the wiki name of the Principal.
+     *  @return the name
+     */
+    public final String getName()
+    {
+        return m_name;
+    }
+
+    /**
+     * Two <code>WikiPrincipal</code>s are considered equal if their
+     * names are equal (case-sensitive).
+     * @param obj the object to compare
+     * @return the result of the equality test
+     */
+    public final boolean equals( Object obj )
+    {
+        if ( obj == null || !( obj instanceof WikiPrincipal ) )
+        {
+            return false;
+        }
+        return m_name.equals( ( (WikiPrincipal) obj ).getName() );
+    }
+
+    /**
+     *  The hashCode() returned for the WikiPrincipal is the same as
+     *  for its name.
+     *  @return the hash code
+     */
+    public final int hashCode()
+    {
+        return m_name.hashCode();
+    }
+    
+    /**
+     * Returns the Principal "type": {@link #LOGIN_NAME}, {@link #FULL_NAME},
+     * {@link #WIKI_NAME} or {@link #WIKI_NAME}
+     * @return the type
+     */
+    public final String getType()
+    {
+        return m_type;
+    }
+    
+    /**
+     * Returns a human-readable representation of the object.
+     * @return the string representation
+     */
+    public final String toString()
+    {
+        return "[WikiPrincipal (" + m_type + "): " + getName() + "]";
+    }
+    
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/WikiSecurityException.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/WikiSecurityException.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/WikiSecurityException.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/WikiSecurityException.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,44 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.auth;
+
+import com.ecyrd.jspwiki.WikiException;
+
+/**
+ *  Indicates an authentication or authorization
+ *  error or exception.
+ *
+ *  @author Erik Bunn
+ *  @since 2.0
+ */
+public class WikiSecurityException
+    extends WikiException
+{
+    private static final long serialVersionUID = 3617293441285764405L;
+
+    /**
+     *  Constructs an exception.
+     *  @param msg the message to supply to the exception
+     */
+    public WikiSecurityException( String msg )
+    {
+        super(msg);
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/Acl.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/Acl.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/Acl.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/Acl.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,117 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.auth.acl;
+
+import java.security.Permission;
+import java.security.Principal;
+import java.util.Enumeration;
+
+/**
+ * <p>
+ * Defines an access control list (ACL) for wiki pages. An Access Control List
+ * is a data structure used to guard access to resources. An ACL can be thought
+ * of as a data structure with multiple ACL entries. Each ACL entry, of
+ * interface type AclEntry, contains a set of positive permissions associated
+ * with a particular principal. (A principal represents an entity such as an
+ * individual user or a group). The ACL Entries in each ACL observe the
+ * following rules:
+ * </p>
+ * <ul>
+ * <li>Each principal can have at most one ACL entry; that is, multiple ACL
+ * entries are not allowed for any principal. Each entry specifies the set of
+ * permissions that are to be granted</li>
+ * <li>If there is no entry for a particular principal, then the principal is
+ * considered to have a null (empty) permission set</li>
+ * </ul>
+ * <p>
+ * This interface is a highly stripped-down derivation of the
+ * java.security.acl.Acl interface. In particular, the notion of an Acl "owner"
+ * has been eliminated, since JWPWiki pages do not have owners. An additional
+ * simplification compared to the standard Java package is that negative
+ * permissions have been eliminated. Instead, JSPWiki assumes a "default-deny"
+ * security stance: principals are granted no permissions by default, and
+ * posesses only those that have been explicitly granted to them. And finally,
+ * the getPermissions() and checkPermission() methods have been eliminated due
+ * to the complexities associated with resolving Role principal membership.
+ * </p>
+ * @author Janne Jalkanen
+ * @author Andrew Jaquith
+ * @since 2.3
+ */
+public interface Acl
+{
+    /**
+     * Adds an ACL entry to this ACL. An entry associates a principal (e.g., an
+     * individual or a group) with a set of permissions. Each principal can have
+     * at most one positive ACL entry, specifying permissions to be granted to
+     * the principal. If there is already an ACL entry already in the ACL, false
+     * is returned.
+     * @param entry - the ACL entry to be added to this ACL
+     * @return true on success, false if an entry of the same type (positive or
+     *         negative) for the same principal is already present in this ACL
+     */
+    public boolean addEntry( AclEntry entry );
+
+    /**
+     * Returns an enumeration of the entries in this ACL. Each element in the
+     * enumeration is of type AclEntry.
+     * @return an enumeration of the entries in this ACL.
+     */
+    public Enumeration entries();
+
+    /**
+     * Returns <code>true</code>, if this Acl is empty.
+     * @return the result
+     * @since 2.4.68
+     */
+    public boolean isEmpty();
+
+    /**
+     * Returns all Principal objects assigned a given Permission in the access
+     * control list. The Princiapls returned are those that have been granted
+     * either the supplied permission, or a permission implied by the supplied
+     * permission. Principals are not "expanded" if they are a role or group.
+     * @param permission the permission to search for
+     * @return an array of Principals posessing the permission
+     */
+    public Principal[] findPrincipals( Permission permission );
+
+    /**
+     * Returns an AclEntry for a supplied Principal, or <code>null</code> if
+     * the Principal does not have a matching AclEntry.
+     * @param principal the principal to search for
+     * @return the AclEntry associated with the principal, or <code>null</code>
+     */
+    public AclEntry getEntry( Principal principal );
+
+    /**
+     * Removes an ACL entry from this ACL.
+     * @param entry the ACL entry to be removed from this ACL
+     * @return true on success, false if the entry is not part of this ACL
+     */
+    public boolean removeEntry( AclEntry entry );
+
+    /**
+     * Returns a string representation of the contents of this Acl.
+     * @return the string representation
+     */
+    public String toString();
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclEntry.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclEntry.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclEntry.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclEntry.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,108 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2007 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.auth.acl;
+
+import java.security.Permission;
+import java.security.Principal;
+import java.util.Enumeration;
+
+/**
+ * <p>
+ * Represents one entry in an Access Control List (ACL).
+ * </p>
+ * <p>
+ * An ACL can be thought of as a data structure with multiple ACL entry objects.
+ * Each ACL entry object contains a set of positive page permissions associated
+ * with a particular principal. (A principal represents an entity such as an
+ * individual user, group, or role). Each principal can have at most one ACL
+ * entry; that is, multiple ACL entries are not allowed for any principal.
+ * </p>
+ * <p>
+ * This interface is functionally equivalent to the java.security.acl.AclEntry
+ * interface, minus negative permissions.
+ * </p>
+ * @see Acl
+ * @author Janne Jalkanen
+ * @author Andrew Jaquith
+ * @since 2.3
+ */
+public interface AclEntry
+{
+
+    /**
+     * Adds the specified permission to this ACL entry. The permission
+     * <em>must</em> be of type
+     * {@link com.ecyrd.jspwiki.auth.permissions.PagePermission}. Note: An entry
+     * can have multiple permissions.
+     * @param permission the permission to be associated with the principal in
+     *            this entry
+     * @return <code>true</code> if the permission was added, 
+     *         <code>false</code> if the permission was
+     *         already part of this entry's permission set, and <code>false</code> if
+     *         the permission is not of type PagePermission
+     */
+    public boolean addPermission(Permission permission);
+
+    /**
+     * Checks if the specified permission is part of the permission set in this
+     * entry.
+     * @param permission the permission to be checked for.
+     * @return true if the permission is part of the permission set in this entry,
+     *         false otherwise.
+     */
+    public boolean checkPermission(Permission permission);
+
+    /**
+     * Returns the principal for which permissions are granted by this
+     * ACL entry. Returns null if there is no principal set for this entry yet.
+     * @return the principal associated with this entry.
+     */
+    public Principal getPrincipal();
+
+    /**
+     * Returns an enumeration of the permissions in this ACL entry.
+     * @return an enumeration of the permissions
+     */
+    public Enumeration permissions();
+
+    /**
+     * Removes the specified permission from this ACL entry.
+     * @param permission the permission to be removed from this entry.
+     * @return true if the permission is removed, false if the permission was not
+     *         part of this entry's permission set.
+     */
+    public boolean removePermission(Permission permission);
+
+    /**
+     * Specifies the principal for which permissions are granted or denied by
+     * this ACL entry. If a principal was already set for this ACL entry, false
+     * is returned, otherwise true is returned.
+     * @param user the principal to be set for this entry
+     * @return true if the principal is set, false if there was already a
+     *         principal set for this entry
+     */
+    public boolean setPrincipal(Principal user);
+
+    /**
+     * Returns a string representation of the contents of this ACL entry.
+     * @return a string representation of the contents.
+     */
+    public String toString();
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclEntryImpl.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclEntryImpl.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclEntryImpl.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclEntryImpl.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,185 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2007 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.auth.acl;
+
+import java.security.Permission;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+
+import com.ecyrd.jspwiki.auth.permissions.PagePermission;
+
+/**
+ * Implementation of a JSPWiki AclEntry.
+ * @author Janne Jalkanen
+ * @author Andrew Jaquith
+ * @since 2.3
+ */
+public class AclEntryImpl implements AclEntry
+{
+
+    private Vector    m_permissions = new Vector();
+    private Principal m_principal;
+
+    /**
+     * Constructs a new AclEntryImpl instance.
+     */
+    public AclEntryImpl()
+    {
+    }
+
+    /**
+     * Adds the specified permission to this ACL entry. The permission
+     * <em>must</em> be of type
+     * {@link com.ecyrd.jspwiki.auth.permissions.PagePermission}. Note: An entry
+     * can have multiple permissions.
+     * @param permission the permission to be associated with the principal in
+     *            this entry
+     * @return <code>true</code> if the permission was added, 
+     *         <code>false</code> if the permission was
+     *         already part of this entry's permission set, and <code>false</code> if
+     *         the permission is not of type PagePermission
+     */
+    public synchronized boolean addPermission( Permission permission )
+    {
+        if ( permission instanceof PagePermission && findPermission( permission ) == null )
+        {
+            m_permissions.add( permission );
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks if the specified permission is part of the permission set in this
+     * entry.
+     * @param permission the permission to be checked for.
+     * @return true if the permission is part of the permission set in this entry,
+     *         false otherwise.
+     */
+    public boolean checkPermission( Permission permission )
+    {
+        return findPermission( permission ) != null;
+    }
+
+    /**
+     * Returns the principal for which permissions are granted by this
+     * ACL entry. Returns null if there is no principal set for this entry yet.
+     * @return the principal associated with this entry.
+     */
+    public synchronized Principal getPrincipal()
+    {
+        return m_principal;
+    }
+
+    /**
+     * Returns an enumeration of the permissions in this ACL entry.
+     * @return an enumeration of the permissions
+     */
+    public Enumeration permissions()
+    {
+        return m_permissions.elements();
+    }
+
+    /**
+     * Removes the specified permission from this ACL entry.
+     * @param permission the permission to be removed from this entry.
+     * @return true if the permission is removed, false if the permission was not
+     *         part of this entry's permission set.
+     */
+    public synchronized boolean removePermission( Permission permission )
+    {
+        Permission p = findPermission( permission );
+
+        if ( p != null )
+        {
+            m_permissions.remove( p );
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Specifies the principal for which permissions are granted or denied by
+     * this ACL entry. If a principal was already set for this ACL entry, false
+     * is returned, otherwise true is returned.
+     * @param user the principal to be set for this entry
+     * @return true if the principal is set, false if there was already a
+     *         principal set for this entry
+     */
+    public synchronized boolean setPrincipal( Principal user )
+    {
+        if ( m_principal != null || user == null )
+            return false;
+
+        m_principal = user;
+
+        return true;
+    }
+
+    /**
+     * Returns a string representation of the contents of this ACL entry.
+     * @return a string representation of the contents.
+     */
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+
+        Principal p = getPrincipal();
+
+        sb.append( "[AclEntry ALLOW " + ( p != null ? p.getName() : "null" ) );
+        sb.append( " " );
+
+        for( Iterator i = m_permissions.iterator(); i.hasNext(); )
+        {
+            Permission pp = (Permission) i.next();
+
+            sb.append( pp.toString() );
+            sb.append( "," );
+        }
+
+        sb.append( "]" );
+
+        return sb.toString();
+    }
+
+    /**
+     * Looks through the permission list and finds a permission that matches the
+     * permission.
+     */
+    private Permission findPermission( Permission p )
+    {
+        for( Iterator i = m_permissions.iterator(); i.hasNext(); )
+        {
+            Permission pp = (Permission) i.next();
+
+            if ( pp.implies( p ) )
+            {
+                return pp;
+            }
+        }
+
+        return null;
+    }
+}
+

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclImpl.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclImpl.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclImpl.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclImpl.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,212 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2004 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.auth.acl;
+
+import java.security.Permission;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+
+/**
+ *  JSPWiki implementation of an Access Control List.
+ *  @author Janne Jalkanen
+ *  @author Andrew Jaquith
+ *  @since 2.3
+ */
+public class AclImpl implements Acl
+{
+    private final Vector<AclEntry> m_entries = new Vector<AclEntry>();
+
+    /**
+     * Constructs a new AclImpl instance.
+     */
+    public AclImpl()
+    {
+    }
+    
+    /**
+     * Returns all Principal objects assigned a given Permission in the access
+     * control list. The Princiapls returned are those that have been granted
+     * either the supplied permission, or a permission implied by the supplied
+     * permission. Principals are not "expanded" if they are a role or group.
+     * @param permission the permission to search for
+     * @return an array of Principals posessing the permission
+     */
+    public Principal[] findPrincipals( Permission permission )
+    {
+        Vector<Principal> principals = new Vector<Principal>();
+        Enumeration entries = entries();
+        
+        while (entries.hasMoreElements()) 
+        {
+            AclEntry entry = (AclEntry)entries.nextElement();
+            Enumeration permissions = entry.permissions();
+            while ( permissions.hasMoreElements() ) 
+            {
+                Permission perm = (Permission)permissions.nextElement();
+                if ( perm.implies( permission ) ) 
+                {
+                    principals.add( entry.getPrincipal() );
+                }
+            }
+        }
+        return principals.toArray( new Principal[principals.size()] );
+    }
+  
+    private boolean hasEntry( AclEntry entry )
+    {
+        if( entry == null )
+        {
+            return false;
+        }
+
+        for( Iterator i = m_entries.iterator(); i.hasNext(); )
+        {
+            AclEntry e = (AclEntry) i.next();
+
+            Principal ep     = e.getPrincipal();
+            Principal entryp = entry.getPrincipal();
+
+            if( ep == null || entryp == null )
+            {
+                throw new IllegalArgumentException( "Entry is null; check code, please (entry="+entry+"; e="+e+")" );
+            }
+            
+            if( ep.getName().equals( entryp.getName() ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Adds an ACL entry to this ACL. An entry associates a principal (e.g., an
+     * individual or a group) with a set of permissions. Each principal can have
+     * at most one positive ACL entry, specifying permissions to be granted to
+     * the principal. If there is already an ACL entry already in the ACL, false
+     * is returned.
+     * @param entry - the ACL entry to be added to this ACL
+     * @return true on success, false if an entry of the same type (positive or
+     *         negative) for the same principal is already present in this ACL
+     */
+    public synchronized boolean addEntry( AclEntry entry )
+    {
+        if( entry.getPrincipal() == null )
+        {
+            throw new IllegalArgumentException( "Entry principal cannot be null" );
+        }
+
+        if( hasEntry( entry ) )
+        {
+            return false;
+        }
+        
+        m_entries.add( entry );
+
+        return true;
+    }
+
+    /**
+     * Removes an ACL entry from this ACL.
+     * @param entry the ACL entry to be removed from this ACL
+     * @return true on success, false if the entry is not part of this ACL
+     */
+    public synchronized boolean removeEntry( AclEntry entry )
+    {
+        return m_entries.remove( entry );
+    }
+
+    /**
+     * Returns an enumeration of the entries in this ACL. Each element in the
+     * enumeration is of type AclEntry.
+     * @return an enumeration of the entries in this ACL.
+     */
+    public Enumeration entries()
+    {
+        return m_entries.elements();
+    }
+
+    /**
+     * Returns an AclEntry for a supplied Principal, or <code>null</code> if
+     * the Principal does not have a matching AclEntry.
+     * @param principal the principal to search for
+     * @return the AclEntry associated with the principal, or <code>null</code>
+     */
+    public AclEntry getEntry( Principal principal )
+    {
+        for( Enumeration e = m_entries.elements(); e.hasMoreElements(); )
+        {
+            AclEntry entry = (AclEntry) e.nextElement();
+        
+            if( entry.getPrincipal().getName().equals( principal.getName() ) )
+            {
+                return entry;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns a string representation of the contents of this Acl.
+     * @return the string representation
+     */
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+
+        for( Enumeration myEnum = entries(); myEnum.hasMoreElements(); )
+        {
+            AclEntry entry = (AclEntry) myEnum.nextElement();
+
+            Principal pal = entry.getPrincipal();
+
+            if( pal != null )
+                sb.append( "  user = "+pal.getName()+": " );
+            else
+                sb.append( "  user = null: " );
+
+            sb.append( "(" );
+            for( Enumeration perms = entry.permissions(); perms.hasMoreElements(); )
+            {
+                Permission perm = (Permission) perms.nextElement();
+                sb.append( perm.toString() );
+            }
+            sb.append( ")\n" );
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Returns <code>true</code>, if this Acl is empty.
+     * @return the result
+     * @since 2.4.68
+     */
+    public boolean isEmpty()
+    {
+        return m_entries.isEmpty();
+    }
+
+}
+    

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclManager.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclManager.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclManager.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/AclManager.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,77 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2007 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.auth.acl;
+
+import java.util.Properties;
+
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiPage;
+import com.ecyrd.jspwiki.auth.WikiSecurityException;
+
+/**
+ *  Specifies how to parse and return ACLs from wiki pages.
+ *  @author Andrew Jaquith
+ *  @since 2.3
+ */
+public interface AclManager
+{
+
+    /**
+     * Initializes the AclManager with a supplied wiki engine and properties.
+     * @param engine the wiki engine
+     * @param props the initialization properties
+     */
+    public void initialize( WikiEngine engine, Properties props );
+
+    /**
+     * A helper method for parsing textual AccessControlLists. The line is in
+     * form "(ALLOW) <permission><principal>, <principal>, <principal>". This
+     * method was moved from Authorizer.
+     * @param page The current wiki page. If the page already has an ACL, it
+     *            will be used as a basis for this ACL in order to avoid the
+     *            creation of a new one.
+     * @param ruleLine The rule line, as described above.
+     * @return A valid Access Control List. May be empty.
+     * @throws WikiSecurityException if the ruleLine was faulty somehow.
+     * @since 2.1.121
+     */
+    public Acl parseAcl( WikiPage page, String ruleLine ) throws WikiSecurityException;
+
+    /**
+     * Returns the access control list for the page.
+     * If the ACL has not been parsed yet, it is done
+     * on-the-fly. If the page has a parent page, then that is tried also.
+     * This method was moved from Authorizer;
+     * it was consolidated with some code from AuthorizationManager.
+     * @param page the wiki page
+     * @since 2.2.121
+     * @return the Acl representing permissions for the page
+     */
+    public Acl getPermissions( WikiPage page );
+
+    /**
+     * Sets the access control list for the page and persists it.
+     * @param page the wiki page
+     * @param acl the access control list
+     * @since 2.5
+     * @throws WikiSecurityException if the ACL cannot be set or persisted
+     */
+    public void setPermissions( WikiPage page, Acl acl ) throws WikiSecurityException;
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/DefaultAclManager.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/DefaultAclManager.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/DefaultAclManager.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/DefaultAclManager.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,299 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2007 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.auth.acl;
+
+import java.security.Permission;
+import java.security.Principal;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+
+import com.ecyrd.jspwiki.*;
+import com.ecyrd.jspwiki.attachment.Attachment;
+import com.ecyrd.jspwiki.auth.AuthorizationManager;
+import com.ecyrd.jspwiki.auth.PrincipalComparator;
+import com.ecyrd.jspwiki.auth.WikiSecurityException;
+import com.ecyrd.jspwiki.auth.permissions.PagePermission;
+import com.ecyrd.jspwiki.auth.permissions.PermissionFactory;
+import com.ecyrd.jspwiki.providers.ProviderException;
+import com.ecyrd.jspwiki.render.RenderingManager;
+
+/**
+ * Default implementation that parses Acls from wiki page markup.
+ * @author Andrew Jaquith
+ * @since 2.3
+ */
+public class DefaultAclManager implements AclManager
+{
+    static Logger                log    = Logger.getLogger( DefaultAclManager.class );
+
+    private AuthorizationManager m_auth = null;
+    private WikiEngine m_engine = null;
+    private static final String PERM_REGEX = "(" +
+        PagePermission.COMMENT_ACTION + "|" +
+        PagePermission.DELETE_ACTION  + "|" +
+        PagePermission.EDIT_ACTION    + "|" +
+        PagePermission.MODIFY_ACTION  + "|" +
+        PagePermission.RENAME_ACTION  + "|" +
+        PagePermission.UPLOAD_ACTION  + "|" +
+        PagePermission.VIEW_ACTION    + ")";
+    private static final String ACL_REGEX = "\\[\\{\\s*ALLOW\\s+" + PERM_REGEX + "\\s*(.*?)\\s*\\}\\]";
+
+    /**
+     * Identifies ACL strings in wiki text; the first group is the action (view, edit) and
+     * the second is the list of Principals separated by commas. The overall match is
+     * the ACL string from [{ to }].
+     * */
+    public static final Pattern ACL_PATTERN = Pattern.compile( ACL_REGEX );
+
+    /**
+     * Initializes the AclManager with a supplied wiki engine and properties.
+     * @param engine the wiki engine
+     * @param props the initialization properties
+     * @see com.ecyrd.jspwiki.auth.acl.AclManager#initialize(com.ecyrd.jspwiki.WikiEngine,
+     *      java.util.Properties)
+     */
+    public void initialize( WikiEngine engine, Properties props )
+    {
+        m_auth = engine.getAuthorizationManager();
+        m_engine = engine;
+    }
+
+    /**
+     * A helper method for parsing textual AccessControlLists. The line is in
+     * form "ALLOW <permission> <principal>, <principal>, <principal>". This
+     * method was moved from Authorizer.
+     * @param page The current wiki page. If the page already has an ACL, it
+     *            will be used as a basis for this ACL in order to avoid the
+     *            creation of a new one.
+     * @param ruleLine The rule line, as described above.
+     * @return A valid Access Control List. May be empty.
+     * @throws WikiSecurityException if the ruleLine was faulty somehow.
+     * @since 2.1.121
+     */
+    public Acl parseAcl( WikiPage page, String ruleLine ) throws WikiSecurityException
+    {
+        Acl acl = page.getAcl();
+        if ( acl == null )
+            acl = new AclImpl();
+
+        try
+        {
+            StringTokenizer fieldToks = new StringTokenizer( ruleLine );
+            fieldToks.nextToken();
+            String actions = fieldToks.nextToken();
+            page.getName();
+
+            while( fieldToks.hasMoreTokens() )
+            {
+                String principalName = fieldToks.nextToken( "," ).trim();
+                Principal principal = m_auth.resolvePrincipal( principalName );
+                AclEntry oldEntry = acl.getEntry( principal );
+
+                if ( oldEntry != null )
+                {
+                    log.debug( "Adding to old acl list: " + principal + ", " + actions );
+                    oldEntry.addPermission( PermissionFactory.getPagePermission( page, actions ) );
+                }
+                else
+                {
+                    log.debug( "Adding new acl entry for " + actions );
+                    AclEntry entry = new AclEntryImpl();
+
+                    entry.setPrincipal( principal );
+                    entry.addPermission( PermissionFactory.getPagePermission( page, actions ) );
+
+                    acl.addEntry( entry );
+                }
+            }
+
+            page.setAcl( acl );
+
+            log.debug( acl.toString() );
+        }
+        catch( NoSuchElementException nsee )
+        {
+            log.warn( "Invalid access rule: " + ruleLine + " - defaults will be used." );
+            throw new WikiSecurityException( "Invalid access rule: " + ruleLine );
+        }
+        catch( IllegalArgumentException iae )
+        {
+            throw new WikiSecurityException( "Invalid permission type: " + ruleLine );
+        }
+
+        return acl;
+    }
+
+
+    /**
+     * Returns the access control list for the page.
+     * If the ACL has not been parsed yet, it is done
+     * on-the-fly. If the page has a parent page, then that is tried also.
+     * This method was moved from Authorizer;
+     * it was consolidated with some code from AuthorizationManager.
+     * This method is guaranteed to return a non-<code>null</code> Acl.
+     * @param page the page
+     * @since 2.2.121
+     * @return the Acl representing permissions for the page
+     */
+    public Acl getPermissions( WikiPage page )
+    {
+        //
+        //  Does the page already have cached ACLs?
+        //
+        Acl acl = page.getAcl();
+        log.debug( "page="+page.getName()+"\n"+acl );
+
+        if( acl == null )
+        {
+            //
+            //  If null, try the parent.
+            //
+            if( page instanceof Attachment )
+            {
+                WikiPage parent = m_engine.getPage( ((Attachment)page).getParentName() );
+
+                acl = getPermissions( parent );
+            }
+            else
+            {
+                //
+                //  Or, try parsing the page
+                //
+                WikiContext ctx = m_engine.getWikiActionBeanFactory().newViewActionBean( page );
+
+                ctx.setVariable( RenderingManager.VAR_EXECUTE_PLUGINS, Boolean.FALSE );
+
+                m_engine.getHTML( ctx, page );
+
+                page = m_engine.getPage( page.getName(), page.getVersion() );
+                acl = page.getAcl();
+
+                if( acl == null )
+                {
+                    acl = new AclImpl();
+                    page.setAcl( acl );
+                }
+            }
+        }
+
+        return acl;
+    }
+
+    /**
+     * Sets the access control list for the page and persists it by prepending
+     * it to the wiki page markup and saving the page. When this method is
+     * called, all other ACL markup in the page is removed. This method will forcibly
+     * expire locks on the wiki page if they exist. Any ProviderExceptions will be
+     * re-thrown as WikiSecurityExceptions.
+     * @param page the wiki page
+     * @param acl the access control list
+     * @since 2.5
+     * @throws WikiSecurityException of the Acl cannot be set
+     */
+    public void setPermissions( WikiPage page, Acl acl ) throws WikiSecurityException
+    {
+        PageManager pageManager = m_engine.getPageManager();
+
+        // Forcibly expire any page locks
+        PageLock lock = pageManager.getCurrentLock( page );
+        if ( lock != null )
+        {
+            pageManager.unlockPage( lock );
+        }
+
+        // Remove all of the existing ACLs.
+        String pageText = m_engine.getPureText( page );
+        Matcher matcher = DefaultAclManager.ACL_PATTERN.matcher( pageText );
+        String cleansedText = matcher.replaceAll( "" );
+        String newText = DefaultAclManager.printAcl( page.getAcl() ) + cleansedText;
+        try
+        {
+            pageManager.putPageText( page, newText );
+        }
+        catch ( ProviderException e )
+        {
+            throw new WikiSecurityException( "Could not set Acl. Reason: ProviderExcpetion " + e.getMessage() );
+        }
+    }
+
+    /**
+     * Generates an ACL string for inclusion in a wiki page, based on a supplied Acl object.
+     * All of the permissions in this Acl are assumed to apply to the same page scope.
+     * The names of the pages are ignored; only the actions and principals matter.
+     * @param acl the ACL
+     * @return the ACL string
+     */
+    protected static String printAcl( Acl acl )
+    {
+        // Extract the ACL entries into a Map with keys == permissions, values == principals
+        Map<String,List<Principal>> permissionPrincipals = new TreeMap<String,List<Principal>>();
+        Enumeration entries = acl.entries();
+        while ( entries.hasMoreElements() )
+        {
+            AclEntry entry = (AclEntry)entries.nextElement();
+            Principal principal = entry.getPrincipal();
+            Enumeration permissions = entry.permissions();
+            while ( permissions.hasMoreElements() )
+            {
+                Permission permission = (Permission)permissions.nextElement();
+                List<Principal> principals = permissionPrincipals.get( permission.getActions() );
+                if ( principals == null )
+                {
+                    principals = new ArrayList<Principal>();
+                    String action = permission.getActions();
+                    if ( action.indexOf(',') != -1 )
+                    {
+                        throw new IllegalStateException( "AclEntry permission cannot have multiple targets." );
+                    }
+                    permissionPrincipals.put( action, principals );
+                }
+                principals.add( principal );
+            }
+        }
+
+        // Now, iterate through each permission in the map and generate an ACL string
+
+        StringBuffer s = new StringBuffer();
+        for ( Map.Entry<String,List<Principal>> entry : permissionPrincipals.entrySet() )
+        {
+            String action = entry.getKey();
+            List<Principal> principals = entry.getValue();
+            Collections.sort( principals, new PrincipalComparator() );
+            s.append( "[{ALLOW ");
+            s.append( action );
+            s.append( " ");
+            for ( int i = 0; i < principals.size(); i++ )
+            {
+                Principal principal = principals.get( i );
+                s.append( principal.getName() );
+                if ( i < ( principals.size() - 1 ) )
+                {
+                    s.append(",");
+                }
+            }
+            s.append( "}]\n");
+        }
+        return s.toString();
+    }
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/UnresolvedPrincipal.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/UnresolvedPrincipal.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/UnresolvedPrincipal.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/acl/UnresolvedPrincipal.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,94 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2007 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.auth.acl;
+
+import java.security.Principal;
+
+/**
+ * Represents a Principal, typically read from an ACL, that cannot
+ * be resolved based on the current state of the user database, group
+ * manager, and built-in role definitions.
+ * Creating a principal marked "unresolved" allows
+ * delayed resolution, which enables principals to be resolved
+ * lazily during a later access control check. Conceptuallly,
+ * UnresolvedPrincipal performs a function similar to
+ * {@link java.security.UnresolvedPermission}.
+ * 
+ * @author Andrew Jaquith
+ * @since 2.3
+ */
+public final class UnresolvedPrincipal implements Principal
+{
+
+    private final String m_name;
+
+    /**
+     * Constructs a new UnresolvedPrincipal instance.
+     * @param name the name of the Principal
+     */
+    public UnresolvedPrincipal( String name )
+    {
+        m_name = name;
+    }
+
+    /**
+     * Returns the name of the principal.
+     * @return the name
+     * @see java.security.Principal#getName()
+     */
+    public final String getName()
+    {
+        return m_name;
+    }
+    
+    /**
+     * Returns a String representation of the UnresolvedPrincipal.
+     * @return the String
+     */
+    public final String toString()
+    {
+        return "[UnresolvedPrincipal: " + m_name + "]";
+    }
+
+    /**
+     * An unresolved principal is equal to another
+     * unresolved principal if their names match.
+     * @param obj the object to compare to this one
+     * @return the result of the equality test
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public final boolean equals( Object obj )
+    {
+        if ( obj instanceof UnresolvedPrincipal )
+        {
+            return m_name.equals( ( (UnresolvedPrincipal) obj ).m_name );
+        }
+        return false;
+    }
+
+    /**
+     *  The hashCode of this object is equal to the hash code of its name.
+     *  @return the hash code
+     */
+    public final int hashCode()
+    {
+        return m_name.hashCode();
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/authorize/Group.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/authorize/Group.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/authorize/Group.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/authorize/Group.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,358 @@
+/*
+ * JSPWiki - a JSP-based WikiWiki clone. Copyright (C) 2001-2003 Janne Jalkanen
+ * (Janne.Jalkanen@iki.fi) This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version. This program is distributed
+ * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details. You should have
+ * received a copy of the GNU Lesser General Public License along with this
+ * program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package com.ecyrd.jspwiki.auth.authorize;
+
+import java.security.Principal;
+import java.util.*;
+
+import com.ecyrd.jspwiki.auth.GroupPrincipal;
+
+/**
+ * <p>
+ * Groups are a specialized type of ad-hoc role used by the wiki system. Unlike
+ * externally-provided roles (such as those provided by an LDAP server or web
+ * container), JSPWiki groups can be created dynamically by wiki users, without
+ * requiring special container privileges or administrator intervention. They
+ * are designed to provide a lightweight role-based access control system that
+ * complements existing role systems.
+ * </p>
+ * <p>
+ * Group names are case-insensitive, and have a few naming restrictions, which
+ * are enforced by the {@link GroupManager}:
+ * </p>
+ * <ul>
+ * <li>Groups cannot have the same name as a built-in Role (e.g., "Admin",
+ * "Authenticated" etc.)</li>
+ * <li>Groups cannot have the same name as an existing user</li>
+ * </ul>
+ * <p>
+ * <em>Note: prior to JSPWiki 2.4.19, Group was an interface; it
+ * is now a concrete, final class.</em>
+ * </p>
+ * <p>
+ * Groups are related to {@link GroupPrincipal}s. A GroupPrincipal, when
+ * injected into the Principal set of a WikiSession's Subject, means that the
+ * user is a member of a Group of the same name -- it is, in essence, an
+ * "authorization token." GroupPrincipals, unlike Groups, are thread-safe,
+ * lightweight and immutable. That's why we use them in Subjects rather than the
+ * Groups themselves.
+ * </p>
+ * @author Janne Jalkanen
+ * @author Andrew Jaquith
+ * @since 2.3
+ */
+public class Group
+{
+
+    public static final String[]  RESTRICTED_GROUPNAMES = new String[]
+                                                  { "Anonymous", "All", "Asserted", "Authenticated" };
+
+    private final List<Principal> m_members = new ArrayList<Principal>();
+
+    private String          m_creator             = null;
+
+    private Date            m_created             = null;
+
+    private String          m_modifier            = null;
+
+    private Date            m_modified            = null;
+
+    private final String    m_name;
+
+    private final Principal m_principal;
+
+    private final String    m_wiki;
+
+    private final String    m_qualifiedName;
+
+    /**
+     * Protected constructor to prevent direct instantiation except by other
+     * package members. Callers should use
+     * {@link GroupManager#parseGroup(String, String, boolean)} or
+     * {@link GroupManager#parseGroup(com.ecyrd.jspwiki.WikiContext, boolean)}.
+     * instead.
+     * @param name the name of the group
+     * @param wiki the wiki the group belongs to
+     */
+    protected Group( String name, String wiki )
+    {
+        m_name = name;
+        m_wiki = wiki;
+        m_principal = new GroupPrincipal( name );
+        m_qualifiedName = wiki + ":" + name;
+    }
+
+    /**
+     * Adds a Principal to the group. 
+     * 
+     * @param user the principal to add
+     * @return <code>true</code> if the operation was successful
+     */
+    public synchronized boolean add( Principal user )
+    {
+        if ( isMember( user ) )
+        {
+            return false;
+        }
+
+        m_members.add( user );
+        return true;
+    }
+
+    /**
+     * Clears all Principals from the group list. 
+     */
+    public synchronized void clear()
+    {
+        m_members.clear();
+    }
+
+    /**
+     * Two DefaultGroups are equal if they contain identical member Principals
+     * and have the same name.
+     * @param o the object to compare
+     * @return the comparison
+     */
+    public boolean equals( Object o )
+    {
+        if ( o == null || !( o instanceof Group ) )
+            return false;
+
+        Group g = (Group) o; // Just a shortcut.
+
+        if ( g.m_members.size() != m_members.size() )
+            return false;
+
+        if ( getName() != null && !getName().equals( g.getName() ) )
+        {
+            return false;
+        }
+        else if ( getName() == null && g.getName() != null )
+        {
+            return false;
+        }
+
+        for( Iterator i = m_members.iterator(); i.hasNext(); )
+        {
+            if ( !( g.isMember( (Principal) i.next() ) ) )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     *  The hashcode is calculated as a XOR sum over all members of
+     *  the Group.
+     *  @return the hash code
+     */
+    public int hashCode()
+    {
+        int hc = 0;
+        for( Iterator i = m_members.iterator(); i.hasNext(); )
+        {
+            hc ^= i.next().hashCode();
+        }
+        return hc;
+    }
+    
+    /**
+     * Returns the creation date.
+     * @return the creation date
+     */
+    public synchronized Date getCreated()
+    {
+        return m_created;
+    }
+
+    /**
+     * Returns the creator of this Group.
+     * @return the creator
+     */
+    public final synchronized String getCreator()
+    {
+        return m_creator;
+    }
+
+    /**
+     * Returns the last-modified date.
+     * @return the date and time of last modification
+     */
+    public synchronized Date getLastModified()
+    {
+        return m_modified;
+    }
+
+    /**
+     * Returns the name of the user who last modified this group.
+     * @return the modifier
+     */
+    public final synchronized String getModifier()
+    {
+        return m_modifier;
+    }
+
+    /**
+     * The name of the group. This is set in the class constructor.
+     * @return the name of the Group
+     */
+    public String getName()
+    {
+        return m_name;
+    }
+    
+    /**
+     * The qualified name of the group, defined as the wiki plus the name,
+     * separated by a colon (<em>e.g.</em>, <code>MyWiki:MyGroup</code>).
+     * @return the qualified name of the Group
+     */
+    public String getQualifiedName()
+    {
+        return m_qualifiedName;
+    }
+
+    /**
+     * Returns the GroupPrincipal that represents this Group.
+     * @return the group principal
+     */
+    public Principal getPrincipal()
+    {
+        return m_principal;
+    }
+
+    /**
+     * Returns the wiki name.
+     * @return the wiki name
+     */
+    public String getWiki()
+    {
+        return m_wiki;
+    }
+
+    /**
+     * Returns <code>true</code> if a Principal is a member of the group.
+     * Specifically, the Principal's <code>getName()</code> method must return
+     * the same value as one of the Principals in the group member list. The
+     * Principal's type does <em>not</em> need to match.
+     * @param principal the principal about whom membeship status is sought
+     * @return the result of the operation
+     */
+    public boolean isMember( Principal principal )
+    {
+        return findMember( principal.getName() ) != null;
+    }
+
+    /**
+     * Returns the members of the group as an unmodifiable Set of Principal
+     * objects.
+     */
+    public List<Principal> getMembers()
+    {
+        return Collections.unmodifiableList(m_members);
+    }
+
+    /**
+     * Returns the members of the group as an array of Principal objects.
+     * @return the members
+     * @deprecated
+     */
+    public Principal[] members()
+    {
+        return m_members.toArray(new Principal[m_members.size()]);
+    }
+
+    /**
+     * Removes a Principal from the group. 
+     * 
+     * @param user the principal to remove
+     * @return <code>true</code> if the operation was successful
+     */
+    public synchronized boolean remove( Principal user )
+    {
+        user = findMember( user.getName() );
+
+        if ( user == null )
+            return false;
+
+        m_members.remove( user );
+        
+        return true;
+    }
+
+    /**
+     * Sets the created date.
+     * @param date the creation date
+     */
+    public synchronized void setCreated( Date date )
+    {
+        m_created = date;
+    }
+
+    /**
+     * Sets the creator of this Group.
+     * @param creator the creator
+     */
+    public final synchronized void setCreator( String creator )
+    {
+        this.m_creator = creator;
+    }
+
+    /**
+     * Sets the last-modified date
+     * @param date the last-modified date
+     */
+    public synchronized void setLastModified( Date date )
+    {
+        m_modified = date;
+    }
+
+    /**
+     * Sets the name of the user who last modified this group.
+     * @param modifier the modifier
+     */
+    public final synchronized void setModifier( String modifier )
+    {
+        this.m_modifier = modifier;
+    }
+
+    /**
+     * Returns a string representation of the Group.
+     * @return the string
+     * @see java.lang.Object#toString()
+     */
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+        sb.append( "(Group " + getName() + ")" );
+        return sb.toString();
+    }
+
+    private Principal findMember( String name )
+    {
+        for( Iterator i = m_members.iterator(); i.hasNext(); )
+        {
+            Principal member = (Principal) i.next();
+
+            if ( member.getName().equals( name ) )
+            {
+                return member;
+            }
+        }
+
+        return null;
+    }
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/authorize/GroupDatabase.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/authorize/GroupDatabase.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/authorize/GroupDatabase.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/authorize/GroupDatabase.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,90 @@
+/*
+ * JSPWiki - a JSP-based WikiWiki clone. Copyright (C) 2001-2003 Janne Jalkanen
+ * (Janne.Jalkanen@iki.fi) This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version. This program is distributed
+ * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details. You should have
+ * received a copy of the GNU Lesser General Public License along with this
+ * program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package com.ecyrd.jspwiki.auth.authorize;
+
+import java.security.Principal;
+import java.util.Properties;
+
+import com.ecyrd.jspwiki.NoRequiredPropertyException;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.auth.NoSuchPrincipalException;
+import com.ecyrd.jspwiki.auth.WikiSecurityException;
+
+/**
+ * Defines an interface for loading, persisting and storing wiki groups.
+ * @author Andrew Jaquith
+ * @since 2.4.22
+ */
+public interface GroupDatabase
+{
+    /**
+     * No-op method that in previous versions of JSPWiki was intended to 
+     * atomically commit changes to the user database. Now, the
+     * {@link #save(Group, Principal)} and {@link #delete(Group)} methods
+     * are atomic themselves.
+     * @throws WikiSecurityException never...
+     * @deprecated there is no need to call this method because the save and
+     * delete methods contain their own commit logic
+     */
+    public void commit() throws WikiSecurityException;
+
+    /**
+     * Looks up and deletes a {@link Group} from the group database. If the
+     * group database does not contain the supplied Group. this method throws a
+     * {@link NoSuchPrincipalException}. The method commits the results
+     * of the delete to persistent storage.
+     * @param group the group to remove
+     * @throws WikiSecurityException if the database does not contain the
+     * supplied group (thrown as {@link NoSuchPrincipalException}) or if
+     * the commit did not succeed
+     */
+    public void delete( Group group ) throws WikiSecurityException;
+
+    /**
+     * Initializes the group database based on values from a Properties object.
+     * @param engine the wiki engine
+     * @param props the properties used to initialize the group database
+     * @throws WikiSecurityException if the database could not be initialized successfully
+     * @throws NoRequiredPropertyException if a required property is not present
+     */
+    public void initialize( WikiEngine engine, Properties props ) throws NoRequiredPropertyException, WikiSecurityException;
+
+    /**
+     * Saves a Group to the group database. Note that this method <em>must</em>
+     * fail, and throw an <code>IllegalArgumentException</code>, if the
+     * proposed group is the same name as one of the built-in Roles: e.g.,
+     * Admin, Authenticated, etc. The database is responsible for setting
+     * create/modify timestamps, upon a successful save, to the Group.
+     * The method commits the results of the delete to persistent storage.
+     * @param group the Group to save
+     * @param modifier the user who saved the Group
+     * @throws WikiSecurityException if the Group could not be saved successfully
+     */
+    public void save( Group group, Principal modifier ) throws WikiSecurityException;
+
+    /**
+     * Returns all wiki groups that are stored in the GroupDatabase as an array
+     * of Group objects. If the database does not contain any groups, this
+     * method will return a zero-length array. This method causes back-end
+     * storage to load the entire set of group; thus, it should be called
+     * infrequently (e.g., at initialization time). Note that this method should
+     * use the protected constructor {@link Group#Group(String, String)} rather
+     * than the various "parse" methods ({@link GroupManager#parseGroup(String, String, boolean)})
+     * to construct the group. This is so as not to flood GroupManager's event
+     * queue with spurious events.
+     * @return the wiki groups
+     * @throws WikiSecurityException if the groups cannot be returned by the back-end
+     */
+    public Group[] groups() throws WikiSecurityException;
+}



Mime
View raw message