SubjectDomainCombiner.java revision ad41624e761bcf1af9c8008eb45187fc13983717
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package javax.security.auth;
19
20import java.security.DomainCombiner;
21import java.security.Principal;
22import java.security.ProtectionDomain;
23import java.util.Set;
24
25/**
26 * Merges permissions based on code source and code signers with permissions
27 * granted to the specified {@link Subject}.
28 */
29public class SubjectDomainCombiner implements DomainCombiner {
30
31    // subject to be associated
32    private Subject subject;
33
34    // permission required to get a subject object
35    private static final AuthPermission _GET = new AuthPermission(
36            "getSubjectFromDomainCombiner");
37
38    /**
39     * Creates a domain combiner for the entity provided in {@code subject}.
40     *
41     * @param subject
42     *            the entity to which this domain combiner is associated.
43     */
44    public SubjectDomainCombiner(Subject subject) {
45        super();
46        if (subject == null) {
47            throw new NullPointerException();
48        }
49        this.subject = subject;
50    }
51
52    /**
53     * Returns the entity to which this domain combiner is associated.
54     *
55     * @return the entity to which this domain combiner is associated.
56     */
57    public Subject getSubject() {
58        return subject;
59    }
60
61    /**
62     * Merges the {@code ProtectionDomain} with the {@code Principal}s
63     * associated with the subject of this {@code SubjectDomainCombiner}.
64     *
65     * @param currentDomains
66     *            the {@code ProtectionDomain}s associated with the context of
67     *            the current thread. The domains must be sorted according to
68     *            the execution order, the most recent residing at the
69     *            beginning.
70     * @param assignedDomains
71     *            the {@code ProtectionDomain}s from the parent thread based on
72     *            code source and signers.
73     * @return a single {@code ProtectionDomain} array computed from the two
74     *         provided arrays, or {@code null}.
75     * @see ProtectionDomain
76     */
77    public ProtectionDomain[] combine(ProtectionDomain[] currentDomains,
78            ProtectionDomain[] assignedDomains) {
79        // get array length for combining protection domains
80        int len = 0;
81        if (currentDomains != null) {
82            len += currentDomains.length;
83        }
84        if (assignedDomains != null) {
85            len += assignedDomains.length;
86        }
87        if (len == 0) {
88            return null;
89        }
90
91        ProtectionDomain[] pd = new ProtectionDomain[len];
92
93        // for each current domain substitute set of principal with subject's
94        int cur = 0;
95        if (currentDomains != null) {
96
97            Set<Principal> s = subject.getPrincipals();
98            Principal[] p = s.toArray(new Principal[s.size()]);
99
100            for (cur = 0; cur < currentDomains.length; cur++) {
101                ProtectionDomain newPD;
102                newPD = new ProtectionDomain(currentDomains[cur].getCodeSource(),
103                        currentDomains[cur].getPermissions(), currentDomains[cur]
104                                .getClassLoader(), p);
105                pd[cur] = newPD;
106            }
107        }
108
109        // copy assigned domains
110        if (assignedDomains != null) {
111            System.arraycopy(assignedDomains, 0, pd, cur, assignedDomains.length);
112        }
113
114        return pd;
115    }
116}
117