cn.vlabs.duckling.vwb.service.auth.permissions.PagePermission.java Source code

Java tutorial

Introduction

Here is the source code for cn.vlabs.duckling.vwb.service.auth.permissions.PagePermission.java

Source

/*
 * Copyright (c) 2008-2016 Computer Network Information Center (CNIC), Chinese Academy of Sciences.
 * 
 * This file is part of Duckling project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 *
 */

package cn.vlabs.duckling.vwb.service.auth.permissions;

import java.security.Permission;
import java.security.PermissionCollection;
import java.util.Arrays;

import org.apache.commons.lang.StringUtils;

/**
 * 
 * @date Feb 3, 2010
 * @author zzb
 */
public final class PagePermission extends Permission {
    private static final long serialVersionUID = 2L;

    public static final String COMMENT_ACTION = "comment";

    public static final String DELETE_ACTION = "delete";

    public static final String EDIT_ACTION = "edit";

    public static final String MODIFY_ACTION = "modify";

    public static final String RENAME_ACTION = "rename";

    public static final String VIEW_ACTION = "view";

    public static final String SHARE_ACTION = "share";

    protected static final int COMMENT_MASK = 0x4;

    protected static final int DELETE_MASK = 0x10;

    protected static final int EDIT_MASK = 0x2;

    protected static final int MODIFY_MASK = 0x40;

    protected static final int RENAME_MASK = 0x20;

    protected static final int SHARE_MASK = 0x8;

    protected static final int VIEW_MASK = 0x1;

    public static final PagePermission COMMENT = new PagePermission(COMMENT_ACTION);

    public static final PagePermission DELETE = new PagePermission(DELETE_ACTION);

    public static final PagePermission EDIT = new PagePermission(EDIT_ACTION);

    public static final PagePermission RENAME = new PagePermission(RENAME_ACTION);

    public static final PagePermission MODIFY = new PagePermission(MODIFY_ACTION);

    public static final PagePermission VIEW = new PagePermission(VIEW_ACTION);

    private static final String ACTION_SEPARATOR = ",";

    private static final String WILDCARD = "*";

    private static final String ATTACHMENT_SEPARATOR = "/";

    private final String m_actionString;

    private final int m_mask;

    private final String m_page;

    /**
     * Private convenience constructor that creates a new PagePermission for all wikis and pages
     * (*:*) and set of actions.
     * @param actions
     */
    private PagePermission(String actions) {
        this(WILDCARD, actions);
    }

