1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.util; 19 20 import java.io.IOException; 21 import java.io.ObjectInputStream; 22 import java.io.ObjectOutputStream; 23 import java.io.ObjectStreamField; 24 import java.security.BasicPermission; 25 import java.security.Permission; 26 import java.security.PermissionCollection; 27 import org.apache.harmony.luni.util.Util; 28 29 /** 30 * {@code PropertyPermission} objects represent a permission to access system 31 * properties. 32 * <p> 33 * A permission is one of the possible permission strings like "user.name" or 34 * "java.version". It's also possible to use a wildcard to define the permission 35 * to several properties at once. For example "user.*" will define the 36 * permission for "user.home", "user.name", "user.dir", ... "*" defines the 37 * permission for all available properties. 38 * <p> 39 * There are two possible permission action types: read and write. Possible 40 * actions are "read", "write", or "read,write"/"write,read". 41 */ 42 public final class PropertyPermission extends BasicPermission { 43 private static final long serialVersionUID = 885438825399942851L; 44 45 transient private boolean read, write; 46 47 /** 48 * Constructs a new instance of this class. 49 * 50 * @param name 51 * the (possibly wildcarded) name of the property. 52 * @param actions 53 * the actions which are applicable to it. Possible actions are 54 * "read", "write", or "read,write"/"write,read". Anything else 55 * will result in an {@code IllegalArgumentException}. 56 */ 57 public PropertyPermission(String name, String actions) { 58 super(name); 59 decodeActions(actions); 60 } 61 62 private void decodeActions(String actions) { 63 StringTokenizer tokenizer = new StringTokenizer(Util.toASCIILowerCase(actions), 64 " \t\n\r,"); 65 while (tokenizer.hasMoreTokens()) { 66 String token = tokenizer.nextToken(); 67 if (token.equals("read")) { 68 read = true; 69 } else if (token.equals("write")) { 70 write = true; 71 } else { 72 throw new IllegalArgumentException(); 73 } 74 } 75 if (!read && !write) { 76 throw new IllegalArgumentException(); 77 } 78 } 79 80 /** 81 * Compares the argument to the receiver, and returns true if they represent 82 * the <em>same</em> object using a class specific comparison. In this 83 * case, the receiver must be a {@code PropertyPermission} for the same 84 * property as the argument, and must have the same actions. 85 * If {@code o} is a permission that is not a {@code PropertyPermission}, 86 * this method may throw a {@code ClassCastException}. 87 * 88 * @param o 89 * the {@code Object} to compare with this {@code Object}. 90 * @return {@code true} if the {@code Object} is the same as this {@code Object}, 91 * {@code false} if it is different from this {@code Object}. 92 * @see #hashCode 93 */ 94 @Override 95 public boolean equals(Object o) { 96 if (super.equals(o)) { 97 PropertyPermission pp = (PropertyPermission) o; 98 return read == pp.read && write == pp.write; 99 } 100 return false; 101 } 102 103 /** 104 * Returns the actions associated with the receiver. The result will be 105 * either "read", "write", or "read,write". 106 * 107 * @return the actions associated with the receiver. 108 */ 109 @Override 110 public String getActions() { 111 return read ? (write ? "read,write" : "read") : "write"; 112 } 113 114 /** 115 * Returns an integer hash code for the receiver. Any two objects which 116 * return {@code true} when passed to {@code equals} must return the same 117 * value for this method. 118 * 119 * @return the receiver's hash. 120 * @see #equals 121 */ 122 @Override 123 public int hashCode() { 124 return super.hashCode(); 125 } 126 127 /** 128 * Indicates whether the argument permission is implied by the receiver. 129 * 130 * @return boolean {@code true} if the argument permission is implied by the 131 * receiver, and {@code false} if it is not. 132 * @param permission 133 * the permission to check. 134 */ 135 @Override 136 public boolean implies(Permission permission) { 137 if (super.implies(permission)) { 138 PropertyPermission pp = (PropertyPermission) permission; 139 return (read || !pp.read) && (write || !pp.write); 140 } 141 return false; 142 } 143 144 /** 145 * Returns a new {@code PermissionCollection} for holding permissions of this class. 146 * Returns {@code null} if any {@code PermissionCollection} can be used. 147 * 148 * @return a new {@code PermissionCollection} or {@code null}. 149 * @see java.security.PermissionCollection 150 */ 151 @Override 152 public PermissionCollection newPermissionCollection() { 153 return new PropertyPermissionCollection(); 154 } 155 156 private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField( 157 "actions", String.class) }; 158 159 private void writeObject(ObjectOutputStream stream) throws IOException { 160 ObjectOutputStream.PutField fields = stream.putFields(); 161 fields.put("actions", getActions()); 162 stream.writeFields(); 163 } 164 165 private void readObject(ObjectInputStream stream) throws IOException, 166 ClassNotFoundException { 167 ObjectInputStream.GetField fields = stream.readFields(); 168 String actions = (String) fields.get("actions", ""); 169 decodeActions(actions); 170 } 171 } 172