/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 org.apache.harmony.javax.security.auth;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.DomainCombiner;
import java.security.Permission;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;



/**
 * The central class of the {@code javax.security.auth} package representing an
 * authenticated user or entity (both referred to as "subject"). IT defines also
 * the static methods that allow code to be run, and do modifications according
 * to the subject's permissions.
 * <p>
 * A subject has the following features:
 * <ul>
 * <li>A set of {@code Principal} objects specifying the identities bound to a
 * {@code Subject} that distinguish it.</li>
 * <li>Credentials (public and private) such as certificates, keys, or
 * authentication proofs such as tickets</li>
 * </ul>
 */
public final class Subject implements Serializable {

    private static final long serialVersionUID = -8308522755600156056L;
    
    private static final AuthPermission _AS = new AuthPermission("doAs"); //$NON-NLS-1$

    private static final AuthPermission _AS_PRIVILEGED = new AuthPermission(
            "doAsPrivileged"); //$NON-NLS-1$

    private static final AuthPermission _SUBJECT = new AuthPermission(
            "getSubject"); //$NON-NLS-1$

    private static final AuthPermission _PRINCIPALS = new AuthPermission(
            "modifyPrincipals"); //$NON-NLS-1$

    private static final AuthPermission _PRIVATE_CREDENTIALS = new AuthPermission(
            "modifyPrivateCredentials"); //$NON-NLS-1$

    private static final AuthPermission _PUBLIC_CREDENTIALS = new AuthPermission(
            "modifyPublicCredentials"); //$NON-NLS-1$

    private static final AuthPermission _READ_ONLY = new AuthPermission(
            "setReadOnly"); //$NON-NLS-1$

    private final Set<Principal> principals;

    private boolean readOnly;
    
    // set of private credentials
    private transient SecureSet<Object> privateCredentials;

    // set of public credentials
    private transient SecureSet<Object> publicCredentials;
    
