1 /* AccessControlContext.java --- Access Control Context Class
2    Copyright (C) 1999, 2004 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 package java.security;
39 
40 import java.util.HashSet;
41 
42 /**
43  * AccessControlContext makes system resource access decsion
44  * based on permission rights.
45  *
46  * It is used for a specific context and has only one method
47  * checkPermission. It is similar to AccessController except
48  * that it makes decsions based on the current context instead
49  * of the the current thread.
50  *
51  * It is created by call AccessController.getContext method.
52  *
53  * @author Mark Benvenuto
54  * @since 1.2
55  */
56 public final class AccessControlContext
57 {
58   private final ProtectionDomain[] protectionDomains;
59   private final DomainCombiner combiner;
60 
61   /**
62    * Construct a new AccessControlContext with the specified
63    * ProtectionDomains. <code>context</code> must not be
64    * null and duplicates will be removed.
65    *
66    * @param context The ProtectionDomains to use
67    */
AccessControlContext(ProtectionDomain[] context)68   public AccessControlContext(ProtectionDomain[] context)
69   {
70     HashSet domains = new HashSet (context.length);
71     for (int i = 0; i < context.length; i++)
72       domains.add (context[i]);
73     protectionDomains = (ProtectionDomain[])
74       domains.toArray (new ProtectionDomain[domains.size()]);
75     combiner = null;
76   }
77 
78   /**
79    * Construct a new AccessControlContext with the specified
80    * {@link ProtectionDomain}s and {@link DomainCombiner}.
81    *
82    * <p>Code calling this constructor must have a {@link
83    * SecurityPermission} of <i>createAccessControlContext</i>.</p>
84    *
85    * @throws SecurityException If the caller does not have permission
86    * to create an access control context.
87    * @since 1.3
88    */
AccessControlContext(AccessControlContext acc, DomainCombiner combiner)89   public AccessControlContext(AccessControlContext acc,
90                               DomainCombiner combiner)
91   {
92     AccessControlContext acc2 = null;
93     SecurityManager sm = System.getSecurityManager ();
94     if (sm != null)
95       {
96         Permission perm =
97           new SecurityPermission ("createAccessControlContext");
98 
99         // 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 
AccessControlContext(ProtectionDomain[] domains, AccessControlContext acc, DomainCombiner combiner)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    */
getDomainCombiner()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    */
checkPermission(Permission perm)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    */
equals(Object obj)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    */
hashCode()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 
getProtectionDomains()214   ProtectionDomain[] getProtectionDomains ()
215   {
216     return protectionDomains;
217   }
218 }
219