    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 org.apache.wiki.auth.permissions.PagePermission;
    022
    023import java.io.Serializable;
    024import java.security.Permission;
    025import java.security.Principal;
    026import java.util.Enumeration;
    027import java.util.Vector;
    028import java.util.stream.Collectors;
    029
    030
    031/**
    032 * Implementation of a JSPWiki AclEntry.
    033 *
    034 * @since 2.3
    035 */
    036public class AclEntryImpl implements AclEntry, Serializable {
    037
    038    private static final long serialVersionUID = 1L;
    039    private final Vector< Permission > m_permissions = new Vector<>();
    040    private Principal m_principal;
    041
    042    /**
    043     * Constructs a new AclEntryImpl instance.
    044     */
    045    public AclEntryImpl() {
    046    }
    047
    048    /**
    049     * Adds the specified permission to this ACL entry. The permission <em>must</em> be of type
    050     * {@link org.apache.wiki.auth.permissions.PagePermission}. Note: An entry can have multiple permissions.
    051     *
    052     * @param permission the permission to be associated with the principal in this entry
    053     * @return <code>true</code> if the permission was added, <code>false</code> if the permission was
    054     * already part of this entry's permission set, and <code>false</code> if the permission is not of type PagePermission
    055     */
    056    @Override
    057    public synchronized boolean addPermission(final Permission permission ) {
    058        if( permission instanceof PagePermission && findPermission( permission ) == null ) {
    059            m_permissions.add( permission );
    060            return true;
    061        }
    062
    063        return false;
    064    }
    065
    066    /**
    067     * Checks if the specified permission is part of the permission set in this entry.
    068     *
    069     * @param permission the permission to be checked for.
    070     * @return true if the permission is part of the permission set in this entry, false otherwise.
    071     */
    072    @Override
    073    public boolean checkPermission(final Permission permission ) {
    074        return findPermission( permission ) != null;
    075    }
    076
    077    /**
    078     * Returns the principal for which permissions are granted by this ACL entry. Returns null if there is no principal set for this
    079     * entry yet.
    080     *
    081     * @return the principal associated with this entry.
    082     */
    083    @Override
    084    public synchronized Principal getPrincipal() {
    085        return m_principal;
    086    }
    087
    088    /**
    089     * Returns an enumeration of the permissions in this ACL entry.
    090     *
    091     * @return an enumeration of the permissions
    092     */
    093    @Override
    094    public Enumeration< Permission > permissions() {
    095        return m_permissions.elements();
    096    }
    097
    098    /**
    099     * Removes the specified permission from this ACL entry.
    100     *
    101     * @param permission the permission to be removed from this entry.
    102     * @return true if the permission is removed, false if the permission was not part of this entry's permission set.
    103     */
    104    @Override
    105    public synchronized boolean removePermission(final Permission permission ) {
    106        final Permission p = findPermission( permission );
    107        if( p != null ) {
    108            m_permissions.remove( p );
    109            return true;
    110        }
    111
    112        return false;
    113    }
    114
    115    /**
    116     * Specifies the principal for which permissions are granted or denied by this ACL entry. If a principal was already set for this ACL
    117     * entry, false is returned, otherwise true is returned.
    118     *
    119     * @param user the principal to be set for this entry
    120     * @return true if the principal is set, false if there was already a
    121     * principal set for this entry
    122     */
    123    @Override
    124    public synchronized boolean setPrincipal(final Principal user ) {
    125        if( m_principal != null || user == null ) {
    126            return false;
    127        }
    128        m_principal = user;
    129        return true;
    130    }
    131
    132    /**
    133     * Returns a string representation of the contents of this ACL entry.
    134     *
    135     * @return a string representation of the contents.
    136     */
    137    public String toString() {
    138        final Principal p = getPrincipal();
    139
    140        return m_permissions.stream().map(pp -> pp.toString() + ",").collect(Collectors.joining("", "[AclEntry ALLOW " + (p != null ? p.getName() : "null") + " ", "]"));
    141    }
    142
    143    /**
    144     * Looks through the permission list and finds a permission that matches the
    145     * permission.
    146     */
    147    private Permission findPermission( final Permission p ) {
    148        return m_permissions.stream().filter(pp -> pp.implies(p)).findFirst().orElse(null);
    149    }
    150
    151}
    152