jdk/src/java.base/share/classes/java/io/FilePermission.java
changeset 31080 00a25f4c4d44
parent 29986 97167d851fc4
child 32649 2ee9017c7597
equal deleted inserted replaced
31062:a6b5f444cb68 31080:00a25f4c4d44
     1 /*
     1 /*
     2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    25 
    25 
    26 package java.io;
    26 package java.io;
    27 
    27 
    28 import java.security.*;
    28 import java.security.*;
    29 import java.util.Enumeration;
    29 import java.util.Enumeration;
    30 import java.util.List;
    30 import java.util.StringJoiner;
    31 import java.util.ArrayList;
       
    32 import java.util.Vector;
    31 import java.util.Vector;
    33 import java.util.Collections;
    32 import java.util.concurrent.ConcurrentHashMap;
    34 import java.util.StringJoiner;
       
    35 import sun.security.util.SecurityConstants;
    33 import sun.security.util.SecurityConstants;
    36 
    34 
    37 /**
    35 /**
    38  * This class represents access to a file or directory.  A FilePermission consists
    36  * This class represents access to a file or directory.  A FilePermission consists
    39  * of a pathname and a set of actions valid for that pathname.
    37  * of a pathname and a set of actions valid for that pathname.
   286      * <code>implies</code> method.
   284      * <code>implies</code> method.
   287      *
   285      *
   288      * @param path the pathname of the file/directory.
   286      * @param path the pathname of the file/directory.
   289      * @param mask the action mask to use.
   287      * @param mask the action mask to use.
   290      */
   288      */
   291 
       
   292     // package private for use by the FilePermissionCollection add method
   289     // package private for use by the FilePermissionCollection add method
   293     FilePermission(String path, int mask) {
   290     FilePermission(String path, int mask) {
   294         super(path);
   291         super(path);
   295         init(mask);
   292         init(mask);
   296     }
   293     }
   313      *
   310      *
   314      * @return <code>true</code> if the specified permission is not
   311      * @return <code>true</code> if the specified permission is not
   315      *                  <code>null</code> and is implied by this object,
   312      *                  <code>null</code> and is implied by this object,
   316      *                  <code>false</code> otherwise.
   313      *                  <code>false</code> otherwise.
   317      */
   314      */
       
   315     @Override
   318     public boolean implies(Permission p) {
   316     public boolean implies(Permission p) {
   319         if (!(p instanceof FilePermission))
   317         if (!(p instanceof FilePermission))
   320             return false;
   318             return false;
   321 
   319 
   322         FilePermission that = (FilePermission) p;
   320         FilePermission that = (FilePermission) p;
   385      * @param obj the object we are testing for equality with this object.
   383      * @param obj the object we are testing for equality with this object.
   386      * @return <code>true</code> if obj is a FilePermission, and has the same
   384      * @return <code>true</code> if obj is a FilePermission, and has the same
   387      *          pathname and actions as this FilePermission object,
   385      *          pathname and actions as this FilePermission object,
   388      *          <code>false</code> otherwise.
   386      *          <code>false</code> otherwise.
   389      */
   387      */
       
   388     @Override
   390     public boolean equals(Object obj) {
   389     public boolean equals(Object obj) {
   391         if (obj == this)
   390         if (obj == this)
   392             return true;
   391             return true;
   393 
   392 
   394         if (! (obj instanceof FilePermission))
   393         if (! (obj instanceof FilePermission))
   405     /**
   404     /**
   406      * Returns the hash code value for this object.
   405      * Returns the hash code value for this object.
   407      *
   406      *
   408      * @return a hash code value for this object.
   407      * @return a hash code value for this object.
   409      */
   408      */
       
   409     @Override
   410     public int hashCode() {
   410     public int hashCode() {
   411         return 0;
   411         return 0;
   412     }
   412     }
   413 
   413 
   414     /**
   414     /**
   585      * object allows both write and read actions, a call to <code>getActions</code>
   585      * object allows both write and read actions, a call to <code>getActions</code>
   586      * will return the string "read,write".
   586      * will return the string "read,write".
   587      *
   587      *
   588      * @return the canonical string representation of the actions.
   588      * @return the canonical string representation of the actions.
   589      */
   589      */
       
   590     @Override
   590     public String getActions() {
   591     public String getActions() {
   591         if (actions == null)
   592         if (actions == null)
   592             actions = getActions(this.mask);
   593             actions = getActions(this.mask);
   593 
   594 
   594         return actions;
   595         return actions;
   623      * returned by this <code>newPermissionCollection</code> method.
   624      * returned by this <code>newPermissionCollection</code> method.
   624      *
   625      *
   625      * @return a new PermissionCollection object suitable for storing
   626      * @return a new PermissionCollection object suitable for storing
   626      * FilePermissions.
   627      * FilePermissions.
   627      */
   628      */
       
   629     @Override
   628     public PermissionCollection newPermissionCollection() {
   630     public PermissionCollection newPermissionCollection() {
   629         return new FilePermissionCollection();
   631         return new FilePermissionCollection();
   630     }
   632     }
   631 
   633 
   632     /**
   634     /**
   687 
   689 
   688 final class FilePermissionCollection extends PermissionCollection
   690 final class FilePermissionCollection extends PermissionCollection
   689     implements Serializable
   691     implements Serializable
   690 {
   692 {
   691     // Not serialized; see serialization section at end of class
   693     // Not serialized; see serialization section at end of class
   692     private transient List<Permission> perms;
   694     private transient ConcurrentHashMap<String, Permission> perms;
   693 
   695 
   694     /**
   696     /**
   695      * Create an empty FilePermissionCollection object.
   697      * Create an empty FilePermissionCollection object.
   696      */
   698      */
   697     public FilePermissionCollection() {
   699     public FilePermissionCollection() {
   698         perms = new ArrayList<>();
   700         perms = new ConcurrentHashMap<>();
   699     }
   701     }
   700 
   702 
   701     /**
   703     /**
   702      * Adds a permission to the FilePermissionCollection. The key for the hash is
   704      * Adds a permission to the FilePermissionCollection. The key for the hash is
   703      * permission.path.
   705      * permission.path.
   708      *                                       FilePermission
   710      *                                       FilePermission
   709      *
   711      *
   710      * @exception SecurityException - if this FilePermissionCollection object
   712      * @exception SecurityException - if this FilePermissionCollection object
   711      *                                has been marked readonly
   713      *                                has been marked readonly
   712      */
   714      */
       
   715     @Override
   713     public void add(Permission permission) {
   716     public void add(Permission permission) {
   714         if (! (permission instanceof FilePermission))
   717         if (! (permission instanceof FilePermission))
   715             throw new IllegalArgumentException("invalid permission: "+
   718             throw new IllegalArgumentException("invalid permission: "+
   716                                                permission);
   719                                                permission);
   717         if (isReadOnly())
   720         if (isReadOnly())
   718             throw new SecurityException(
   721             throw new SecurityException(
   719                 "attempt to add a Permission to a readonly PermissionCollection");
   722                 "attempt to add a Permission to a readonly PermissionCollection");
   720 
   723 
   721         synchronized (this) {
   724         FilePermission fp = (FilePermission)permission;
   722             perms.add(permission);
   725 
   723         }
   726         // Add permission to map if it is absent, or replace with new
       
   727         // permission if applicable. NOTE: cannot use lambda for
       
   728         // remappingFunction parameter until JDK-8076596 is fixed.
       
   729         perms.merge(fp.getName(), fp,
       
   730             new java.util.function.BiFunction<>() {
       
   731                 @Override
       
   732                 public Permission apply(Permission existingVal,
       
   733                                         Permission newVal) {
       
   734                     int oldMask = ((FilePermission)existingVal).getMask();
       
   735                     int newMask = ((FilePermission)newVal).getMask();
       
   736                     if (oldMask != newMask) {
       
   737                         int effective = oldMask | newMask;
       
   738                         if (effective == newMask) {
       
   739                             return newVal;
       
   740                         }
       
   741                         if (effective != oldMask) {
       
   742                             return new FilePermission(fp.getName(), effective);
       
   743                         }
       
   744                     }
       
   745                     return existingVal;
       
   746                 }
       
   747             }
       
   748         );
   724     }
   749     }
   725 
   750 
   726     /**
   751     /**
   727      * Check and see if this set of permissions implies the permissions
   752      * Check and see if this set of permissions implies the permissions
   728      * expressed in "permission".
   753      * expressed in "permission".
   730      * @param permission the Permission object to compare
   755      * @param permission the Permission object to compare
   731      *
   756      *
   732      * @return true if "permission" is a proper subset of a permission in
   757      * @return true if "permission" is a proper subset of a permission in
   733      * the set, false if not.
   758      * the set, false if not.
   734      */
   759      */
       
   760     @Override
   735     public boolean implies(Permission permission) {
   761     public boolean implies(Permission permission) {
   736         if (! (permission instanceof FilePermission))
   762         if (! (permission instanceof FilePermission))
   737             return false;
   763             return false;
   738 
   764 
   739         FilePermission fp = (FilePermission) permission;
   765         FilePermission fperm = (FilePermission) permission;
   740 
   766 
   741         int desired = fp.getMask();
   767         int desired = fperm.getMask();
   742         int effective = 0;
   768         int effective = 0;
   743         int needed = desired;
   769         int needed = desired;
   744 
   770 
   745         synchronized (this) {
   771         for (Permission perm : perms.values()) {
   746             int len = perms.size();
   772             FilePermission fp = (FilePermission)perm;
   747             for (int i = 0; i < len; i++) {
   773             if (((needed & fp.getMask()) != 0) && fp.impliesIgnoreMask(fperm)) {
   748                 FilePermission x = (FilePermission) perms.get(i);
   774                 effective |= fp.getMask();
   749                 if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(fp)) {
   775                 if ((effective & desired) == desired) {
   750                     effective |=  x.getMask();
   776                     return true;
   751                     if ((effective & desired) == desired)
       
   752                         return true;
       
   753                     needed = (desired ^ effective);
       
   754                 }
   777                 }
       
   778                 needed = (desired ^ effective);
   755             }
   779             }
   756         }
   780         }
   757         return false;
   781         return false;
   758     }
   782     }
   759 
   783 
   761      * Returns an enumeration of all the FilePermission objects in the
   785      * Returns an enumeration of all the FilePermission objects in the
   762      * container.
   786      * container.
   763      *
   787      *
   764      * @return an enumeration of all the FilePermission objects.
   788      * @return an enumeration of all the FilePermission objects.
   765      */
   789      */
       
   790     @Override
   766     public Enumeration<Permission> elements() {
   791     public Enumeration<Permission> elements() {
   767         // Convert Iterator into Enumeration
   792         return perms.elements();
   768         synchronized (this) {
       
   769             return Collections.enumeration(perms);
       
   770         }
       
   771     }
   793     }
   772 
   794 
   773     private static final long serialVersionUID = 2202956749081564585L;
   795     private static final long serialVersionUID = 2202956749081564585L;
   774 
   796 
   775     // Need to maintain serialization interoperability with earlier releases,
   797     // Need to maintain serialization interoperability with earlier releases,
   793      */
   815      */
   794     private void writeObject(ObjectOutputStream out) throws IOException {
   816     private void writeObject(ObjectOutputStream out) throws IOException {
   795         // Don't call out.defaultWriteObject()
   817         // Don't call out.defaultWriteObject()
   796 
   818 
   797         // Write out Vector
   819         // Write out Vector
   798         Vector<Permission> permissions = new Vector<>(perms.size());
   820         Vector<Permission> permissions = new Vector<>(perms.values());
   799         synchronized (this) {
       
   800             permissions.addAll(perms);
       
   801         }
       
   802 
   821 
   803         ObjectOutputStream.PutField pfields = out.putFields();
   822         ObjectOutputStream.PutField pfields = out.putFields();
   804         pfields.put("permissions", permissions);
   823         pfields.put("permissions", permissions);
   805         out.writeFields();
   824         out.writeFields();
   806     }
   825     }
   817         ObjectInputStream.GetField gfields = in.readFields();
   836         ObjectInputStream.GetField gfields = in.readFields();
   818 
   837 
   819         // Get the one we want
   838         // Get the one we want
   820         @SuppressWarnings("unchecked")
   839         @SuppressWarnings("unchecked")
   821         Vector<Permission> permissions = (Vector<Permission>)gfields.get("permissions", null);
   840         Vector<Permission> permissions = (Vector<Permission>)gfields.get("permissions", null);
   822         perms = new ArrayList<>(permissions.size());
   841         perms = new ConcurrentHashMap<>(permissions.size());
   823         perms.addAll(permissions);
   842         for (Permission perm : permissions) {
       
   843             perms.put(perm.getName(), perm);
       
   844         }
   824     }
   845     }
   825 }
   846 }