Home » openjdk-7 » javax » management » [javadoc | source]

    1   /*
    2    * Copyright (c) 2001, 2007, 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   
   26   package javax.management;
   27   
   28   import java.io.IOException;
   29   import java.io.ObjectInputStream;
   30   import java.security.BasicPermission;
   31   import java.security.Permission;
   32   import java.security.PermissionCollection;
   33   import java.util.Collections;
   34   import java.util.Enumeration;
   35   import java.util.Set;
   36   import java.util.StringTokenizer;
   37   
   38   /** A Permission to perform actions related to MBeanServers.
   39       The <em>name</em> of the permission specifies the operation requested
   40       or granted by the permission.  For a granted permission, it can be
   41       <code>*</code> to allow all of the MBeanServer operations specified below.
   42       Otherwise, for a granted or requested permission, it must be one of the
   43       following:
   44       <dl>
   45       <dt>createMBeanServer</dt>
   46       <dd>Create a new MBeanServer object using the method
   47       {@link MBeanServerFactory#createMBeanServer()} or
   48       {@link MBeanServerFactory#createMBeanServer(java.lang.String)}.
   49       <dt>findMBeanServer</dt>
   50       <dd>Find an MBeanServer with a given name, or all MBeanServers in this
   51       JVM, using the method {@link MBeanServerFactory#findMBeanServer}.
   52       <dt>newMBeanServer</dt>
   53       <dd>Create a new MBeanServer object without keeping a reference to it,
   54       using the method {@link MBeanServerFactory#newMBeanServer()} or
   55       {@link MBeanServerFactory#newMBeanServer(java.lang.String)}.
   56       <dt>releaseMBeanServer</dt>
   57       <dd>Remove the MBeanServerFactory's reference to an MBeanServer,
   58       using the method {@link MBeanServerFactory#releaseMBeanServer}.
   59       </dl>
   60       The <em>name</em> of the permission can also denote a list of one or more
   61       comma-separated operations.  Spaces are allowed at the beginning and
   62       end of the <em>name</em> and before and after commas.
   63       <p>
   64       <code>MBeanServerPermission("createMBeanServer")</code> implies
   65       <code>MBeanServerPermission("newMBeanServer")</code>.
   66    *
   67    * @since 1.5
   68    */
   69   public class MBeanServerPermission extends BasicPermission {
   70       private static final long serialVersionUID = -5661980843569388590L;
   71   
   72       private final static int
   73           CREATE = 0,
   74           FIND = 1,
   75           NEW = 2,
   76           RELEASE = 3,
   77           N_NAMES = 4;
   78   
   79       private final static String[] names = {
   80           "createMBeanServer",
   81           "findMBeanServer",
   82           "newMBeanServer",
   83           "releaseMBeanServer",
   84       };
   85   
   86       private final static int
   87           CREATE_MASK = 1<<CREATE,
   88           FIND_MASK = 1<<FIND,
   89           NEW_MASK = 1<<NEW,
   90           RELEASE_MASK = 1<<RELEASE,
   91           ALL_MASK = CREATE_MASK|FIND_MASK|NEW_MASK|RELEASE_MASK;
   92   
   93       /*
   94        * Map from permission masks to canonical names.  This array is
   95        * filled in on demand.
   96        *
   97        * This isn't very scalable.  If we have more than five or six
   98        * permissions, we should consider doing this differently,
   99        * e.g. with a Map.
  100        */
  101       private final static String[] canonicalNames = new String[1 << N_NAMES];
  102   
  103       /*
  104        * The target names mask.  This is not private to avoid having to
  105        * generate accessor methods for accesses from the collection class.
  106        *
  107        * This mask includes implied bits.  So if it has CREATE_MASK then
  108        * it necessarily has NEW_MASK too.
  109        */
  110       transient int mask;
  111   
  112       /** <p>Create a new MBeanServerPermission with the given name.</p>
  113           <p>This constructor is equivalent to
  114           <code>MBeanServerPermission(name,null)</code>.</p>
  115           @param name the name of the granted permission.  It must
  116           respect the constraints spelt out in the description of the
  117           {@link MBeanServerPermission} class.
  118           @exception NullPointerException if the name is null.
  119           @exception IllegalArgumentException if the name is not
  120           <code>*</code> or one of the allowed names or a comma-separated
  121           list of the allowed names.
  122       */
  123       public MBeanServerPermission(String name) {
  124           this(name, null);
  125       }
  126   
  127       /** <p>Create a new MBeanServerPermission with the given name.</p>
  128           @param name the name of the granted permission.  It must
  129           respect the constraints spelt out in the description of the
  130           {@link MBeanServerPermission} class.
  131           @param actions the associated actions.  This parameter is not
  132           currently used and must be null or the empty string.
  133           @exception NullPointerException if the name is null.
  134           @exception IllegalArgumentException if the name is not
  135           <code>*</code> or one of the allowed names or a comma-separated
  136           list of the allowed names, or if <code>actions</code> is a non-null
  137           non-empty string.
  138        *
  139        * @throws NullPointerException if <code>name</code> is <code>null</code>.
  140        * @throws IllegalArgumentException if <code>name</code> is empty or
  141        * if arguments are invalid.
  142        */
  143       public MBeanServerPermission(String name, String actions) {
  144           super(getCanonicalName(parseMask(name)), actions);
  145   
  146           /* It's annoying to have to parse the name twice, but since
  147              Permission.getName() is final and since we can't access "this"
  148              until after the call to the superclass constructor, there
  149              isn't any very clean way to do this.  MBeanServerPermission
  150              objects aren't constructed very often, luckily.  */
  151           mask = parseMask(name);
  152   
  153           /* Check that actions is a null empty string */
  154           if (actions != null && actions.length() > 0)
  155               throw new IllegalArgumentException("MBeanServerPermission " +
  156                                                  "actions must be null: " +
  157                                                  actions);
  158       }
  159   
  160       MBeanServerPermission(int mask) {
  161           super(getCanonicalName(mask));
  162           this.mask = impliedMask(mask);
  163       }
  164   
  165       private void readObject(ObjectInputStream in)
  166               throws IOException, ClassNotFoundException {
  167           in.defaultReadObject();
  168           mask = parseMask(getName());
  169       }
  170   
  171       static int simplifyMask(int mask) {
  172           if ((mask & CREATE_MASK) != 0)
  173               mask &= ~NEW_MASK;
  174           return mask;
  175       }
  176   
  177       static int impliedMask(int mask) {
  178           if ((mask & CREATE_MASK) != 0)
  179               mask |= NEW_MASK;
  180           return mask;
  181       }
  182   
  183       static String getCanonicalName(int mask) {
  184           if (mask == ALL_MASK)
  185               return "*";
  186   
  187           mask = simplifyMask(mask);
  188   
  189           synchronized (canonicalNames) {
  190               if (canonicalNames[mask] == null)
  191                   canonicalNames[mask] = makeCanonicalName(mask);
  192           }
  193   
  194           return canonicalNames[mask];
  195       }
  196   
  197       private static String makeCanonicalName(int mask) {
  198           final StringBuilder buf = new StringBuilder();
  199           for (int i = 0; i < N_NAMES; i++) {
  200               if ((mask & (1<<i)) != 0) {
  201                   if (buf.length() > 0)
  202                       buf.append(',');
  203                   buf.append(names[i]);
  204               }
  205           }
  206           return buf.toString().intern();
  207           /* intern() avoids duplication when the mask has only
  208              one bit, so is equivalent to the string constants
  209              we have for the names[] array.  */
  210       }
  211   
  212       /* Convert the string into a bitmask, including bits that
  213          are implied by the permissions in the string.  */
  214       private static int parseMask(String name) {
  215           /* Check that target name is a non-null non-empty string */
  216           if (name == null) {
  217               throw new NullPointerException("MBeanServerPermission: " +
  218                                              "target name can't be null");
  219           }
  220   
  221           name = name.trim();
  222           if (name.equals("*"))
  223               return ALL_MASK;
  224   
  225           /* If the name is empty, nameIndex will barf. */
  226           if (name.indexOf(',') < 0)
  227               return impliedMask(1 << nameIndex(name.trim()));
  228   
  229           int mask = 0;
  230   
  231           StringTokenizer tok = new StringTokenizer(name, ",");
  232           while (tok.hasMoreTokens()) {
  233               String action = tok.nextToken();
  234               int i = nameIndex(action.trim());
  235               mask |= (1 << i);
  236           }
  237   
  238           return impliedMask(mask);
  239       }
  240   
  241       private static int nameIndex(String name)
  242               throws IllegalArgumentException {
  243           for (int i = 0; i < N_NAMES; i++) {
  244               if (names[i].equals(name))
  245                   return i;
  246           }
  247           final String msg =
  248               "Invalid MBeanServerPermission name: \"" + name + "\"";
  249           throw new IllegalArgumentException(msg);
  250       }
  251   
  252       public int hashCode() {
  253           return mask;
  254       }
  255   
  256       /**
  257        * <p>Checks if this MBeanServerPermission object "implies" the specified
  258        * permission.</p>
  259        *
  260        * <p>More specifically, this method returns true if:</p>
  261        *
  262        * <ul>
  263        * <li> <i>p</i> is an instance of MBeanServerPermission,</li>
  264        * <li> <i>p</i>'s target names are a subset of this object's target
  265        * names</li>
  266        * </ul>
  267        *
  268        * <p>The <code>createMBeanServer</code> permission implies the
  269        * <code>newMBeanServer</code> permission.</p>
  270        *
  271        * @param p the permission to check against.
  272        * @return true if the specified permission is implied by this object,
  273        * false if not.
  274        */
  275       public boolean implies(Permission p) {
  276           if (!(p instanceof MBeanServerPermission))
  277               return false;
  278   
  279           MBeanServerPermission that = (MBeanServerPermission) p;
  280   
  281           return ((this.mask & that.mask) == that.mask);
  282       }
  283   
  284       /**
  285        * Checks two MBeanServerPermission objects for equality. Checks that
  286        * <i>obj</i> is an MBeanServerPermission, and represents the same
  287        * list of allowable actions as this object.
  288        * <P>
  289        * @param obj the object we are testing for equality with this object.
  290        * @return true if the objects are equal.
  291        */
  292       public boolean equals(Object obj) {
  293           if (obj == this)
  294               return true;
  295   
  296           if (! (obj instanceof MBeanServerPermission))
  297               return false;
  298   
  299           MBeanServerPermission that = (MBeanServerPermission) obj;
  300   
  301           return (this.mask == that.mask);
  302       }
  303   
  304       public PermissionCollection newPermissionCollection() {
  305           return new MBeanServerPermissionCollection();
  306       }
  307   }
  308   
  309   /**
  310    * Class returned by {@link MBeanServerPermission#newPermissionCollection()}.
  311    *
  312    * @serial include
  313    */
  314   
  315   /*
  316    * Since every collection of MBSP can be represented by a single MBSP,
  317    * that is what our PermissionCollection does.  We need to define a
  318    * PermissionCollection because the one inherited from BasicPermission
  319    * doesn't know that createMBeanServer implies newMBeanServer.
  320    *
  321    * Though the serial form is defined, the TCK does not check it.  We do
  322    * not require independent implementations to duplicate it.  Even though
  323    * PermissionCollection is Serializable, instances of this class will
  324    * hardly ever be serialized, and different implementations do not
  325    * typically exchange serialized permission collections.
  326    *
  327    * If we did require that a particular form be respected here, we would
  328    * logically also have to require it for
  329    * MBeanPermission.newPermissionCollection, which would preclude an
  330    * implementation from defining a PermissionCollection there with an
  331    * optimized "implies" method.
  332    */
  333   class MBeanServerPermissionCollection extends PermissionCollection {
  334       /** @serial Null if no permissions in collection, otherwise a
  335           single permission that is the union of all permissions that
  336           have been added.  */
  337       private MBeanServerPermission collectionPermission;
  338   
  339       private static final long serialVersionUID = -5661980843569388590L;
  340   
  341       public synchronized void add(Permission permission) {
  342           if (!(permission instanceof MBeanServerPermission)) {
  343               final String msg =
  344                   "Permission not an MBeanServerPermission: " + permission;
  345               throw new IllegalArgumentException(msg);
  346           }
  347           if (isReadOnly())
  348               throw new SecurityException("Read-only permission collection");
  349           MBeanServerPermission mbsp = (MBeanServerPermission) permission;
  350           if (collectionPermission == null)
  351               collectionPermission = mbsp;
  352           else if (!collectionPermission.implies(permission)) {
  353               int newmask = collectionPermission.mask | mbsp.mask;
  354               collectionPermission = new MBeanServerPermission(newmask);
  355           }
  356       }
  357   
  358       public synchronized boolean implies(Permission permission) {
  359           return (collectionPermission != null &&
  360                   collectionPermission.implies(permission));
  361       }
  362   
  363       public synchronized Enumeration<Permission> elements() {
  364           Set<Permission> set;
  365           if (collectionPermission == null)
  366               set = Collections.emptySet();
  367           else
  368               set = Collections.singleton((Permission) collectionPermission);
  369           return Collections.enumeration(set);
  370       }
  371   }

Home » openjdk-7 » javax » management » [javadoc | source]