1/* 2 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.rmi.rmid; 27 28import java.security.*; 29import java.io.*; 30import java.util.*; 31 32/** 33 * The ExecOptionPermission class represents permission for rmid to use 34 * a specific command-line option when launching an activation group. 35 * 36 * @author Ann Wollrath 37 * 38 * @serial exclude 39 */ 40public final class ExecOptionPermission extends Permission 41{ 42 /** 43 * does this permission have a wildcard at the end? 44 */ 45 private transient boolean wildcard; 46 47 /** 48 * the name without the wildcard on the end 49 */ 50 private transient String name; 51 52 /** 53 * UID for serialization 54 */ 55 private static final long serialVersionUID = 5842294756823092756L; 56 57 public ExecOptionPermission(String name) { 58 super(name); 59 init(name); 60 } 61 62 public ExecOptionPermission(String name, String actions) { 63 this(name); 64 } 65 66 /** 67 * Checks if the specified permission is "implied" by 68 * this object. 69 * <P> 70 * More specifically, this method returns true if: 71 * <ul> 72 * <li> <i>p</i>'s class is the same as this object's class, and 73 * <li> <i>p</i>'s name equals or (in the case of wildcards) 74 * is implied by this object's 75 * name. For example, "a.b.*" implies "a.b.c", and 76 * "a.b=*" implies "a.b=c" 77 * </ul> 78 * 79 * @param p the permission to check against. 80 * 81 * @return true if the passed permission is equal to or 82 * implied by this permission, false otherwise. 83 */ 84 public boolean implies(Permission p) { 85 if (!(p instanceof ExecOptionPermission)) 86 return false; 87 88 ExecOptionPermission that = (ExecOptionPermission) p; 89 90 if (this.wildcard) { 91 if (that.wildcard) { 92 // one wildcard can imply another 93 return that.name.startsWith(name); 94 } else { 95 // make sure p.name is longer so a.b.* doesn't imply a.b 96 return (that.name.length() > this.name.length()) && 97 that.name.startsWith(this.name); 98 } 99 } else { 100 if (that.wildcard) { 101 // a non-wildcard can't imply a wildcard 102 return false; 103 } else { 104 return this.name.equals(that.name); 105 } 106 } 107 } 108 109 /** 110 * Checks two ExecOptionPermission objects for equality. 111 * Checks that <i>obj</i>'s class is the same as this object's class 112 * and has the same name as this object. 113 * 114 * @param obj the object we are testing for equality with this object. 115 * @return true if <i>obj</i> is an ExecOptionPermission, and has the same 116 * name as this ExecOptionPermission object, false otherwise. 117 */ 118 public boolean equals(Object obj) { 119 if (obj == this) 120 return true; 121 122 if ((obj == null) || (obj.getClass() != getClass())) 123 return false; 124 125 ExecOptionPermission that = (ExecOptionPermission) obj; 126 127 return this.getName().equals(that.getName()); 128 } 129 130 131 /** 132 * Returns the hash code value for this object. 133 * The hash code used is the hash code of the name, that is, 134 * <code>getName().hashCode()</code>, where <code>getName</code> is 135 * from the Permission superclass. 136 * 137 * @return a hash code value for this object. 138 */ 139 public int hashCode() { 140 return this.getName().hashCode(); 141 } 142 143 /** 144 * Returns the canonical string representation of the actions. 145 * 146 * @return the canonical string representation of the actions. 147 */ 148 public String getActions() { 149 return ""; 150 } 151 152 /** 153 * Returns a new PermissionCollection object for storing 154 * ExecOptionPermission objects. 155 * <p> 156 * An ExecOptionPermissionCollection stores a collection of 157 * ExecOptionPermission permissions. 158 * 159 * <p>ExecOptionPermission objects must be stored in a manner that allows 160 * them to be inserted in any order, but that also enables the 161 * PermissionCollection <code>implies</code> method 162 * to be implemented in an efficient (and consistent) manner. 163 * 164 * @return a new PermissionCollection object suitable for 165 * storing ExecOptionPermissions. 166 */ 167 public PermissionCollection newPermissionCollection() { 168 return new ExecOptionPermissionCollection(); 169 } 170 171 /** 172 * readObject is called to restore the state of the ExecOptionPermission 173 * from a stream. 174 */ 175 private synchronized void readObject(java.io.ObjectInputStream s) 176 throws IOException, ClassNotFoundException 177 { 178 s.defaultReadObject(); 179 // init is called to initialize the rest of the values. 180 init(getName()); 181 } 182 183 /** 184 * Initialize a ExecOptionPermission object. Common to all constructors. 185 * Also called during de-serialization. 186 */ 187 private void init(String name) 188 { 189 if (name == null) 190 throw new NullPointerException("name can't be null"); 191 192 if (name.equals("")) { 193 throw new IllegalArgumentException("name can't be empty"); 194 } 195 196 if (name.endsWith(".*") || name.endsWith("=*") || name.equals("*")) { 197 wildcard = true; 198 if (name.length() == 1) { 199 this.name = ""; 200 } else { 201 this.name = name.substring(0, name.length()-1); 202 } 203 } else { 204 this.name = name; 205 } 206 } 207 208 /** 209 * A ExecOptionPermissionCollection stores a collection 210 * of ExecOptionPermission permissions. ExecOptionPermission objects 211 * must be stored in a manner that allows them to be inserted in any 212 * order, but enable the implies function to evaluate the implies 213 * method in an efficient (and consistent) manner. 214 * 215 * A ExecOptionPermissionCollection handles comparing a permission like 216 * "a.b.c.d.e" * with a Permission such as "a.b.*", or "*". 217 * 218 * @serial include 219 */ 220 private static class ExecOptionPermissionCollection 221 extends PermissionCollection 222 implements java.io.Serializable 223 { 224 225 private Hashtable<String, Permission> permissions; 226 private boolean all_allowed; // true if "*" is in the collection 227 private static final long serialVersionUID = -1242475729790124375L; 228 229 /** 230 * Create an empty ExecOptionPermissionCollection. 231 */ 232 public ExecOptionPermissionCollection() { 233 permissions = new Hashtable<>(11); 234 all_allowed = false; 235 } 236 237 /** 238 * Adds a permission to the collection. The key for the hash is 239 * permission.name. 240 * 241 * @param permission the Permission object to add. 242 * 243 * @exception IllegalArgumentException - if the permission is not a 244 * ExecOptionPermission 245 * 246 * @exception SecurityException - if this ExecOptionPermissionCollection 247 * object has been marked readonly 248 */ 249 250 public void add(Permission permission) 251 { 252 if (! (permission instanceof ExecOptionPermission)) 253 throw new IllegalArgumentException("invalid permission: "+ 254 permission); 255 if (isReadOnly()) 256 throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection"); 257 258 ExecOptionPermission p = (ExecOptionPermission) permission; 259 260 permissions.put(p.getName(), permission); 261 if (!all_allowed) { 262 if (p.getName().equals("*")) 263 all_allowed = true; 264 } 265 } 266 267 /** 268 * Check and see if this set of permissions implies the permissions 269 * expressed in "permission". 270 * 271 * @param p the Permission object to compare 272 * 273 * @return true if "permission" is a proper subset of a permission in 274 * the set, false if not. 275 */ 276 public boolean implies(Permission permission) 277 { 278 if (! (permission instanceof ExecOptionPermission)) 279 return false; 280 281 ExecOptionPermission p = (ExecOptionPermission) permission; 282 283 // short circuit if the "*" Permission was added 284 if (all_allowed) 285 return true; 286 287 // strategy: 288 // Check for full match first. Then work our way up the 289 // name looking for matches on a.b.* 290 291 String pname = p.getName(); 292 293 Permission x = permissions.get(pname); 294 295 if (x != null) 296 // we have a direct hit! 297 return x.implies(permission); 298 299 300 // work our way up the tree... 301 int last, offset; 302 303 offset = pname.length() - 1; 304 305 while ((last = pname.lastIndexOf('.', offset)) != -1) { 306 307 pname = pname.substring(0, last+1) + "*"; 308 x = permissions.get(pname); 309 310 if (x != null) { 311 return x.implies(permission); 312 } 313 offset = last - 1; 314 } 315 316 // check for "=*" wildcard match 317 pname = p.getName(); 318 offset = pname.length() - 1; 319 320 while ((last = pname.lastIndexOf('=', offset)) != -1) { 321 322 pname = pname.substring(0, last+1) + "*"; 323 x = permissions.get(pname); 324 325 if (x != null) { 326 return x.implies(permission); 327 } 328 offset = last - 1; 329 } 330 331 // we don't have to check for "*" as it was already checked 332 // at the top (all_allowed), so we just return false 333 return false; 334 } 335 336 /** 337 * Returns an enumeration of all the ExecOptionPermission objects in the 338 * container. 339 * 340 * @return an enumeration of all the ExecOptionPermission objects. 341 */ 342 343 public Enumeration<Permission> elements() 344 { 345 return permissions.elements(); 346 } 347 } 348} 349