001/* 
002    Licensed to the Apache Software Foundation (ASF) under one
003    or more contributor license agreements.  See the NOTICE file
004    distributed with this work for additional information
005    regarding copyright ownership.  The ASF licenses this file
006    to you under the Apache License, Version 2.0 (the
007    "License"); you may not use this file except in compliance
008    with the License.  You may obtain a copy of the License at
009
010       http://www.apache.org/licenses/LICENSE-2.0
011
012    Unless required by applicable law or agreed to in writing,
013    software distributed under the License is distributed on an
014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015    KIND, either express or implied.  See the License for the
016    specific language governing permissions and limitations
017    under the License.  
018 */
019package org.apache.wiki.auth.acl;
020
021import java.io.Serializable;
022import java.security.Permission;
023import java.security.Principal;
024import java.util.Enumeration;
025import java.util.Vector;
026
027import org.apache.wiki.auth.permissions.PagePermission;
028
029/**
030 * Implementation of a JSPWiki AclEntry.
031 *
032 * @since 2.3
033 */
034public class AclEntryImpl implements AclEntry, Serializable
035{
036    private static final long serialVersionUID = 1L;
037    private Vector<Permission>    m_permissions = new Vector<Permission>();
038    private Principal m_principal;
039
040    /**
041     * Constructs a new AclEntryImpl instance.
042     */
043    public AclEntryImpl()
044    {
045    }
046
047    /**
048     * Adds the specified permission to this ACL entry. The permission
049     * <em>must</em> be of type
050     * {@link org.apache.wiki.auth.permissions.PagePermission}. Note: An entry
051     * can have multiple permissions.
052     * @param permission the permission to be associated with the principal in
053     *            this entry
054     * @return <code>true</code> if the permission was added, 
055     *         <code>false</code> if the permission was
056     *         already part of this entry's permission set, and <code>false</code> if
057     *         the permission is not of type PagePermission
058     */
059    public synchronized boolean addPermission( Permission permission )
060    {
061        if ( permission instanceof PagePermission && findPermission( permission ) == null )
062        {
063            m_permissions.add( permission );
064            return true;
065        }
066
067        return false;
068    }
069
070    /**
071     * Checks if the specified permission is part of the permission set in this
072     * entry.
073     * @param permission the permission to be checked for.
074     * @return true if the permission is part of the permission set in this entry,
075     *         false otherwise.
076     */
077    public boolean checkPermission( Permission permission )
078    {
079        return findPermission( permission ) != null;
080    }
081
082    /**
083     * Returns the principal for which permissions are granted by this
084     * ACL entry. Returns null if there is no principal set for this entry yet.
085     * @return the principal associated with this entry.
086     */
087    public synchronized Principal getPrincipal()
088    {
089        return m_principal;
090    }
091
092    /**
093     * Returns an enumeration of the permissions in this ACL entry.
094     * @return an enumeration of the permissions
095     */
096    public Enumeration< Permission > permissions()
097    {
098        return m_permissions.elements();
099    }
100
101    /**
102     * Removes the specified permission from this ACL entry.
103     * @param permission the permission to be removed from this entry.
104     * @return true if the permission is removed, false if the permission was not
105     *         part of this entry's permission set.
106     */
107    public synchronized boolean removePermission( Permission permission )
108    {
109        Permission p = findPermission( permission );
110
111        if ( p != null )
112        {
113            m_permissions.remove( p );
114            return true;
115        }
116
117        return false;
118    }
119
120    /**
121     * Specifies the principal for which permissions are granted or denied by
122     * this ACL entry. If a principal was already set for this ACL entry, false
123     * is returned, otherwise true is returned.
124     * @param user the principal to be set for this entry
125     * @return true if the principal is set, false if there was already a
126     *         principal set for this entry
127     */
128    public synchronized boolean setPrincipal( Principal user )
129    {
130        if ( m_principal != null || user == null )
131            return false;
132
133        m_principal = user;
134
135        return true;
136    }
137
138    /**
139     * Returns a string representation of the contents of this ACL entry.
140     * @return a string representation of the contents.
141     */
142    public String toString()
143    {
144        StringBuilder sb = new StringBuilder();
145
146        Principal p = getPrincipal();
147
148        sb.append( "[AclEntry ALLOW " + ( p != null ? p.getName() : "null" ) );
149        sb.append( " " );
150
151        for( Permission pp : m_permissions )
152        {
153            sb.append( pp.toString() );
154            sb.append( "," );
155        }
156
157        sb.append( "]" );
158
159        return sb.toString();
160    }
161
162    /**
163     * Looks through the permission list and finds a permission that matches the
164     * permission.
165     */
166    private Permission findPermission( Permission p )
167    {
168        for( Permission pp : m_permissions )
169        {
170            if ( pp.implies( p ) )
171            {
172                return pp;
173            }
174        }
175
176        return null;
177    }
178}
179