    /**
     * The default constructor initializing the sets of public and private
     * credentials and principals with the empty set.
     */
    public Subject() {
        super();
        principals = new SecureSet<Principal>(_PRINCIPALS);
        publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS);
        privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS);

        readOnly = false;
    }

    /**
     * The constructor for the subject, setting its public and private
     * credentials and principals according to the arguments.
     *
     * @param readOnly
     *            {@code true} if this {@code Subject} is read-only, thus
     *            preventing any modifications to be done.
     * @param subjPrincipals
     *            the set of Principals that are attributed to this {@code
     *            Subject}.
     * @param pubCredentials
     *            the set of public credentials that distinguish this {@code
     *            Subject}.
     * @param privCredentials
     *            the set of private credentials that distinguish this {@code
     *            Subject}.
     */
    public Subject(boolean readOnly, Set<? extends Principal> subjPrincipals,
            Set<?> pubCredentials, Set<?> privCredentials) {

        if (subjPrincipals == null || pubCredentials == null || privCredentials == null) {
            throw new NullPointerException();
        }

        principals = new SecureSet<Principal>(_PRINCIPALS, subjPrincipals);
        publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS, pubCredentials);
        privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS, privCredentials);

        this.readOnly = readOnly;
    }

    /**
     * Runs the code defined by {@code action} using the permissions granted to
     * the {@code Subject} itself and to the code as well.
     *
     * @param subject
     *            the distinguished {@code Subject}.
     * @param action
     *            the code to be run.
     * @return the {@code Object} returned when running the {@code action}.
     */
    @SuppressWarnings("unchecked")
    public static Object doAs(Subject subject, PrivilegedAction action) {

        checkPermission(_AS);

        return doAs_PrivilegedAction(subject, action, AccessController.getContext());
    }

    /**
     * Run the code defined by {@code action} using the permissions granted to
     * the {@code Subject} and to the code itself, additionally providing a more
     * specific context.
     *
     * @param subject
     *            the distinguished {@code Subject}.
     * @param action
     *            the code to be run.
     * @param context
     *            the specific context in which the {@code action} is invoked.
     *            if {@code null} a new {@link AccessControlContext} is
     *            instantiated.
     * @return the {@code Object} returned when running the {@code action}.
     */
    @SuppressWarnings("unchecked")
    public static Object doAsPrivileged(Subject subject, PrivilegedAction action,
            AccessControlContext context) {

        checkPermission(_AS_PRIVILEGED);

        if (context == null) {
            return doAs_PrivilegedAction(subject, action, new AccessControlContext(
                    new ProtectionDomain[0]));
        }
        return doAs_PrivilegedAction(subject, action, context);
    }

    // instantiates a new context and passes it to AccessController
    @SuppressWarnings("unchecked")
    private static Object doAs_PrivilegedAction(Subject subject, PrivilegedAction action,
            final AccessControlContext context) {

        AccessControlContext newContext;

        final SubjectDomainCombiner combiner;
        if (subject == null) {
            // performance optimization
            // if subject is null there is nothing to combine
            combiner = null;
        } else {
            combiner = new SubjectDomainCombiner(subject);
        }

        PrivilegedAction dccAction = new PrivilegedAction() {
            public Object run() {

                return new AccessControlContext(context, combiner);
            }
        };

        newContext = (AccessControlContext) AccessController.doPrivileged(dccAction);

        return AccessController.doPrivileged(action, newContext);
    }

    /**
     * Runs the code defined by {@code action} using the permissions granted to
     * the subject and to the code itself.
     *
     * @param subject
     *            the distinguished {@code Subject}.
     * @param action
     *            the code to be run.
     * @return the {@code Object} returned when running the {@code action}.
     * @throws PrivilegedActionException
     *             if running the {@code action} throws an exception.
     */
    @SuppressWarnings("unchecked")
    public static Object doAs(Subject subject, PrivilegedExceptionAction action)
            throws PrivilegedActionException {

        checkPermission(_AS);

        return doAs_PrivilegedExceptionAction(subject, action, AccessController.getContext());
    }

    /**
     * Runs the code defined by {@code action} using the permissions granted to
     * the subject and to the code itself, additionally providing a more
     * specific context.
     *
     * @param subject
     *            the distinguished {@code Subject}.
     * @param action
     *            the code to be run.
     * @param context
     *            the specific context in which the {@code action} is invoked.
     *            if {@code null} a new {@link AccessControlContext} is
     *            instantiated.
     * @return the {@code Object} returned when running the {@code action}.
     * @throws PrivilegedActionException
     *             if running the {@code action} throws an exception.
     */
    @SuppressWarnings("unchecked")
    public static Object doAsPrivileged(Subject subject,
            PrivilegedExceptionAction action, AccessControlContext context)
            throws PrivilegedActionException {

        checkPermission(_AS_PRIVILEGED);

        if (context == null) {
            return doAs_PrivilegedExceptionAction(subject, action,
                    new AccessControlContext(new ProtectionDomain[0]));
        }
        return doAs_PrivilegedExceptionAction(subject, action, context);
    }

    // instantiates a new context and passes it to AccessController
    @SuppressWarnings("unchecked")
    private static Object doAs_PrivilegedExceptionAction(Subject subject,
            PrivilegedExceptionAction action, final AccessControlContext context)
            throws PrivilegedActionException {

        AccessControlContext newContext;

        final SubjectDomainCombiner combiner;
        if (subject == null) {
            // performance optimization
            // if subject is null there is nothing to combine
            combiner = null;
        } else {
            combiner = new SubjectDomainCombiner(subject);
        }

        PrivilegedAction<AccessControlContext> dccAction = new PrivilegedAction<AccessControlContext>() {
            public AccessControlContext run() {
                return new AccessControlContext(context, combiner);
            }
        };

        newContext = AccessController.doPrivileged(dccAction);

        return AccessController.doPrivileged(action, newContext);
    }

    /**
     * Checks two Subjects for equality. More specifically if the principals,
     * public and private credentials are equal, equality for two {@code
     * Subjects} is implied.
     *
     * @param obj
     *            the {@code Object} checked for equality with this {@code
     *            Subject}.
     * @return {@code true} if the specified {@code Subject} is equal to this
     *         one.
     */
    @Override
    public boolean equals(Object obj) {

        if (this == obj) {
            return true;
        }

        if (obj == null || this.getClass() != obj.getClass()) {
            return false;
        }

        Subject that = (Subject) obj;

        if (principals.equals(that.principals)
                && publicCredentials.equals(that.publicCredentials)
                && privateCredentials.equals(that.privateCredentials)) {
            return true;
        }
        return false;
    }

    /**
     * Returns this {@code Subject}'s {@link Principal}.
     *
     * @return this {@code Subject}'s {@link Principal}.
     */
    public Set<Principal> getPrincipals() {
        return principals;
    }


    /**
     * Returns this {@code Subject}'s {@link Principal} which is a subclass of
     * the {@code Class} provided.
     *
     * @param c
     *            the {@code Class} as a criteria which the {@code Principal}
     *            returned must satisfy.
     * @return this {@code Subject}'s {@link Principal}. Modifications to the
     *         returned set of {@code Principal}s do not affect this {@code
     *         Subject}'s set.
     */
    public <T extends Principal> Set<T> getPrincipals(Class<T> c) {
        return ((SecureSet<Principal>) principals).get(c);
    }

    /**
     * Returns the private credentials associated with this {@code Subject}.
     *
     * @return the private credentials associated with this {@code Subject}.
     */
    public Set<Object> getPrivateCredentials() {
        return privateCredentials;
    }

    /**
     * Returns this {@code Subject}'s private credentials which are a subclass
     * of the {@code Class} provided.
     *
     * @param c
     *            the {@code Class} as a criteria which the private credentials
     *            returned must satisfy.
     * @return this {@code Subject}'s private credentials. Modifications to the
     *         returned set of credentials do not affect this {@code Subject}'s
     *         credentials.
     */
    public <T> Set<T> getPrivateCredentials(Class<T> c) {
        return privateCredentials.get(c);
    }

    /**
     * Returns the public credentials associated with this {@code Subject}.
     *
     * @return the public credentials associated with this {@code Subject}.
     */
    public Set<Object> getPublicCredentials() {
        return publicCredentials;
    }


    /**
     * Returns this {@code Subject}'s public credentials which are a subclass of
     * the {@code Class} provided.
     *
     * @param c
     *            the {@code Class} as a criteria which the public credentials
     *            returned must satisfy.
     * @return this {@code Subject}'s public credentials. Modifications to the
     *         returned set of credentials do not affect this {@code Subject}'s
     *         credentials.
     */
    public <T> Set<T> getPublicCredentials(Class<T> c) {
        return publicCredentials.get(c);
    }

    /**
     * Returns a hash code of this {@code Subject}.
     *
     * @return a hash code of this {@code Subject}.
     */
    @Override
    public int hashCode() {
        return principals.hashCode() + privateCredentials.hashCode()
                + publicCredentials.hashCode();
    }

    /**
     * Prevents from modifications being done to the credentials and {@link
     * Principal} sets. After setting it to read-only this {@code Subject} can
     * not be made writable again. The destroy method on the credentials still
     * works though.
     */
    public void setReadOnly() {
        checkPermission(_READ_ONLY);

        readOnly = true;
    }

    /**
     * Returns whether this {@code Subject} is read-only or not.
     *
     * @return whether this {@code Subject} is read-only or not.
     */
    public boolean isReadOnly() {
        return readOnly;
    }

    /**
     * Returns a {@code String} representation of this {@code Subject}.
     *
     * @return a {@code String} representation of this {@code Subject}.
     */
    @Override
    public String toString() {

        StringBuilder buf = new StringBuilder("Subject:\n"); //$NON-NLS-1$

        Iterator<?> it = principals.iterator();
        while (it.hasNext()) {
            buf.append("\tPrincipal: "); //$NON-NLS-1$
            buf.append(it.next());
            buf.append('\n');
        }

        it = publicCredentials.iterator();
        while (it.hasNext()) {
            buf.append("\tPublic Credential: "); //$NON-NLS-1$
            buf.append(it.next());
            buf.append('\n');
        }

        int offset = buf.length() - 1;
        it = privateCredentials.iterator();
        try {
            while (it.hasNext()) {
                buf.append("\tPrivate Credential: "); //$NON-NLS-1$
                buf.append(it.next());
                buf.append('\n');
            }
        } catch (SecurityException e) {
            buf.delete(offset, buf.length());
            buf.append("\tPrivate Credentials: no accessible information\n"); //$NON-NLS-1$
        }
        return buf.toString();
    }

    private void readObject(ObjectInputStream in) throws IOException,
            ClassNotFoundException {

        in.defaultReadObject();

        publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS);
        privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS);
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
    }

    /**
     * Returns the {@code Subject} that was last associated with the {@code
     * context} provided as argument.
     *
     * @param context
     *            the {@code context} that was associated with the
     *            {@code Subject}.
     * @return the {@code Subject} that was last associated with the {@code
     *         context} provided as argument.
     */
    public static Subject getSubject(final AccessControlContext context) {
        checkPermission(_SUBJECT);
        if (context == null) {
            throw new NullPointerException("auth.09"); //$NON-NLS-1$
        }
        PrivilegedAction<DomainCombiner> action = new PrivilegedAction<DomainCombiner>() {
            public DomainCombiner run() {
                return context.getDomainCombiner();
            }
        };
        DomainCombiner combiner = AccessController.doPrivileged(action);

        if ((combiner == null) || !(combiner instanceof SubjectDomainCombiner)) {
            return null;
        }
        return ((SubjectDomainCombiner) combiner).getSubject();
    }

    // checks passed permission
    private static void checkPermission(Permission p) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(p);
        }
    }

    // FIXME is used only in two places. remove?
    private void checkState() {
        if (readOnly) {
            throw new IllegalStateException("auth.0A"); //$NON-NLS-1$
        }
    }

    private final class SecureSet<SST> extends AbstractSet<SST> implements Serializable {

        /**
         * Compatibility issue: see comments for setType variable
         */
        private static final long serialVersionUID = 7911754171111800359L;

        private LinkedList<SST> elements;

        /*
         * Is used to define a set type for serialization.
         * 
         * A type can be principal, priv. or pub. credential set. The spec.
         * doesn't clearly says that priv. and pub. credential sets can be
         * serialized and what classes they are. It is only possible to figure
         * out from writeObject method comments that priv. credential set is
         * serializable and it is an instance of SecureSet class. So pub.
         * credential was implemented by analogy
         * 
         * Compatibility issue: the class follows its specified serial form.
         * Also according to the serialization spec. adding new field is a
         * compatible change. So is ok for principal set (because the default
         * value for integer is zero). But priv. or pub. credential set it is
         * not compatible because most probably other implementations resolve
         * this issue in other way
         */
        private int setType;

        // Defines principal set for serialization.
        private static final int SET_Principal = 0;

        // Defines private credential set for serialization.
        private static final int SET_PrivCred = 1;

        // Defines public credential set for serialization.
        private static final int SET_PubCred = 2;

        // permission required to modify set
        private transient AuthPermission permission;

        protected SecureSet(AuthPermission perm) {
            permission = perm;
            elements = new LinkedList<SST>();
        }

        // creates set from specified collection with specified permission
        // all collection elements are verified before adding
        protected SecureSet(AuthPermission perm, Collection<? extends SST> s) {
            this(perm);

            // Subject's constructor receives a Set, we can trusts if a set is from bootclasspath,
            // and not to check whether it contains duplicates or not
            boolean trust = s.getClass().getClassLoader() == null; 
            
            Iterator<? extends SST> it = s.iterator();
            while (it.hasNext()) {
                SST o = it.next();
                verifyElement(o);
                if (trust || !elements.contains(o)) {
                    elements.add(o);
                }
            }
        }

        // verifies new set element
        private void verifyElement(Object o) {

            if (o == null) {
                throw new NullPointerException();
            }
            if (permission == _PRINCIPALS && !(Principal.class.isAssignableFrom(o.getClass()))) {
                throw new IllegalArgumentException("auth.0B"); //$NON-NLS-1$
            }
        }

        /*
         * verifies specified element, checks set state, and security permission
         * to modify set before adding new element
         */
        @Override
        public boolean add(SST o) {

            verifyElement(o);

            checkState();
            checkPermission(permission);

            if (!elements.contains(o)) {
                elements.add(o);
                return true;
            }
            return false;
        }

        // returns an instance of SecureIterator
        @Override
        public Iterator<SST> iterator() {

            if (permission == _PRIVATE_CREDENTIALS) {
                /*
                 * private credential set requires iterator with additional
                 * security check (PrivateCredentialPermission)
                 */
                return new SecureIterator(elements.iterator()) {
                    /*
                     * checks permission to access next private credential moves
                     * to the next element even SecurityException was thrown
                     */
                    @Override
                    public SST next() {
                        SST obj = iterator.next();
                        checkPermission(new PrivateCredentialPermission(obj
                                .getClass().getName(), principals));
                        return obj;
                    }
                };
            }
            return new SecureIterator(elements.iterator());
        }

        @Override
        public boolean retainAll(Collection<?> c) {

            if (c == null) {
                throw new NullPointerException();
            }
            return super.retainAll(c);
        }

        @Override
        public int size() {
            return elements.size();
        }

        /**
         * return set with elements that are instances or subclasses of the
         * specified class
         */
        protected final <E> Set<E> get(final Class<E> c) {

            if (c == null) {
                throw new NullPointerException();
            }

            AbstractSet<E> s = new AbstractSet<E>() {
                private LinkedList<E> elements = new LinkedList<E>();

                @Override
                public boolean add(E o) {

                    if (!c.isAssignableFrom(o.getClass())) {
                        throw new IllegalArgumentException(
                                "auth.0C " + c.getName()); //$NON-NLS-1$
                    }

                    if (elements.contains(o)) {
                        return false;
                    }
                    elements.add(o);
                    return true;
                }

                @Override
                public Iterator<E> iterator() {
                    return elements.iterator();
                }

                @Override
                public boolean retainAll(Collection<?> c) {

                    if (c == null) {
                        throw new NullPointerException();
                    }
                    return super.retainAll(c);
                }

                @Override
                public int size() {
                    return elements.size();
                }
            };

            // FIXME must have permissions for requested priv. credentials
            for (Iterator<SST> it = iterator(); it.hasNext();) {
                SST o = it.next();
                if (c.isAssignableFrom(o.getClass())) {
                    s.add(c.cast(o));
                }
            }
            return s;
        }

        private void readObject(ObjectInputStream in) throws IOException,
                ClassNotFoundException {
            in.defaultReadObject();

            switch (setType) {
            case SET_Principal:
                permission = _PRINCIPALS;
                break;
            case SET_PrivCred:
                permission = _PRIVATE_CREDENTIALS;
                break;
            case SET_PubCred:
                permission = _PUBLIC_CREDENTIALS;
                break;
            default:
                throw new IllegalArgumentException();
            }

            Iterator<SST> it = elements.iterator();
            while (it.hasNext()) {
                verifyElement(it.next());
            }
        }

        private void writeObject(ObjectOutputStream out) throws IOException {

            if (permission == _PRIVATE_CREDENTIALS) {
                // does security check for each private credential
                for (Iterator<SST> it = iterator(); it.hasNext();) {
                    it.next();
                }
                setType = SET_PrivCred;
            } else if (permission == _PRINCIPALS) {
                setType = SET_Principal;
            } else {
                setType = SET_PubCred;
            }

            out.defaultWriteObject();
        }

        /**
         * Represents iterator for subject's secure set
         */
        private class SecureIterator implements Iterator<SST> {
            protected Iterator<SST> iterator;

            protected SecureIterator(Iterator<SST> iterator) {
                this.iterator = iterator;
            }

            public boolean hasNext() {
                return iterator.hasNext();
            }

            public SST next() {
                return iterator.next();
            }

            /**
             * checks set state, and security permission to modify set before
             * removing current element
             */
            public void remove() {
                checkState();
                checkPermission(permission);
                iterator.remove();
            }
        }
    }
}
