/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2000-2009 Sun Microsystems, Inc. All rights reserved. 
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License ("CDDL") (collectively, the "License").  You may
 * not use this file except in compliance with the License.  You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or mq/legal/LICENSE.txt.  See the License for the specific language
 * governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at mq/legal/LICENSE.txt.  Sun designates
 * this particular file as subject to the "Classpath" exception as provided by
 * Sun in the GPL Version 2 section of the License file that accompanied this
 * code.  If applicable, add the following below the License Header, with the
 * fields enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or  to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright holder. 
 */

/*
 * @(#)MQBasicPermission.java	1.5 06/27/07
 */ 

package com.sun.messaging.jmq.auth.jaas;

import java.util.Map;
import java.util.HashMap;
import java.util.Enumeration;
import java.util.Collections;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.security.Permission;
import java.security.PermissionCollection;

/**
 * A base permission class for MQ connection and destination
 * auto-creation permissionS
 */

public abstract class MQBasicPermission extends Permission 
                           implements java.io.Serializable
{ 

    private static final long serialVersionUID = 7965671047666454007L;

    private transient boolean wildcard;

    /**
     *
     */
    public MQBasicPermission(String name) {
        super(name);
        init(name);
    }

    /**
     *
     */
    private void init(String name) {
        if (name == null) throw new NullPointerException("name null");

        int len = name.length();
        if (len == 0) throw new IllegalArgumentException("name empty");

        if (len == 1 && name.equals("*")) {
            wildcard = true;
        } else {
            validateName(name);
        }
    }

    public abstract void validateName(String name) throws IllegalArgumentException; 

    /**
     * 
     */
    public boolean implies(Permission p) {
	    if (!(p instanceof MQBasicPermission)) return false;
        if (p.getClass() != getClass()) return false;

        MQBasicPermission that = (MQBasicPermission)p;

        if (this.wildcard) return true;
        if (that.wildcard) return false;

	    return this.getName().equals(that.getName());
    }

    /**
     *
     */
    public boolean equals(Object obj) {
	    if (obj == this) return true;

        if (!(obj instanceof MQBasicPermission)) return false;

        if (obj.getClass() != getClass()) return false;

        MQBasicPermission p = (MQBasicPermission)obj;

        return getName().equals(p.getName());
    }

    /**
     *
     */
    public int hashCode() {
        return this.getName().hashCode();
    }

    /**
     *
     */
    public String getActions() {
        return "";
    }

    /**
     *
     */
    public PermissionCollection newPermissionCollection() {
	    return new MQBasicPermissionCollection();
    }

    /**
     *
     */
    private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        init(getName());
    }

}


/**
 *
 */
final class MQBasicPermissionCollection extends PermissionCollection
                                     implements java.io.Serializable
{

    private static final long serialVersionUID = 8958682081876542895L;

    private Map perms = null;
    private Class permClass = null;

    private boolean allowAll = false; 

    /**
     *
     */
    public MQBasicPermissionCollection() {
        perms = new HashMap(11);
        allowAll = false;
    }

    /**
     *
     */
    public void add(Permission p) {

        if (! (p instanceof MQBasicPermission)) {
            throw new IllegalArgumentException("invalid permission: "+p);
        }

        if (isReadOnly()) {
	        throw new SecurityException("Attempt to add to a read only permission "+p);
        }

        MQBasicPermission pm = (MQBasicPermission)p;

        synchronized (this) {
            if (perms.size() == 0) {
                permClass = pm.getClass();
            } else if (pm.getClass() != permClass) {
                throw new IllegalArgumentException("invalid permission: " +p);
            }
            perms.put(pm.getName(), pm);
        }

        if (!allowAll) {
            if (pm.getName().equals("*")) allowAll = true;
        }
    }

    /**
     *
     */
    public boolean implies(Permission p) {
        if (! (p instanceof MQBasicPermission)) return false;

        MQBasicPermission pm = (MQBasicPermission)p;

        if (pm.getClass() != permClass) return false;

        if (allowAll) return true;


        Permission x;
        synchronized (this) {
            x = (Permission) perms.get(p.getName());
        }
        if (x != null) return x.implies(p);

        return false;
	}

    /**
     *
     */
    public Enumeration elements() {
        synchronized (this) {
	        return Collections.enumeration(perms.values());
        }
    }

}
