1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage javax.security.auth;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectInputStream;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectOutputStream;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.Serializable;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.AccessControlContext;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.AccessController;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.DomainCombiner;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.Permission;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.Principal;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivilegedAction;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivilegedActionException;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivilegedExceptionAction;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.ProtectionDomain;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.AbstractSet;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collection;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Iterator;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.LinkedList;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Set;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The central class of the {@code javax.security.auth} package representing an
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * authenticated user or entity (both referred to as "subject"). IT defines also
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the static methods that allow code to be run, and do modifications according
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to the subject's permissions.
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A subject has the following features:
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ul>
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>A set of {@code Principal} objects specifying the identities bound to a
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code Subject} that distinguish it.</li>
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>Credentials (public and private) such as certificates, keys, or
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * authentication proofs such as tickets</li>
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </ul>
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic final class Subject implements Serializable {
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = -8308522755600156056L;
56f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
57f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    private static final AuthPermission _AS = new AuthPermission("doAs");
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final AuthPermission _AS_PRIVILEGED = new AuthPermission(
60f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            "doAsPrivileged");
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final AuthPermission _SUBJECT = new AuthPermission(
63f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            "getSubject");
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final AuthPermission _PRINCIPALS = new AuthPermission(
66f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            "modifyPrincipals");
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final AuthPermission _PRIVATE_CREDENTIALS = new AuthPermission(
69f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            "modifyPrivateCredentials");
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final AuthPermission _PUBLIC_CREDENTIALS = new AuthPermission(
72f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            "modifyPublicCredentials");
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final AuthPermission _READ_ONLY = new AuthPermission(
75f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            "setReadOnly");
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final Set<Principal> principals;
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean readOnly;
80f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // set of private credentials
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient SecureSet<Object> privateCredentials;
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // set of public credentials
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient SecureSet<Object> publicCredentials;
86f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The default constructor initializing the sets of public and private
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * credentials and principals with the empty set.
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Subject() {
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        principals = new SecureSet<Principal>(_PRINCIPALS);
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS);
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS);
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        readOnly = false;
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The constructor for the subject, setting its public and private
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * credentials and principals according to the arguments.
10213970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param readOnly
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            {@code true} if this {@code Subject} is read-only, thus
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            preventing any modifications to be done.
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param subjPrincipals
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the set of Principals that are attributed to this {@code
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            Subject}.
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param pubCredentials
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the set of public credentials that distinguish this {@code
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            Subject}.
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param privCredentials
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the set of private credentials that distinguish this {@code
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            Subject}.
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Subject(boolean readOnly, Set<? extends Principal> subjPrincipals,
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Set<?> pubCredentials, Set<?> privCredentials) {
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
11986acc043d3334651ee26c65467d78d6cefedd397Kenny Root        if (subjPrincipals == null) {
12086acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("subjPrincipals == null");
12186acc043d3334651ee26c65467d78d6cefedd397Kenny Root        } else if (pubCredentials == null) {
12286acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("pubCredentials == null");
12386acc043d3334651ee26c65467d78d6cefedd397Kenny Root        } else if (privCredentials == null) {
12486acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("privCredentials == null");
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        principals = new SecureSet<Principal>(_PRINCIPALS, subjPrincipals);
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS, pubCredentials);
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS, privCredentials);
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.readOnly = readOnly;
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Runs the code defined by {@code action} using the permissions granted to
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the {@code Subject} itself and to the code as well.
13713970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param subject
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the distinguished {@code Subject}.
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param action
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the code to be run.
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the {@code Object} returned when running the {@code action}.
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("unchecked")
14555b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson    public static <T> T doAs(Subject subject, PrivilegedAction<T> action) {
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return doAs_PrivilegedAction(subject, action, AccessController.getContext());
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Run the code defined by {@code action} using the permissions granted to
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the {@code Subject} and to the code itself, additionally providing a more
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * specific context.
15313970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param subject
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the distinguished {@code Subject}.
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param action
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the code to be run.
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param context
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the specific context in which the {@code action} is invoked.
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            if {@code null} a new {@link AccessControlContext} is
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            instantiated.
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the {@code Object} returned when running the {@code action}.
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("unchecked")
16555b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson    public static <T> T doAsPrivileged(Subject subject, PrivilegedAction<T> action,
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            AccessControlContext context) {
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (context == null) {
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return doAs_PrivilegedAction(subject, action, new AccessControlContext(
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    new ProtectionDomain[0]));
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return doAs_PrivilegedAction(subject, action, context);
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // instantiates a new context and passes it to AccessController
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("unchecked")
17655b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson    private static <T> T doAs_PrivilegedAction(Subject subject, PrivilegedAction<T> action,
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            final AccessControlContext context) {
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        AccessControlContext newContext;
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        final SubjectDomainCombiner combiner;
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (subject == null) {
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // performance optimization
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // if subject is null there is nothing to combine
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            combiner = null;
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            combiner = new SubjectDomainCombiner(subject);
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        PrivilegedAction dccAction = new PrivilegedAction() {
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            public Object run() {
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return new AccessControlContext(context, combiner);
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        };
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        newContext = (AccessControlContext) AccessController.doPrivileged(dccAction);
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return AccessController.doPrivileged(action, newContext);
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Runs the code defined by {@code action} using the permissions granted to
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the subject and to the code itself.
20413970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param subject
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the distinguished {@code Subject}.
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param action
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the code to be run.
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the {@code Object} returned when running the {@code action}.
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws PrivilegedActionException
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if running the {@code action} throws an exception.
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("unchecked")
21455b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson    public static <T> T doAs(Subject subject, PrivilegedExceptionAction<T> action)
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws PrivilegedActionException {
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return doAs_PrivilegedExceptionAction(subject, action, AccessController.getContext());
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Runs the code defined by {@code action} using the permissions granted to
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the subject and to the code itself, additionally providing a more
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * specific context.
22313970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param subject
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the distinguished {@code Subject}.
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param action
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the code to be run.
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param context
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the specific context in which the {@code action} is invoked.
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            if {@code null} a new {@link AccessControlContext} is
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            instantiated.
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the {@code Object} returned when running the {@code action}.
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws PrivilegedActionException
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if running the {@code action} throws an exception.
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("unchecked")
23755b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson    public static <T> T doAsPrivileged(Subject subject,
23855b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson            PrivilegedExceptionAction<T> action, AccessControlContext context)
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws PrivilegedActionException {
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (context == null) {
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return doAs_PrivilegedExceptionAction(subject, action,
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    new AccessControlContext(new ProtectionDomain[0]));
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return doAs_PrivilegedExceptionAction(subject, action, context);
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // instantiates a new context and passes it to AccessController
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("unchecked")
24955b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson    private static <T> T doAs_PrivilegedExceptionAction(Subject subject,
25055b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson            PrivilegedExceptionAction<T> action, final AccessControlContext context)
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws PrivilegedActionException {
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        AccessControlContext newContext;
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        final SubjectDomainCombiner combiner;
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (subject == null) {
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // performance optimization
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // if subject is null there is nothing to combine
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            combiner = null;
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            combiner = new SubjectDomainCombiner(subject);
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        PrivilegedAction<AccessControlContext> dccAction = new PrivilegedAction<AccessControlContext>() {
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            public AccessControlContext run() {
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return new AccessControlContext(context, combiner);
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        };
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        newContext = AccessController.doPrivileged(dccAction);
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return AccessController.doPrivileged(action, newContext);
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks two Subjects for equality. More specifically if the principals,
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * public and private credentials are equal, equality for two {@code
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Subjects} is implied.
27913970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param obj
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Object} checked for equality with this {@code
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            Subject}.
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the specified {@code Subject} is equal to this
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         one.
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Object obj) {
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (this == obj) {
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (obj == null || this.getClass() != obj.getClass()) {
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Subject that = (Subject) obj;
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (principals.equals(that.principals)
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && publicCredentials.equals(that.publicCredentials)
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && privateCredentials.equals(that.privateCredentials)) {
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns this {@code Subject}'s {@link Principal}.
30913970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this {@code Subject}'s {@link Principal}.
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Set<Principal> getPrincipals() {
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return principals;
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
31613970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns this {@code Subject}'s {@link Principal} which is a subclass of
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the {@code Class} provided.
32013970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param c
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Class} as a criteria which the {@code Principal}
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            returned must satisfy.
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this {@code Subject}'s {@link Principal}. Modifications to the
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         returned set of {@code Principal}s do not affect this {@code
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         Subject}'s set.
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public <T extends Principal> Set<T> getPrincipals(Class<T> c) {
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return ((SecureSet<Principal>) principals).get(c);
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the private credentials associated with this {@code Subject}.
33413970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the private credentials associated with this {@code Subject}.
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Set<Object> getPrivateCredentials() {
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return privateCredentials;
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns this {@code Subject}'s private credentials which are a subclass
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of the {@code Class} provided.
34413970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param c
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Class} as a criteria which the private credentials
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            returned must satisfy.
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this {@code Subject}'s private credentials. Modifications to the
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         returned set of credentials do not affect this {@code Subject}'s
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         credentials.
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public <T> Set<T> getPrivateCredentials(Class<T> c) {
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return privateCredentials.get(c);
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the public credentials associated with this {@code Subject}.
35813970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the public credentials associated with this {@code Subject}.
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Set<Object> getPublicCredentials() {
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return publicCredentials;
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
36513970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns this {@code Subject}'s public credentials which are a subclass of
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the {@code Class} provided.
36913970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param c
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Class} as a criteria which the public credentials
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            returned must satisfy.
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this {@code Subject}'s public credentials. Modifications to the
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         returned set of credentials do not affect this {@code Subject}'s
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         credentials.
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public <T> Set<T> getPublicCredentials(Class<T> c) {
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return publicCredentials.get(c);
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a hash code of this {@code Subject}.
38313970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a hash code of this {@code Subject}.
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int hashCode() {
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return principals.hashCode() + privateCredentials.hashCode()
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                + publicCredentials.hashCode();
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Prevents from modifications being done to the credentials and {@link
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Principal} sets. After setting it to read-only this {@code Subject} can
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * not be made writable again. The destroy method on the credentials still
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * works though.
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setReadOnly() {
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        readOnly = true;
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether this {@code Subject} is read-only or not.
40413970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return whether this {@code Subject} is read-only or not.
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isReadOnly() {
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return readOnly;
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a {@code String} representation of this {@code Subject}.
41313970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a {@code String} representation of this {@code Subject}.
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
4187f0c06f737b6f1f6b3a5bb30111f95dd0ca586a2Brian Carlstrom        StringBuilder buf = new StringBuilder("Subject:\n");
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Iterator<?> it = principals.iterator();
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (it.hasNext()) {
422f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            buf.append("\tPrincipal: ");
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            buf.append(it.next());
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            buf.append('\n');
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        it = publicCredentials.iterator();
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (it.hasNext()) {
429f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            buf.append("\tPublic Credential: ");
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            buf.append(it.next());
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            buf.append('\n');
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int offset = buf.length() - 1;
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        it = privateCredentials.iterator();
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            while (it.hasNext()) {
438f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                buf.append("\tPrivate Credential: ");
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                buf.append(it.next());
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                buf.append('\n');
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (SecurityException e) {
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            buf.delete(offset, buf.length());
444f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            buf.append("\tPrivate Credentials: no accessible information\n");
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return buf.toString();
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void readObject(ObjectInputStream in) throws IOException,
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ClassNotFoundException {
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        in.defaultReadObject();
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS);
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS);
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void writeObject(ObjectOutputStream out) throws IOException {
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        out.defaultWriteObject();
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the {@code Subject} that was last associated with the {@code
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * context} provided as argument.
46513970a92a67826bfd12464079b9ccc173f9ab5a6Jesse Wilson     *
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param context
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code context} that was associated with the
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            {@code Subject}.
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the {@code Subject} that was last associated with the {@code
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         context} provided as argument.
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static Subject getSubject(final AccessControlContext context) {
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (context == null) {
47486acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("context == null");
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        PrivilegedAction<DomainCombiner> action = new PrivilegedAction<DomainCombiner>() {
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            public DomainCombiner run() {
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return context.getDomainCombiner();
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        };
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        DomainCombiner combiner = AccessController.doPrivileged(action);
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((combiner == null) || !(combiner instanceof SubjectDomainCombiner)) {
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return ((SubjectDomainCombiner) combiner).getSubject();
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void checkState() {
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (readOnly) {
4912313047d797e4daece04da8e8ed406d26b589f82Elliott Hughes            throw new IllegalStateException("Set is read-only");
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final class SecureSet<SST> extends AbstractSet<SST> implements Serializable {
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Compatibility issue: see comments for setType variable
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private static final long serialVersionUID = 7911754171111800359L;
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private LinkedList<SST> elements;
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Is used to define a set type for serialization.
506f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes         *
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * A type can be principal, priv. or pub. credential set. The spec.
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * doesn't clearly says that priv. and pub. credential sets can be
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * serialized and what classes they are. It is only possible to figure
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * out from writeObject method comments that priv. credential set is
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * serializable and it is an instance of SecureSet class. So pub.
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * credential was implemented by analogy
513f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes         *
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Compatibility issue: the class follows its specified serial form.
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Also according to the serialization spec. adding new field is a
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * compatible change. So is ok for principal set (because the default
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * value for integer is zero). But priv. or pub. credential set it is
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * not compatible because most probably other implementations resolve
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * this issue in other way
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private int setType;
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Defines principal set for serialization.
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private static final int SET_Principal = 0;
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Defines private credential set for serialization.
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private static final int SET_PrivCred = 1;
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Defines public credential set for serialization.
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private static final int SET_PubCred = 2;
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // permission required to modify set
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private transient AuthPermission permission;
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        protected SecureSet(AuthPermission perm) {
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            permission = perm;
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            elements = new LinkedList<SST>();
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // creates set from specified collection with specified permission
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // all collection elements are verified before adding
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        protected SecureSet(AuthPermission perm, Collection<? extends SST> s) {
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this(perm);
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Subject's constructor receives a Set, we can trusts if a set is from bootclasspath,
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // and not to check whether it contains duplicates or not
547f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            boolean trust = s.getClass().getClassLoader() == null;
548f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
54955b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson            for (SST o : s) {
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                verifyElement(o);
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (trust || !elements.contains(o)) {
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    elements.add(o);
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // verifies new set element
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private void verifyElement(Object o) {
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (o == null) {
56186acc043d3334651ee26c65467d78d6cefedd397Kenny Root                throw new NullPointerException("o == null");
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (permission == _PRINCIPALS && !(Principal.class.isAssignableFrom(o.getClass()))) {
5642313047d797e4daece04da8e8ed406d26b589f82Elliott Hughes                throw new IllegalArgumentException("Element is not instance of java.security.Principal");
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * verifies specified element, checks set state, and security permission
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * to modify set before adding new element
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public boolean add(SST o) {
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            verifyElement(o);
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            checkState();
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!elements.contains(o)) {
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                elements.add(o);
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return true;
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // returns an instance of SecureIterator
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public Iterator<SST> iterator() {
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (permission == _PRIVATE_CREDENTIALS) {
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                /*
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                 * private credential set requires iterator with additional
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                 * security check (PrivateCredentialPermission)
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                 */
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return new SecureIterator(elements.iterator()) {
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    /*
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * checks permission to access next private credential moves
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * to the next element even SecurityException was thrown
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     */
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    @Override
601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    public SST next() {
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        SST obj = iterator.next();
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return obj;
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                };
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return new SecureIterator(elements.iterator());
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public boolean retainAll(Collection<?> c) {
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (c == null) {
61486acc043d3334651ee26c65467d78d6cefedd397Kenny Root                throw new NullPointerException("c == null");
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return super.retainAll(c);
617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int size() {
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return elements.size();
622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * return set with elements that are instances or subclasses of the
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * specified class
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        protected final <E> Set<E> get(final Class<E> c) {
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (c == null) {
63186acc043d3334651ee26c65467d78d6cefedd397Kenny Root                throw new NullPointerException("c == null");
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            AbstractSet<E> s = new AbstractSet<E>() {
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                private LinkedList<E> elements = new LinkedList<E>();
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                @Override
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                public boolean add(E o) {
639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (!c.isAssignableFrom(o.getClass())) {
6402313047d797e4daece04da8e8ed406d26b589f82Elliott Hughes                        throw new IllegalArgumentException("Invalid type: " + o.getClass());
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (elements.contains(o)) {
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return false;
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    elements.add(o);
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return true;
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                @Override
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                public Iterator<E> iterator() {
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return elements.iterator();
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                @Override
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                public boolean retainAll(Collection<?> c) {
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (c == null) {
65986acc043d3334651ee26c65467d78d6cefedd397Kenny Root                        throw new NullPointerException("c == null");
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return super.retainAll(c);
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                @Override
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                public int size() {
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return elements.size();
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            };
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // FIXME must have permissions for requested priv. credentials
67155b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson            for (SST o : this) {
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (c.isAssignableFrom(o.getClass())) {
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s.add(c.cast(o));
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return s;
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private void readObject(ObjectInputStream in) throws IOException,
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                ClassNotFoundException {
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            in.defaultReadObject();
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            switch (setType) {
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case SET_Principal:
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                permission = _PRINCIPALS;
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case SET_PrivCred:
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                permission = _PRIVATE_CREDENTIALS;
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case SET_PubCred:
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                permission = _PUBLIC_CREDENTIALS;
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
69755b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson            for (SST element : elements) {
69855b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson                verifyElement(element);
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70255b2d1c3f492f6140ad6dd18a4bec4ec2643d664Jesse Wilson        @SuppressWarnings("UnusedDeclaration")
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private void writeObject(ObjectOutputStream out) throws IOException {
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (permission == _PRIVATE_CREDENTIALS) {
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                setType = SET_PrivCred;
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (permission == _PRINCIPALS) {
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                setType = SET_Principal;
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                setType = SET_PubCred;
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            out.defaultWriteObject();
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Represents iterator for subject's secure set
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private class SecureIterator implements Iterator<SST> {
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            protected Iterator<SST> iterator;
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            protected SecureIterator(Iterator<SST> iterator) {
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.iterator = iterator;
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            public boolean hasNext() {
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return iterator.hasNext();
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            public SST next() {
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return iterator.next();
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /**
735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * checks set state, and security permission to modify set before
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * removing current element
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            public void remove() {
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                checkState();
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                iterator.remove();
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
7442313047d797e4daece04da8e8ed406d26b589f82Elliott Hughes}
745