Frames | No Frames |
1: /* MBeanServerPermission.java -- Permissions controlling server creation. 2: Copyright (C) 2006 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 javax.management; 39: 40: import java.security.BasicPermission; 41: import java.security.Permission; 42: import java.security.PermissionCollection; 43: 44: import java.util.Enumeration; 45: import java.util.NoSuchElementException; 46: 47: /** 48: * <p> 49: * Represents the permissions required to perform 50: * operations provided by the {@link MBeanServerFactory}. 51: * As with all {@link java.security.Permission} objects, an 52: * instance of this class either represents a permission 53: * already held or one that is required to access a 54: * particular service. In the case of {@link MBeanServerPermission}s, 55: * implication checks are made using an instance of this class 56: * when a user requests an operation from the factory, and a 57: * {@link SecurityManager} is in place. 58: * </p> 59: * <p> 60: * The permission is defined by its name, which may be 61: * either a <code>'*'</code> (to allow all) or one or 62: * more of the following, separated by a <code>','</code>: 63: * </p> 64: * <ul> 65: * <li><code>createMBeanServer</code> -- allows a registered 66: * instance of a server to be obtained from the factory.</li> 67: * <li><code>findMBeanServer</code> -- allows all or one 68: * particular server instance to be retrieved from the factory.</li> 69: * <li><code>newMBeanServer</code> -- allows an unregistered 70: * instance of a server to be obtained from the factory.</li> 71: * <li><code>releaseMBeanServer</code> -- allows a reference to 72: * a server instance to be removed from the factory.</li> 73: * </ul> 74: * <p> 75: * The names may be surrounded by arbitrary amounts of whitespace. 76: * <code>createMBeanServer</code> implies <code>newMBeanServer</code>. 77: * </p> 78: * 79: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 80: * @since 1.5 81: */ 82: public class MBeanServerPermission 83: extends BasicPermission 84: { 85: 86: /** 87: * Compatible with JDK 1.5 88: */ 89: private static final long serialVersionUID = -5661980843569388590L; 90: 91: /** 92: * <p> 93: * Constructs a new {@link MBeanServerPermission} with 94: * the given name. The name must not be <code>null</code> 95: * and must be equal to either <code>"*"</code> or a 96: * comma-separated list of valid permissions. The four 97: * valid constraints are: 98: * </p> 99: * <ol> 100: * <li><code>createMBeanServer</code></li> 101: * <li><code>findMBeanServer</code></li> 102: * <li><code>newMBeanServer</code></li> 103: * <li><code>releaseMBeanServer</code></li> 104: * </ol> 105: * <p> 106: * Calling this constructor is equivalent to calling 107: * <code>MBeanPermission(name, null)</code>. 108: * </p> 109: * 110: * @param name the name of this permission. 111: * @throws NullPointerException if <code>name</code> 112: * is <code>null</code>. 113: * @throws IllegalArgumentException if <code>name</code> 114: * is not either equal to 115: * <code>"*"</code> or forms 116: * a comma-separated list of 117: * valid constraints. 118: * @see #MBeanServerPermission(String,String) 119: */ 120: public MBeanServerPermission(String name) 121: { 122: this(name, null); 123: } 124: 125: /** 126: * <p> 127: * Constructs a new {@link MBeanServerPermission} with 128: * the given name and actions. The actions are unused, 129: * and must be either <code>null</code> or the empty 130: * string. The name must not be <code>null</code> 131: * and must be equal to either <code>"*"</code> or a 132: * comma-separated list of valid permissions. The four 133: * valid constraints are: 134: * </p> 135: * <ol> 136: * <li><code>createMBeanServer</code></li> 137: * <li><code>findMBeanServer</code></li> 138: * <li><code>newMBeanServer</code></li> 139: * <li><code>releaseMBeanServer</code></li> 140: * </ol> 141: * <p> 142: * Calling this constructor is equivalent to calling 143: * <code>MBeanPermission(name, null)</code>. 144: * </p> 145: * 146: * @param name the name of this permission. 147: * @throws NullPointerException if <code>name</code> 148: * is <code>null</code>. 149: * @throws IllegalArgumentException if <code>name</code> 150: * is not either equal to 151: * <code>"*"</code> or forms 152: * a comma-separated list of 153: * valid constraints, or if 154: * <code>actions</code> is not 155: * <code>null</code> or the 156: * empty string. 157: * @see #MBeanServerPermission(String,String) 158: */ 159: public MBeanServerPermission(String name, String actions) 160: { 161: super(checkName(name), actions); 162: if (actions != null && actions.length() > 0) 163: throw new IllegalArgumentException("The supplied action list " + 164: "was not equal to null or the " + 165: "empty string."); 166: } 167: 168: /** 169: * Returns true if the given object is also an {@link MBeanServerPermission} 170: * with the same name. 171: * 172: * @param obj the object to compare with this one. 173: * @return true if the object is an {@link MBeanPermission} 174: * with the same name. 175: */ 176: public boolean equals(Object obj) 177: { 178: if (obj instanceof MBeanServerPermission) 179: { 180: MBeanServerPermission o = (MBeanServerPermission) obj; 181: return o.getName().equals(getName()); 182: } 183: return false; 184: } 185: 186: /** 187: * Returns a unique hash code for this permission. 188: * This is simply the hashcode of {@link BasicPermission#getName()}. 189: * 190: * @return the hashcode of this permission. 191: */ 192: public int hashCode() 193: { 194: return getName().hashCode(); 195: } 196: 197: /** 198: * Returns true if this {@link MBeanServerPermission} implies 199: * the given permission. This occurs if the given permission 200: * is also an {@link MBeanServerPermission} and its target names 201: * are a subset of the target names of this permission. Note that 202: * the name <code>createMBeanServer</code> implies 203: * <code>newMBeanServer</code>. 204: * 205: * @param p the permission to check for implication. 206: * @return true if this permission implies <code>p</code>. 207: */ 208: public boolean implies(Permission p) 209: { 210: if (p instanceof MBeanServerPermission) 211: { 212: if (getName().equals("*")) 213: return true; 214: MBeanServerPermission msp = (MBeanServerPermission) p; 215: String[] thisCaps = getName().split(","); 216: String[] mspCaps = msp.getName().split(","); 217: for (int a = 0; a < mspCaps.length; ++a) 218: { 219: boolean found = false; 220: String mc = mspCaps[a].trim(); 221: for (int b = 0; b < thisCaps.length; ++b) 222: { 223: String tc = thisCaps[b].trim(); 224: if (tc.equals(mc)) 225: found = true; 226: if (tc.equals("createMBeanServer") && 227: mc.equals("newMBeanServer")) 228: found = true; 229: } 230: if (!found) 231: return false; 232: } 233: return true; 234: } 235: return false; 236: } 237: 238: /** 239: * Returns a {@link PermissionCollection} which stores 240: * a series of {@link MBeanServerPermission}s as the union 241: * of their capabilities. 242: * 243: * @return a collection for {@link MBeanServerPermission}s. 244: */ 245: public PermissionCollection newPermissionCollection() 246: { 247: return new MBeanServerPermissionCollection(); 248: } 249: 250: /** 251: * A collection of {@link MBeanServerPermission}s, stored 252: * as a single permission with the union of the capabilities 253: * as its capabilities. 254: * 255: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 256: * @since 1.5 257: */ 258: private class MBeanServerPermissionCollection 259: extends PermissionCollection 260: { 261: 262: /** 263: * Compatible with JDK 1.5 264: */ 265: private static final long serialVersionUID = -5661980843569388590L; 266: 267: /** 268: * The collected permission. This is <code>null</code> or 269: * the union of the permissions held by all the collected 270: * permissions. 271: */ 272: private MBeanServerPermission collectionPermission; 273: 274: /** 275: * Adds a new permission by unifying it with the existing 276: * collection permission. 277: * 278: * @param p the permission to add. 279: * @throws SecurityException if the collection is read only. 280: * @see #isReadOnly() 281: * @see #setReadOnly(boolean) 282: */ 283: @Override 284: public void add(Permission p) 285: { 286: if (isReadOnly()) 287: throw new SecurityException("This collection is read only."); 288: if (p instanceof MBeanServerPermission) 289: { 290: MBeanServerPermission msp = (MBeanServerPermission) p; 291: if (collectionPermission == null) 292: collectionPermission = msp; 293: else 294: { 295: String finalString = collectionPermission.getName(); 296: String[] cp = finalString.split(","); 297: String[] np = msp.getName().split(","); 298: int createms = finalString.indexOf("createMBeanServer"); 299: int newms = finalString.indexOf("newMBeanServer"); 300: for (int a = 0; a < np.length; ++a) 301: { 302: boolean found = false; 303: String nps = np[a].trim(); 304: for (int b = 0; b < cp.length; ++b) 305: { 306: String cps = cp[b].trim(); 307: if (cps.equals(nps)) 308: found = true; 309: if (nps.equals("newMBeanServer") 310: && createms != -1) 311: found = true; 312: if (nps.equals("createMBeanServer") 313: && newms != -1) 314: finalString = 315: finalString.replace("newMBeanServer", 316: "createMBeanServer"); 317: } 318: if (!found) 319: finalString += "," + nps; 320: } 321: collectionPermission = 322: new MBeanServerPermission(finalString); 323: } 324: } 325: } 326: 327: /** 328: * Returns an enumeration over the single permission. 329: * 330: * @return an enumeration over the collection permission. 331: */ 332: @Override 333: public Enumeration<Permission> elements() 334: { 335: return new 336: MBeanServerPermissionEnumeration(collectionPermission); 337: } 338: 339: /** 340: * Provides an enumeration over a comma-separated list 341: * of capabilities. 342: * 343: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 344: * @since 1.5 345: */ 346: private class MBeanServerPermissionEnumeration 347: implements Enumeration<Permission> 348: { 349: 350: /** 351: * The collected permission. 352: */ 353: private MBeanServerPermission p; 354: 355: /** 356: * True if we have returned the permission. 357: */ 358: private boolean done; 359: 360: /** 361: * Constructs a new {@link MBeanServerPermissionEnumeration} 362: * using the given collected permission. 363: * 364: * @param p the collected permission. 365: */ 366: public MBeanServerPermissionEnumeration(MBeanServerPermission p) 367: { 368: this.p = p; 369: done = false; 370: } 371: 372: /** 373: * Returns true if there are more capabilities to return. 374: * 375: * @return true if there are more capabilities available. 376: */ 377: public boolean hasMoreElements() 378: { 379: return !done; 380: } 381: 382: /** 383: * Returns the next capability. 384: * 385: * @return the next capability. 386: */ 387: public Permission nextElement() 388: { 389: if (hasMoreElements()) 390: { 391: done = true; 392: return p; 393: } 394: else 395: throw new NoSuchElementException("No more elements are available."); 396: } 397: 398: } 399: 400: /** 401: * Returns true if the collected {@link MBeanServerPermission} 402: * implies the given permission. This occurs if the given permission 403: * is also an {@link MBeanServerPermission} and its target names 404: * are a subset of the target names of this permission. Note that 405: * the name <code>createMBeanServer</code> implies 406: * <code>newMBeanServer</code>. 407: * 408: * @param p the permission to check for implication. 409: * @return true if this permission implies <code>p</code>. 410: */ 411: @Override 412: public boolean implies(Permission p) 413: { 414: return collectionPermission.implies(p); 415: } 416: } 417: 418: /** 419: * Checks the name is valid, including removing 420: * the <code>newMBeanServer</code> permission when 421: * <code>createMBeanServer</code> is present. 422: * 423: * @param name the name to check. 424: * @throws NullPointerException if <code>name</code> 425: * is <code>null</code>. 426: * @throws IllegalArgumentException if <code>name</code> 427: * is not either equal to 428: * <code>"*"</code> or forms 429: * a comma-separated list of 430: * valid constraints. 431: */ 432: private static String checkName(String name) 433: { 434: if (!(name.equals("*"))) 435: { 436: String[] constraints = name.split(","); 437: name = ""; 438: boolean seenCreate = false; 439: boolean seenNew = false; 440: boolean start = true; 441: for (int a = 0; a < constraints.length; ++a) 442: { 443: String next = constraints[a].trim(); 444: if (!(next.equals("createMBeanServer") || 445: next.equals("findMBeanServer") || 446: next.equals("newMBeanServer") || 447: next.equals("releaseMBeanServer"))) 448: throw new IllegalArgumentException("An invalid constraint, " + 449: next + ", was specified."); 450: if (next.equals("newMBeanServer")) 451: seenNew = true; 452: else if (next.equals("createMBeanServer")) 453: seenCreate = true; 454: else 455: { 456: if (!start) 457: name += ","; 458: name += next; 459: start = false; 460: } 461: } 462: if (seenNew && !seenCreate) 463: name += (start ? "" : ",") + "newMBeanServer"; 464: else if (seenCreate) 465: name += (start ? "" : ",") + "createMBeanServer"; 466: } 467: return name; 468: } 469: 470: }