ProtectionDomain.java revision adc854b798c1cfe3bfd4c27d68d5cee38ca617da
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 18/** 19* @author Alexander V. Astapchuk 20* @version $Revision$ 21*/ 22 23package java.security; 24 25/** 26 * {@code ProtectionDomain} represents all permissions that are granted to a 27 * specific code source. The {@link ClassLoader} associates each class with the 28 * corresponding {@code ProtectionDomain}, depending on the location and the 29 * certificates (encapsulates in {@link CodeSource}) it loads the code from. 30 * <p> 31 * A class belongs to exactly one protection domain and the protection domain 32 * can not be changed during the lifetime of the class. 33 * </p> 34 * 35 * @since Android 1.0 36 */ 37public class ProtectionDomain { 38 39 // CodeSource for this ProtectionDomain 40 private CodeSource codeSource; 41 42 // Static permissions for this ProtectionDomain 43 private PermissionCollection permissions; 44 45 // ClassLoader 46 private ClassLoader classLoader; 47 48 // Set of principals associated with this ProtectionDomain 49 private Principal[] principals; 50 51 // false if this ProtectionDomain was constructed with static 52 // permissions, true otherwise. 53 private boolean dynamicPerms; 54 55 /** 56 * Constructs a new instance of {@code ProtectionDomain} with the specified 57 * code source and the specified static permissions. 58 * <p> 59 * If {@code permissions} is not {@code null}, the {@code permissions} 60 * collection is made immutable by calling 61 * {@link PermissionCollection#setReadOnly()} and it is considered as 62 * granted statically to this {@code ProtectionDomain}. 63 * </p> 64 * <p> 65 * The policy will not be consulted by access checks against this {@code 66 * ProtectionDomain}. 67 * </p> 68 * <p> 69 * If {@code permissions} is {@code null}, the method 70 * {@link ProtectionDomain#implies(Permission)} always returns {@code false} 71 * . 72 * </p> 73 * 74 * @param cs 75 * the code source associated with this domain, maybe {@code 76 * null}. 77 * @param permissions 78 * the {@code PermissionCollection} containing all permissions to 79 * be statically granted to this {@code ProtectionDomain}, maybe 80 * {@code null}. 81 * @since Android 1.0 82 */ 83 public ProtectionDomain(CodeSource cs, PermissionCollection permissions) { 84 this.codeSource = cs; 85 if (permissions != null) { 86 permissions.setReadOnly(); 87 } 88 this.permissions = permissions; 89 //this.classLoader = null; 90 //this.principals = null; 91 //dynamicPerms = false; 92 } 93 94 95 /** 96 * Constructs a new instance of {@code ProtectionDomain} with the specified 97 * code source, the permissions, the class loader and the principals. 98 * <p> 99 * If {@code permissions} is {@code null}, and access checks are performed 100 * against this protection domain, the permissions defined by the policy are 101 * consulted. If {@code permissions} is not {@code null}, the {@code 102 * permissions} collection is made immutable by calling 103 * {@link PermissionCollection#setReadOnly()}. If access checks are 104 * performed, the policy and the provided permission collection are checked. 105 * </p> 106 * <p> 107 * External modifications of the provided {@code principals} array has no 108 * impact on this {@code ProtectionDomain}. 109 * </p> 110 * 111 * @param cs 112 * the code source associated with this domain, maybe {@code 113 * null}. 114 * @param permissions 115 * the permissions associated with this domain, maybe {@code 116 * null}. 117 * @param cl 118 * the class loader associated with this domain, maybe {@code 119 * null}. 120 * @param principals 121 * the principals associated with this domain, maybe {@code null} 122 * . 123 * @since Android 1.0 124 */ 125 public ProtectionDomain(CodeSource cs, PermissionCollection permissions, 126 ClassLoader cl, Principal[] principals) { 127 this.codeSource = cs; 128 if (permissions != null) { 129 permissions.setReadOnly(); 130 } 131 this.permissions = permissions; 132 this.classLoader = cl; 133 if (principals != null) { 134 this.principals = new Principal[principals.length]; 135 System.arraycopy(principals, 0, this.principals, 0, 136 this.principals.length); 137 } 138 dynamicPerms = true; 139 } 140 141 /** 142 * Returns the {@code ClassLoader} associated with this {@code 143 * ProtectionDomain}. 144 * 145 * @return the {@code ClassLoader} associated with this {@code 146 * ProtectionDomain}, maybe {@code null}. 147 * @since Android 1.0 148 */ 149 public final ClassLoader getClassLoader() { 150 return classLoader; 151 } 152 153 /** 154 * Returns the {@code CodeSource} of this {@code ProtectionDomain}. 155 * 156 * @return the {@code CodeSource} of this {@code ProtectionDomain}, maybe 157 * {@code null}. 158 * @since Android 1.0 159 */ 160 public final CodeSource getCodeSource() { 161 return codeSource; 162 } 163 164 /** 165 * Returns the static permissions that are granted to this {@code 166 * ProtectionDomain}. 167 * 168 * @return the static permissions that are granted to this {@code 169 * ProtectionDomain}, maybe {@code null}. 170 * @since Android 1.0 171 */ 172 public final PermissionCollection getPermissions() { 173 return permissions; 174 } 175 176 /** 177 * Returns the principals associated with this {@code ProtectionDomain}. 178 * Modifications of the returned {@code Principal} array has no impact on 179 * this {@code ProtectionDomain}. 180 * 181 * @return the principals associated with this {@code ProtectionDomain}. 182 * @since Android 1.0 183 */ 184 public final Principal[] getPrincipals() { 185 if( principals == null ) { 186 return new Principal[0]; 187 } 188 Principal[] tmp = new Principal[principals.length]; 189 System.arraycopy(principals, 0, tmp, 0, tmp.length); 190 return tmp; 191 } 192 193 /** 194 * Indicates whether the specified permission is implied by this {@code 195 * ProtectionDomain}. 196 * <p> 197 * If this {@code ProtectionDomain} was constructed with 198 * {@link #ProtectionDomain(CodeSource, PermissionCollection)}, the 199 * specified permission is only checked against the permission collection 200 * provided in the constructor. If {@code null} was provided, {@code false} 201 * is returned. 202 * </p> 203 * <p> 204 * If this {@code ProtectionDomain} was constructed with 205 * {@link #ProtectionDomain(CodeSource, PermissionCollection, ClassLoader, Principal[])} 206 * , the specified permission is checked against the policy and the 207 * permission collection provided in the constructor. 208 * </p> 209 * 210 * @param permission 211 * the permission to check against the domain. 212 * @return {@code true} if the specified {@code permission} is implied by 213 * this {@code ProtectionDomain}, {@code false} otherwise. 214 * @since Android 1.0 215 */ 216 public boolean implies(Permission permission) { 217 // First, test with the Policy, as the default Policy.implies() 218 // checks for both dynamic and static collections of the 219 // ProtectionDomain passed... 220 if (dynamicPerms 221 && Policy.getAccessiblePolicy().implies(this, permission)) { 222 return true; 223 } 224 225 // ... and we get here if 226 // either the permissions are static 227 // or Policy.implies() did not check for static permissions 228 // or the permission is not implied 229 return permissions == null ? false : permissions.implies(permission); 230 } 231 232 /** 233 * Returns a string containing a concise, human-readable description of the 234 * this {@code ProtectionDomain}. 235 * 236 * @return a printable representation for this {@code ProtectionDomain}. 237 * @since Android 1.0 238 */ 239 public String toString() { 240 //FIXME: 1.5 use StreamBuilder here 241 StringBuffer buf = new StringBuffer(200); 242 buf.append("ProtectionDomain\n"); //$NON-NLS-1$ 243 buf.append("CodeSource=").append( //$NON-NLS-1$ 244 codeSource == null ? "<null>" : codeSource.toString()).append( //$NON-NLS-1$ 245 "\n"); //$NON-NLS-1$ 246 buf.append("ClassLoader=").append( //$NON-NLS-1$ 247 classLoader == null ? "<null>" : classLoader.toString()) //$NON-NLS-1$ 248 .append("\n"); //$NON-NLS-1$ 249 if (principals == null || principals.length == 0) { 250 buf.append("<no principals>\n"); //$NON-NLS-1$ 251 } else { 252 buf.append("Principals: <\n"); //$NON-NLS-1$ 253 for (int i = 0; i < principals.length; i++) { 254 buf.append("\t").append( //$NON-NLS-1$ 255 principals[i] == null ? "<null>" : principals[i] //$NON-NLS-1$ 256 .toString()).append("\n"); //$NON-NLS-1$ 257 } 258 buf.append(">"); //$NON-NLS-1$ 259 } 260 261 //permissions here 262 buf.append("Permissions:\n"); //$NON-NLS-1$ 263 if (permissions == null) { 264 buf.append("\t\t<no static permissions>\n"); //$NON-NLS-1$ 265 } else { 266 buf.append("\t\tstatic: ").append(permissions.toString()).append( //$NON-NLS-1$ 267 "\n"); //$NON-NLS-1$ 268 } 269 270 if (dynamicPerms) { 271 if (Policy.isSet()) { 272 PermissionCollection perms; 273 perms = Policy.getAccessiblePolicy().getPermissions(this); 274 if (perms == null) { 275 buf.append("\t\t<no dynamic permissions>\n"); //$NON-NLS-1$ 276 } else { 277 buf.append("\t\tdynamic: ").append(perms.toString()) //$NON-NLS-1$ 278 .append("\n"); //$NON-NLS-1$ 279 } 280 } else { 281 buf.append("\t\t<no dynamic permissions>\n"); //$NON-NLS-1$ 282 } 283 } 284 return buf.toString(); 285 } 286} 287