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 }