Source for javax.management.MBeanServerPermission

   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:     public void add(Permission p)
 284:     {
 285:       if (isReadOnly())
 286:     throw new SecurityException("This collection is read only.");
 287:       if (p instanceof MBeanServerPermission)
 288:     {
 289:       MBeanServerPermission msp = (MBeanServerPermission) p;
 290:       if (collectionPermission == null)
 291:         collectionPermission = msp;
 292:       else
 293:         {
 294:           String finalString = collectionPermission.getName();
 295:           String[] cp = finalString.split(",");
 296:           String[] np = msp.getName().split(",");
 297:           int createms = finalString.indexOf("createMBeanServer");
 298:           int newms = finalString.indexOf("newMBeanServer");
 299:           for (int a = 0; a < np.length; ++a)
 300:         {
 301:           boolean found = false;
 302:           String nps = np[a].trim();
 303:           for (int b = 0; b < cp.length; ++b)
 304:             {
 305:               String cps = cp[b].trim();
 306:               if (cps.equals(nps))
 307:             found = true;
 308:               if (np.equals("newMBeanServer") 
 309:               && createms != -1)
 310:             found = true;
 311:               if (np.equals("createMBeanServer")
 312:               && newms != -1)
 313:             finalString.replace("newMBeanServer",
 314:                         "createMBeanServer");
 315:             }
 316:           if (!found)
 317:             finalString += "," + nps;
 318:         }
 319:           collectionPermission =
 320:         new MBeanServerPermission(finalString);
 321:         }
 322:     }
 323:     }
 324:     
 325:     /**
 326:      * Returns an enumeration over the single permission.
 327:      *
 328:      * @return an enumeration over the collection permission.
 329:      */
 330:     public Enumeration elements()
 331:     {
 332:       return new
 333:     MBeanServerPermissionEnumeration(collectionPermission);
 334:     }
 335: 
 336:     /**
 337:      * Provides an enumeration over a comma-separated list
 338:      * of capabilities.
 339:      *
 340:      * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 341:      * @since 1.5
 342:      */
 343:     private class MBeanServerPermissionEnumeration
 344:       implements Enumeration
 345:     {
 346: 
 347:       /**
 348:        * The collected permission.
 349:        */
 350:       private MBeanServerPermission p;
 351: 
 352:       /**
 353:        * True if we have returned the permission.
 354:        */
 355:       private boolean done;
 356: 
 357:       /**
 358:        * Constructs a new {@link MBeanServerPermissionEnumeration}
 359:        * using the given collected permission.
 360:        *
 361:        * @param p the collected permission.
 362:        */
 363:       public MBeanServerPermissionEnumeration(MBeanServerPermission p)
 364:       {
 365:     this.p = p;
 366:     done = false;
 367:       }
 368: 
 369:       /**
 370:        * Returns true if there are more capabilities to return.
 371:        *
 372:        * @return true if there are more capabilities available.
 373:        */
 374:       public boolean hasMoreElements()
 375:       {
 376:     return !done;
 377:       }
 378: 
 379:       /**
 380:        * Returns the next capability.
 381:        *
 382:        * @return the next capability.
 383:        */
 384:       public Object nextElement()
 385:       {
 386:     if (hasMoreElements())
 387:       {
 388:         done = true;
 389:         return p;
 390:       }
 391:     else
 392:       throw new NoSuchElementException("No more elements are available.");
 393:       }
 394: 
 395:     }
 396: 
 397:     /**
 398:      * Returns true if the collected {@link MBeanServerPermission}
 399:      * implies the given permission.  This occurs if the given permission
 400:      * is also an {@link MBeanServerPermission} and its target names
 401:      * are a subset of the target names of this permission.  Note that
 402:      * the name <code>createMBeanServer</code> implies
 403:      * <code>newMBeanServer</code>.
 404:      *
 405:      * @param p the permission to check for implication.
 406:      * @return true if this permission implies <code>p</code>.
 407:      */
 408:     public boolean implies(Permission p)
 409:     {
 410:       return collectionPermission.implies(p);
 411:     }
 412:   }
 413: 
 414:   /**
 415:    * Checks the name is valid, including removing
 416:    * the <code>newMBeanServer</code> permission when
 417:    * <code>createMBeanServer</code> is present.
 418:    *
 419:    * @param name the name to check.
 420:    * @throws NullPointerException if <code>name</code>
 421:    *                              is <code>null</code>.
 422:    * @throws IllegalArgumentException if <code>name</code>
 423:    *                                  is not either equal to
 424:    *                                  <code>"*"</code> or forms
 425:    *                                  a comma-separated list of
 426:    *                                  valid constraints.
 427:    */
 428:   private static String checkName(String name)
 429:   {
 430:     if (!(name.equals("*")))
 431:       {
 432:     String[] constraints = name.split(",");
 433:     name = "";
 434:     boolean seenCreate = false;
 435:     boolean seenNew = false;
 436:     boolean start = true;
 437:     for (int a = 0; a < constraints.length; ++a)
 438:       {
 439:         String next = constraints[a].trim();
 440:         if (!(next.equals("createMBeanServer") ||
 441:           next.equals("findMBeanServer") ||
 442:           next.equals("newMBeanServer") ||
 443:           next.equals("releaseMBeanServer")))
 444:           throw new IllegalArgumentException("An invalid constraint, " +
 445:                          next + ", was specified.");
 446:         if (next.equals("newMBeanServer"))
 447:           seenNew = true;
 448:         else if (next.equals("createMBeanServer"))
 449:           seenCreate = true;
 450:         else
 451:           {
 452:         if (!start)
 453:           name += ",";
 454:         name += next;
 455:         start = false;
 456:           }
 457:       }
 458:     if (seenNew && !seenCreate)
 459:       name += (start ? "" : ",") + "newMBeanServer";
 460:     else if (seenCreate)
 461:       name += (start ? "" : ",") + "createMBeanServer";
 462:       }
 463:     return name;
 464:   }
 465: 
 466: }
 467: 
 468: 
 469: