Save This Page
Home » openjdk-7 » java » security » [javadoc | source]
    1   /*
    2    * Copyright (c) 1997, 2011, 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 java.security;
   27   
   28   import java.security;
   29   import java.util.Enumeration;
   30   import java.util.Map;
   31   import java.util.HashMap;
   32   import java.util.Hashtable;
   33   import java.util.Collections;
   34   import java.io.ObjectStreamField;
   35   import java.io.ObjectOutputStream;
   36   import java.io.ObjectInputStream;
   37   import java.io.IOException;
   38   
   39   /**
   40    * The BasicPermission class extends the Permission class, and
   41    * can be used as the base class for permissions that want to
   42    * follow the same naming convention as BasicPermission.
   43    * <P>
   44    * The name for a BasicPermission is the name of the given permission
   45    * (for example, "exit",
   46    * "setFactory", "print.queueJob", etc). The naming
   47    * convention follows the  hierarchical property naming convention.
   48    * An asterisk may appear by itself, or if immediately preceded by a "."
   49    * may appear at the end of the name, to signify a wildcard match.
   50    * For example, "*" and "java.*" are valid, while "*java", "a*b",
   51    * and "java*" are not valid.
   52    * <P>
   53    * The action string (inherited from Permission) is unused.
   54    * Thus, BasicPermission is commonly used as the base class for
   55    * "named" permissions
   56    * (ones that contain a name but no actions list; you either have the
   57    * named permission or you don't.)
   58    * Subclasses may implement actions on top of BasicPermission,
   59    * if desired.
   60    * <p>
   61    * <P>
   62    * @see java.security.Permission
   63    * @see java.security.Permissions
   64    * @see java.security.PermissionCollection
   65    * @see java.lang.SecurityManager
   66    *
   67    * @author Marianne Mueller
   68    * @author Roland Schemers
   69    */
   70   
   71   public abstract class BasicPermission extends Permission
   72   implements java.io.Serializable
   73   {
   74   
   75       private static final long serialVersionUID = 6279438298436773498L;
   76   
   77       // does this permission have a wildcard at the end?
   78       private transient boolean wildcard;
   79   
   80       // the name without the wildcard on the end
   81       private transient String path;
   82   
   83       // is this permission the old-style exitVM permission (pre JDK 1.6)?
   84       private transient boolean exitVM;
   85   
   86       /**
   87        * initialize a BasicPermission object. Common to all constructors.
   88        *
   89        */
   90       private void init(String name)
   91       {
   92           if (name == null)
   93               throw new NullPointerException("name can't be null");
   94   
   95           int len = name.length();
   96   
   97           if (len == 0) {
   98               throw new IllegalArgumentException("name can't be empty");
   99           }
  100   
  101           char last = name.charAt(len - 1);
  102   
  103           // Is wildcard or ends with ".*"?
  104           if (last == '*' && (len == 1 || name.charAt(len - 2) == '.')) {
  105               wildcard = true;
  106               if (len == 1) {
  107                   path = "";
  108               } else {
  109                   path = name.substring(0, len - 1);
  110               }
  111           } else {
  112               if (name.equals("exitVM")) {
  113                   wildcard = true;
  114                   path = "exitVM.";
  115                   exitVM = true;
  116               } else {
  117                   path = name;
  118               }
  119           }
  120       }
  121   
  122       /**
  123        * Creates a new BasicPermission with the specified name.
  124        * Name is the symbolic name of the permission, such as
  125        * "setFactory",
  126        * "print.queueJob", or "topLevelWindow", etc.
  127        *
  128        * @param name the name of the BasicPermission.
  129        *
  130        * @throws NullPointerException if <code>name</code> is <code>null</code>.
  131        * @throws IllegalArgumentException if <code>name</code> is empty.
  132        */
  133   
  134       public BasicPermission(String name)
  135       {
  136           super(name);
  137           init(name);
  138       }
  139   
  140   
  141       /**
  142        * Creates a new BasicPermission object with the specified name.
  143        * The name is the symbolic name of the BasicPermission, and the
  144        * actions String is currently unused.
  145        *
  146        * @param name the name of the BasicPermission.
  147        * @param actions ignored.
  148        *
  149        * @throws NullPointerException if <code>name</code> is <code>null</code>.
  150        * @throws IllegalArgumentException if <code>name</code> is empty.
  151        */
  152       public BasicPermission(String name, String actions)
  153       {
  154           super(name);
  155           init(name);
  156       }
  157   
  158       /**
  159        * Checks if the specified permission is "implied" by
  160        * this object.
  161        * <P>
  162        * More specifically, this method returns true if:<p>
  163        * <ul>
  164        * <li> <i>p</i>'s class is the same as this object's class, and<p>
  165        * <li> <i>p</i>'s name equals or (in the case of wildcards)
  166        *      is implied by this object's
  167        *      name. For example, "a.b.*" implies "a.b.c".
  168        * </ul>
  169        *
  170        * @param p the permission to check against.
  171        *
  172        * @return true if the passed permission is equal to or
  173        * implied by this permission, false otherwise.
  174        */
  175       public boolean implies(Permission p) {
  176           if ((p == null) || (p.getClass() != getClass()))
  177               return false;
  178   
  179           BasicPermission that = (BasicPermission) p;
  180   
  181           if (this.wildcard) {
  182               if (that.wildcard) {
  183                   // one wildcard can imply another
  184                   return that.path.startsWith(path);
  185               } else {
  186                   // make sure ap.path is longer so a.b.* doesn't imply a.b
  187                   return (that.path.length() > this.path.length()) &&
  188                       that.path.startsWith(this.path);
  189               }
  190           } else {
  191               if (that.wildcard) {
  192                   // a non-wildcard can't imply a wildcard
  193                   return false;
  194               }
  195               else {
  196                   return this.path.equals(that.path);
  197               }
  198           }
  199       }
  200   
  201       /**
  202        * Checks two BasicPermission objects for equality.
  203        * Checks that <i>obj</i>'s class is the same as this object's class
  204        * and has the same name as this object.
  205        * <P>
  206        * @param obj the object we are testing for equality with this object.
  207        * @return true if <i>obj</i>'s class is the same as this object's class
  208        *  and has the same name as this BasicPermission object, false otherwise.
  209        */
  210       public boolean equals(Object obj) {
  211           if (obj == this)
  212               return true;
  213   
  214           if ((obj == null) || (obj.getClass() != getClass()))
  215               return false;
  216   
  217           BasicPermission bp = (BasicPermission) obj;
  218   
  219           return getName().equals(bp.getName());
  220       }
  221   
  222   
  223       /**
  224        * Returns the hash code value for this object.
  225        * The hash code used is the hash code of the name, that is,
  226        * <code>getName().hashCode()</code>, where <code>getName</code> is
  227        * from the Permission superclass.
  228        *
  229        * @return a hash code value for this object.
  230        */
  231       public int hashCode() {
  232           return this.getName().hashCode();
  233       }
  234   
  235       /**
  236        * Returns the canonical string representation of the actions,
  237        * which currently is the empty string "", since there are no actions for
  238        * a BasicPermission.
  239        *
  240        * @return the empty string "".
  241        */
  242       public String getActions()
  243       {
  244           return "";
  245       }
  246   
  247       /**
  248        * Returns a new PermissionCollection object for storing BasicPermission
  249        * objects.
  250        *
  251        * <p>BasicPermission objects must be stored in a manner that allows them
  252        * to be inserted in any order, but that also enables the
  253        * PermissionCollection <code>implies</code> method
  254        * to be implemented in an efficient (and consistent) manner.
  255        *
  256        * @return a new PermissionCollection object suitable for
  257        * storing BasicPermissions.
  258        */
  259       public PermissionCollection newPermissionCollection() {
  260           return new BasicPermissionCollection(this.getClass());
  261       }
  262   
  263       /**
  264        * readObject is called to restore the state of the BasicPermission from
  265        * a stream.
  266        */
  267       private void readObject(ObjectInputStream s)
  268            throws IOException, ClassNotFoundException
  269       {
  270           s.defaultReadObject();
  271           // init is called to initialize the rest of the values.
  272           init(getName());
  273       }
  274   
  275       /**
  276        * Returns the canonical name of this BasicPermission.
  277        * All internal invocations of getName should invoke this method, so
  278        * that the pre-JDK 1.6 "exitVM" and current "exitVM.*" permission are
  279        * equivalent in equals/hashCode methods.
  280        *
  281        * @return the canonical name of this BasicPermission.
  282        */
  283       final String getCanonicalName() {
  284           return exitVM ? "exitVM.*" : getName();
  285       }
  286   }
  287   
  288   /**
  289    * A BasicPermissionCollection stores a collection
  290    * of BasicPermission permissions. BasicPermission objects
  291    * must be stored in a manner that allows them to be inserted in any
  292    * order, but enable the implies function to evaluate the implies
  293    * method in an efficient (and consistent) manner.
  294    *
  295    * A BasicPermissionCollection handles comparing a permission like "a.b.c.d.e"
  296    * with a Permission such as "a.b.*", or "*".
  297    *
  298    * @see java.security.Permission
  299    * @see java.security.Permissions
  300    * @see java.security.PermissionsImpl
  301    *
  302    *
  303    * @author Roland Schemers
  304    *
  305    * @serial include
  306    */
  307   
  308   final class BasicPermissionCollection
  309   extends PermissionCollection
  310   implements java.io.Serializable
  311   {
  312   
  313       private static final long serialVersionUID = 739301742472979399L;
  314   
  315       /**
  316         * Key is name, value is permission. All permission objects in
  317         * collection must be of the same type.
  318         * Not serialized; see serialization section at end of class.
  319         */
  320       private transient Map<String, Permission> perms;
  321   
  322       /**
  323        * This is set to <code>true</code> if this BasicPermissionCollection
  324        * contains a BasicPermission with '*' as its permission name.
  325        *
  326        * @see #serialPersistentFields
  327        */
  328       private boolean all_allowed;
  329   
  330       /**
  331        * The class to which all BasicPermissions in this
  332        * BasicPermissionCollection belongs.
  333        *
  334        * @see #serialPersistentFields
  335        */
  336       private Class permClass;
  337   
  338       /**
  339        * Create an empty BasicPermissionCollection object.
  340        *
  341        */
  342   
  343       public BasicPermissionCollection(Class clazz) {
  344           perms = new HashMap<String, Permission>(11);
  345           all_allowed = false;
  346           permClass = clazz;
  347       }
  348   
  349       /**
  350        * Adds a permission to the BasicPermissions. The key for the hash is
  351        * permission.path.
  352        *
  353        * @param permission the Permission object to add.
  354        *
  355        * @exception IllegalArgumentException - if the permission is not a
  356        *                                       BasicPermission, or if
  357        *                                       the permission is not of the
  358        *                                       same Class as the other
  359        *                                       permissions in this collection.
  360        *
  361        * @exception SecurityException - if this BasicPermissionCollection object
  362        *                                has been marked readonly
  363        */
  364   
  365       public void add(Permission permission)
  366       {
  367           if (! (permission instanceof BasicPermission))
  368               throw new IllegalArgumentException("invalid permission: "+
  369                                                  permission);
  370           if (isReadOnly())
  371               throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection");
  372   
  373           BasicPermission bp = (BasicPermission) permission;
  374   
  375           // make sure we only add new BasicPermissions of the same class
  376           // Also check null for compatibility with deserialized form from
  377           // previous versions.
  378           if (permClass == null) {
  379               // adding first permission
  380               permClass = bp.getClass();
  381           } else {
  382               if (bp.getClass() != permClass)
  383                   throw new IllegalArgumentException("invalid permission: " +
  384                                                   permission);
  385           }
  386   
  387           synchronized (this) {
  388               perms.put(bp.getCanonicalName(), permission);
  389           }
  390   
  391           // No sync on all_allowed; staleness OK
  392           if (!all_allowed) {
  393               if (bp.getCanonicalName().equals("*"))
  394                   all_allowed = true;
  395           }
  396       }
  397   
  398       /**
  399        * Check and see if this set of permissions implies the permissions
  400        * expressed in "permission".
  401        *
  402        * @param p the Permission object to compare
  403        *
  404        * @return true if "permission" is a proper subset of a permission in
  405        * the set, false if not.
  406        */
  407   
  408       public boolean implies(Permission permission)
  409       {
  410           if (! (permission instanceof BasicPermission))
  411                   return false;
  412   
  413           BasicPermission bp = (BasicPermission) permission;
  414   
  415           // random subclasses of BasicPermission do not imply each other
  416           if (bp.getClass() != permClass)
  417               return false;
  418   
  419           // short circuit if the "*" Permission was added
  420           if (all_allowed)
  421               return true;
  422   
  423           // strategy:
  424           // Check for full match first. Then work our way up the
  425           // path looking for matches on a.b..*
  426   
  427           String path = bp.getCanonicalName();
  428           //System.out.println("check "+path);
  429   
  430           Permission x;
  431   
  432           synchronized (this) {
  433               x = perms.get(path);
  434           }
  435   
  436           if (x != null) {
  437               // we have a direct hit!
  438               return x.implies(permission);
  439           }
  440   
  441           // work our way up the tree...
  442           int last, offset;
  443   
  444           offset = path.length()-1;
  445   
  446           while ((last = path.lastIndexOf(".", offset)) != -1) {
  447   
  448               path = path.substring(0, last+1) + "*";
  449               //System.out.println("check "+path);
  450   
  451               synchronized (this) {
  452                   x = perms.get(path);
  453               }
  454   
  455               if (x != null) {
  456                   return x.implies(permission);
  457               }
  458               offset = last -1;
  459           }
  460   
  461           // we don't have to check for "*" as it was already checked
  462           // at the top (all_allowed), so we just return false
  463           return false;
  464       }
  465   
  466       /**
  467        * Returns an enumeration of all the BasicPermission objects in the
  468        * container.
  469        *
  470        * @return an enumeration of all the BasicPermission objects.
  471        */
  472   
  473       public Enumeration<Permission> elements() {
  474           // Convert Iterator of Map values into an Enumeration
  475           synchronized (this) {
  476               return Collections.enumeration(perms.values());
  477           }
  478       }
  479   
  480       // Need to maintain serialization interoperability with earlier releases,
  481       // which had the serializable field:
  482       //
  483       // @serial the Hashtable is indexed by the BasicPermission name
  484       //
  485       // private Hashtable permissions;
  486       /**
  487        * @serialField permissions java.util.Hashtable
  488        *    The BasicPermissions in this BasicPermissionCollection.
  489        *    All BasicPermissions in the collection must belong to the same class.
  490        *    The Hashtable is indexed by the BasicPermission name; the value
  491        *    of the Hashtable entry is the permission.
  492        * @serialField all_allowed boolean
  493        *   This is set to <code>true</code> if this BasicPermissionCollection
  494        *   contains a BasicPermission with '*' as its permission name.
  495        * @serialField permClass java.lang.Class
  496        *   The class to which all BasicPermissions in this
  497        *   BasicPermissionCollection belongs.
  498        */
  499       private static final ObjectStreamField[] serialPersistentFields = {
  500           new ObjectStreamField("permissions", Hashtable.class),
  501           new ObjectStreamField("all_allowed", Boolean.TYPE),
  502           new ObjectStreamField("permClass", Class.class),
  503       };
  504   
  505       /**
  506        * @serialData Default fields.
  507        */
  508       /*
  509        * Writes the contents of the perms field out as a Hashtable for
  510        * serialization compatibility with earlier releases. all_allowed
  511        * and permClass unchanged.
  512        */
  513       private void writeObject(ObjectOutputStream out) throws IOException {
  514           // Don't call out.defaultWriteObject()
  515   
  516           // Copy perms into a Hashtable
  517           Hashtable<String, Permission> permissions =
  518                   new Hashtable<>(perms.size()*2);
  519   
  520           synchronized (this) {
  521               permissions.putAll(perms);
  522           }
  523   
  524           // Write out serializable fields
  525           ObjectOutputStream.PutField pfields = out.putFields();
  526           pfields.put("all_allowed", all_allowed);
  527           pfields.put("permissions", permissions);
  528           pfields.put("permClass", permClass);
  529           out.writeFields();
  530       }
  531   
  532       /**
  533        * readObject is called to restore the state of the
  534        * BasicPermissionCollection from a stream.
  535        */
  536       private void readObject(java.io.ObjectInputStream in)
  537            throws IOException, ClassNotFoundException
  538       {
  539           // Don't call defaultReadObject()
  540   
  541           // Read in serialized fields
  542           ObjectInputStream.GetField gfields = in.readFields();
  543   
  544           // Get permissions
  545           Hashtable<String, Permission> permissions =
  546                   (Hashtable<String, Permission>)gfields.get("permissions", null);
  547           perms = new HashMap<String, Permission>(permissions.size()*2);
  548           perms.putAll(permissions);
  549   
  550           // Get all_allowed
  551           all_allowed = gfields.get("all_allowed", false);
  552   
  553           // Get permClass
  554           permClass = (Class) gfields.get("permClass", null);
  555   
  556           if (permClass == null) {
  557               // set permClass
  558               Enumeration<Permission> e = permissions.elements();
  559               if (e.hasMoreElements()) {
  560                   Permission p = e.nextElement();
  561                   permClass = p.getClass();
  562               }
  563           }
  564       }
  565   }

Save This Page
Home » openjdk-7 » java » security » [javadoc | source]