    /**
     * Creates a new PagePermission for a specified page name and set of
     * actions. Page should include a prepended wiki name followed by a colon (:).
     * If the wiki name is not supplied or starts with a colon, the page
     * refers to no wiki in particular, and will never imply any other
     * PagePermission.
     * @param page the wiki page
     * @param actions the allowed actions for this page
     */
    public PagePermission(String page, String actions) {
        super(page);

        // Parse wiki and page (which may include wiki name and page)
        // Strip out attachment separator; it is irrelevant.

        int pos = page.indexOf(ATTACHMENT_SEPARATOR);
        m_page = (pos == -1) ? page : page.substring(0, pos);

        // Parse actions
        String[] pageActions = StringUtils.split(actions.toLowerCase(), ACTION_SEPARATOR);
        Arrays.sort(pageActions, String.CASE_INSENSITIVE_ORDER);
        m_mask = createMask(actions);
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < pageActions.length; i++) {
            buffer.append(pageActions[i]);
            if (i < (pageActions.length - 1)) {
                buffer.append(ACTION_SEPARATOR);
            }
        }
        m_actionString = buffer.toString();
    }

    /**
     * Creates a new PagePermission for a specified page and set of actions.
     * @param page The wikipage.
     * @param actions A set of actions; a comma-separated list of actions.
     */
    /*    public PagePermission( WikiPage page, String actions )
        {
    this( page.getWiki() + WIKI_SEPARATOR + page.getName(), actions );
        }*/

    /**
     * Two PagePermission objects are considered equal if their actions (after
     * normalization), wiki and target are equal.
     * @see java.lang.Object#equals(java.lang.Object)
     */
    public final boolean equals(Object obj) {
        if (!(obj instanceof PagePermission)) {
            return false;
        }
        PagePermission p = (PagePermission) obj;
        return p.m_mask == m_mask && p.m_page.equals(m_page);
    }

    /**
     * Returns the actions for this permission: "view", "edit", "comment",
     * "modify", "upload" or "delete". The actions will always be sorted in alphabetic
     * order, and will always appear in lower case.
     * @see java.security.Permission#getActions()
     */
    public final String getActions() {
        return m_actionString;
    }

    /**
     * Returns the name of the wiki page represented by this permission.
     * @return the page name
     */
    public final String getPage() {
        return m_page;
    }

    /**
     * Returns the hash code for this PagePermission.
     * @see java.lang.Object#hashCode()
     */
    public final int hashCode() {
        //  If the wiki has not been set, uses a dummy value for the hashcode
        //  calculation.  This may occur if the page given does not refer
        //  to any particular wiki
        String page = m_page != null ? m_page : "dummy_value";
        return m_mask + ((13 * m_actionString.hashCode()) * 23 * page.hashCode());
    }

    /**
     * <p>
     * PagePermission can only imply other PagePermissions; no other permission
     * types are implied. One PagePermission implies another if its actions if
     * three conditions are met:
     * </p>
     * <ol>
     * <li>The other PagePermission's wiki is equal to, or a subset of, that of
     * this permission. This permission's wiki is considered a superset of the
     * other if it contains a matching prefix plus a wildcard, or a wildcard
     * followed by a matching suffix.</li>
     * <li>The other PagePermission's target is equal to, or a subset of, the
     * target specified by this permission. This permission's target is
     * considered a superset of the other if it contains a matching prefix plus
     * a wildcard, or a wildcard followed by a matching suffix.</li>
     * <li>All of other PagePermission's actions are equal to, or a subset of,
     * those of this permission</li>
     * </ol>
     * @see java.security.Permission#implies(java.security.Permission)
     */
    public final boolean implies(Permission permission) {
        // Permission must be a PagePermission
        if (!(permission instanceof PagePermission)) {
            return false;
        }

        // Build up an "implied mask"
        PagePermission p = (PagePermission) permission;
        int impliedMask = impliedMask(m_mask);

        // If actions aren't a proper subset, return false
        if ((impliedMask & p.m_mask) != p.m_mask) {
            return false;
        }

        return isSubset(m_page, p.m_page);
    }

    /**
     * Returns a new {@link AllPermissionCollection}.
     * @see java.security.Permission#newPermissionCollection()
     */
    public PermissionCollection newPermissionCollection() {
        return new AllPermissionCollection();
    }

    /**
     * Prints a human-readable representation of this permission.
     * @see java.lang.Object#toString()
     */
    public final String toString() {
        return "(\"" + this.getClass().getName() + "\",\"" + m_page + "\",\"" + getActions() + "\")";
    }

    /**
     * Creates an "implied mask" based on the actions originally assigned: for
     * example, delete implies modify, comment, upload and view.
     * @param mask binary mask for actions
     * @return binary mask for implied actions
     */
    protected static final int impliedMask(int mask) {
        if ((mask & DELETE_MASK) > 0) {
            mask |= MODIFY_MASK;
        }
        if ((mask & RENAME_MASK) > 0) {
            mask |= EDIT_MASK;
        }
        if ((mask & MODIFY_MASK) > 0) {
            //Modified by morrise 20080402
            //mask |= EDIT_MASK | UPLOAD_MASK;
            mask |= EDIT_MASK;
        }
        if ((mask & EDIT_MASK) > 0) {
            mask |= COMMENT_MASK;
        }
        if ((mask & COMMENT_MASK) > 0) {
            mask |= VIEW_MASK;
        }
        //Modified by morrise 20080402
        //if ( ( mask & UPLOAD_MASK ) > 0 )
        //{
        //    mask |= VIEW_MASK;
        //}
        return mask;
    }

    /**
     * Determines whether one target string is a logical subset of the other.
     * @param superSet the prospective superset
     * @param subSet the prospective subset
     * @return the results of the test, where <code>true</code> indicates that
     *         <code>subSet</code> is a subset of <code>superSet</code>
     */
    protected static final boolean isSubset(String superSet, String subSet) {
        // If either is null, return false
        if (superSet == null || subSet == null) {
            return false;
        }

        // If targets are identical, it's a subset
        if (superSet.equals(subSet)) {
            return true;
        }

        // If super is "*", it's a subset
        if (superSet.equals(WILDCARD)) {
            return true;
        }

        // If super starts with "*", sub must end with everything after the *
        if (superSet.startsWith(WILDCARD)) {
            String suffix = superSet.substring(1);
            return subSet.endsWith(suffix);
        }

        // If super ends with "*", sub must start with everything before *
        if (superSet.endsWith(WILDCARD)) {
            String prefix = superSet.substring(0, superSet.length() - 1);
            return subSet.startsWith(prefix);
        }

        return false;
    }

    /**
     * Private method that creates a binary mask based on the actions specified.
     * This is used by {@link #implies(Permission)}.
     * @param actions the actions for this permission, separated by commas
     * @return the binary actions mask
     */
    protected static final int createMask(String actions) {
        if (actions == null || actions.length() == 0) {
            throw new IllegalArgumentException("Actions cannot be blank or null");
        }
        int mask = 0;
        String[] actionList = StringUtils.split(actions, ACTION_SEPARATOR);
        for (int i = 0; i < actionList.length; i++) {
            String action = actionList[i];
            if (action.equalsIgnoreCase(VIEW_ACTION)) {
                mask |= VIEW_MASK;
            } else if (action.equalsIgnoreCase(EDIT_ACTION)) {
                mask |= EDIT_MASK;
            } else if (action.equalsIgnoreCase(COMMENT_ACTION)) {
                mask |= COMMENT_MASK;
            } else if (action.equalsIgnoreCase(MODIFY_ACTION)) {
                mask |= MODIFY_MASK;
            }
            //Modified by morrise 20080402
            //else if ( action.equalsIgnoreCase( UPLOAD_ACTION ) )
            //{
            //    mask |= UPLOAD_MASK;
            //}
            else if (action.equalsIgnoreCase(DELETE_ACTION)) {
                mask |= DELETE_MASK;
            } else if (action.equalsIgnoreCase(RENAME_ACTION)) {
                mask |= RENAME_MASK;
            } else if (action.equalsIgnoreCase(SHARE_ACTION)) //added by morrise
            {
                mask |= SHARE_MASK;
            } else {
                throw new IllegalArgumentException("Unrecognized action: " + action);
            }
        }
        return mask;
    }
}