001 /* AccessControlContext.java --- Access Control Context Class
002 Copyright (C) 1999, 2004 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038 package java.security;
039
040 import java.util.HashSet;
041
042 /**
043 * AccessControlContext makes system resource access decsion
044 * based on permission rights.
045 *
046 * It is used for a specific context and has only one method
047 * checkPermission. It is similar to AccessController except
048 * that it makes decsions based on the current context instead
049 * of the the current thread.
050 *
051 * It is created by call AccessController.getContext method.
052 *
053 * @author Mark Benvenuto
054 * @since 1.2
055 */
056 public final class AccessControlContext
057 {
058 private final ProtectionDomain[] protectionDomains;
059 private final DomainCombiner combiner;
060
061 /**
062 * Construct a new AccessControlContext with the specified
063 * ProtectionDomains. <code>context</code> must not be
064 * null and duplicates will be removed.
065 *
066 * @param context The ProtectionDomains to use
067 */
068 public AccessControlContext(ProtectionDomain[] context)
069 {
070 HashSet domains = new HashSet (context.length);
071 for (int i = 0; i < context.length; i++)
072 domains.add (context[i]);
073 protectionDomains = (ProtectionDomain[])
074 domains.toArray (new ProtectionDomain[domains.size()]);
075 combiner = null;
076 }
077
078 /**
079 * Construct a new AccessControlContext with the specified
080 * {@link ProtectionDomain}s and {@link DomainCombiner}.
081 *
082 * <p>Code calling this constructor must have a {@link
083 * SecurityPermission} of <i>createAccessControlContext</i>.</p>
084 *
085 * @throws SecurityException If the caller does not have permission
086 * to create an access control context.
087 * @since 1.3
088 */
089 public AccessControlContext(AccessControlContext acc,
090 DomainCombiner combiner)
091 {
092 AccessControlContext acc2 = null;
093 SecurityManager sm = System.getSecurityManager ();
094 if (sm != null)
095 {
096 Permission perm =
097 new SecurityPermission ("createAccessControlContext");
098
099 // The default SecurityManager.checkPermission(perm) just calls
100 // AccessController.checkPermission(perm) which in turn just
101 // calls AccessController.getContext().checkPermission(perm).
102 // This means AccessController.getContext() is called twice,
103 // once for the security check and once by us. It's a very
104 // expensive call (on gcj at least) so if we're using the
105 // default security manager we avoid this duplication.
106 if (sm.getClass() == SecurityManager.class)
107 {
108 acc2 = AccessController.getContext ();
109 acc2.checkPermission (perm);
110 }
111 else
112 sm.checkPermission (perm);
113 }
114 if (acc2 == null)
115 acc2 = AccessController.getContext ();
116 protectionDomains = combiner.combine (acc2.protectionDomains,
117 acc.protectionDomains);
118 this.combiner = combiner;
119 }
120
121 AccessControlContext (ProtectionDomain[] domains, AccessControlContext acc,
122 DomainCombiner combiner)
123 {
124 protectionDomains = combiner.combine (domains, acc.protectionDomains);
125 this.combiner = combiner;
126 }
127
128 /**
129 * Returns the Domain Combiner associated with the AccessControlContext
130 *
131 * @return the DomainCombiner
132 */
133 public DomainCombiner getDomainCombiner()
134 {
135 return combiner;
136 }
137
138 /**
139 * Determines whether or not the specific permission is granted
140 * depending on the context it is within.
141 *
142 * @param perm a permission to check
143 *
144 * @throws AccessControlException if the permssion is not permitted
145 */
146 public void checkPermission(Permission perm) throws AccessControlException
147 {
148 if (protectionDomains.length == 0)
149 throw new AccessControlException ("permission "
150 + perm
151 + " not granted: no protection domains");
152
153 for (int i = 0; i < protectionDomains.length; i++)
154 {
155 final ProtectionDomain domain = protectionDomains[i];
156 if (!domain.implies(perm))
157 throw new AccessControlException ("permission "
158 + perm
159 + " not granted: "
160 + domain
161 + " does not imply it.");
162 }
163 }
164
165 /**
166 * Checks if two AccessControlContexts are equal.
167 *
168 * It first checks if obj is an AccessControlContext class, and
169 * then checks if each ProtectionDomain matches.
170 *
171 * @param obj The object to compare this class to
172 *
173 * @return true if equal, false otherwise
174 */
175 public boolean equals(Object obj)
176 {
177 if (obj instanceof AccessControlContext)
178 {
179 AccessControlContext acc = (AccessControlContext) obj;
180
181 if (acc.protectionDomains.length != protectionDomains.length)
182 return false;
183
184 int i, j;
185 for (i = 0; i < protectionDomains.length; i++)
186 {
187 for (j = 0; j < acc.protectionDomains.length; j++)
188 {
189 if (acc.protectionDomains[j].equals (protectionDomains[i]))
190 break;
191 }
192 if (j == acc.protectionDomains.length)
193 return false;
194 }
195 return true;
196 }
197 return false;
198 }
199
200 /**
201 * Computes a hash code of this class
202 *
203 * @return a hash code representing this class
204 */
205 public int hashCode()
206 {
207 int h = 0;
208 for (int i = 0; i < protectionDomains.length; i++)
209 h ^= protectionDomains[i].hashCode();
210
211 return h;
212 }
213
214 ProtectionDomain[] getProtectionDomains ()
215 {
216 return protectionDomains;
217 }
218 }