KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > security > BasicPermission


1 /*
2  * @(#)BasicPermission.java 1.40 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.security;
9
10 import java.security.*;
11 import java.util.Enumeration JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.Map JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.Hashtable JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.util.StringTokenizer JavaDoc;
18 import java.io.ObjectStreamField JavaDoc;
19 import java.io.ObjectOutputStream JavaDoc;
20 import java.io.ObjectInputStream JavaDoc;
21 import java.io.IOException JavaDoc;
22
23 /**
24  * The BasicPermission class extends the Permission class, and
25  * can be used as the base class for permissions that want to
26  * follow the same naming convention as BasicPermission.
27  * <P>
28  * The name for a BasicPermission is the name of the given permission
29  * (for example, "exit",
30  * "setFactory", "print.queueJob", etc). The naming
31  * convention follows the hierarchical property naming convention.
32  * An asterisk may appear by itself, or if immediately preceded by a "."
33  * may appear at the end of the name, to signify a wildcard match.
34  * For example, "*" and "java.*" are valid, while "*java", "a*b",
35  * and "java*" are not valid.
36  * <P>
37  * The action string (inherited from Permission) is unused.
38  * Thus, BasicPermission is commonly used as the base class for
39  * "named" permissions
40  * (ones that contain a name but no actions list; you either have the
41  * named permission or you don't.)
42  * Subclasses may implement actions on top of BasicPermission,
43  * if desired.
44  * <p>
45  * <P>
46  * @see java.security.Permission
47  * @see java.security.Permissions
48  * @see java.security.PermissionCollection
49  * @see java.lang.RuntimePermission
50  * @see java.security.SecurityPermission
51  * @see java.util.PropertyPermission
52  * @see java.awt.AWTPermission
53  * @see java.net.NetPermission
54  * @see java.lang.SecurityManager
55  *
56  * @version 1.40 03/12/19
57  *
58  * @author Marianne Mueller
59  * @author Roland Schemers
60  */

61
62 public abstract class BasicPermission extends Permission JavaDoc
63 implements java.io.Serializable JavaDoc
64 {
65
66     private static final long serialVersionUID = 6279438298436773498L;
67
68     // does this permission have a wildcard at the end?
69
private transient boolean wildcard;
70
71     // the name without the wildcard on the end
72
private transient String JavaDoc path;
73
74     /**
75      * initialize a BasicPermission object. Common to all constructors.
76      *
77      */

78
79     private void init(String JavaDoc name)
80     {
81     if (name == null)
82         throw new NullPointerException JavaDoc("name can't be null");
83
84     int len = name.length();
85         
86     if (len == 0) {
87         throw new IllegalArgumentException JavaDoc("name can't be empty");
88     }
89
90     char last = name.charAt(len - 1);
91
92     // Is wildcard or ends with ".*"?
93
if (last == '*' && (len == 1 || name.charAt(len - 2) == '.')) {
94         wildcard = true;
95         if (len == 1) {
96         path = "";
97         } else {
98         path = name.substring(0, len - 1);
99         }
100     } else {
101         path = name;
102     }
103     }
104
105     /**
106      * Creates a new BasicPermission with the specified name.
107      * Name is the symbolic name of the permission, such as
108      * "setFactory",
109      * "print.queueJob", or "topLevelWindow", etc.
110      *
111      * @param name the name of the BasicPermission.
112      *
113      * @throws NullPointerException if <code>name</code> is <code>null</code>.
114      * @throws IllegalArgumentException if <code>name</code> is empty.
115      */

116
117     public BasicPermission(String JavaDoc name)
118     {
119     super(name);
120     init(name);
121     }
122
123
124     /**
125      * Creates a new BasicPermission object with the specified name.
126      * The name is the symbolic name of the BasicPermission, and the
127      * actions String is currently unused.
128      *
129      * @param name the name of the BasicPermission.
130      * @param actions ignored.
131      *
132      * @throws NullPointerException if <code>name</code> is <code>null</code>.
133      * @throws IllegalArgumentException if <code>name</code> is empty.
134      */

135     public BasicPermission(String JavaDoc name, String JavaDoc actions)
136     {
137     super(name);
138     init(name);
139     }
140
141     /**
142      * Checks if the specified permission is "implied" by
143      * this object.
144      * <P>
145      * More specifically, this method returns true if:<p>
146      * <ul>
147      * <li> <i>p</i>'s class is the same as this object's class, and<p>
148      * <li> <i>p</i>'s name equals or (in the case of wildcards)
149      * is implied by this object's
150      * name. For example, "a.b.*" implies "a.b.c".
151      * </ul>
152      *
153      * @param p the permission to check against.
154      *
155      * @return true if the passed permission is equal to or
156      * implied by this permission, false otherwise.
157      */

158     public boolean implies(Permission JavaDoc p) {
159     if ((p == null) || (p.getClass() != getClass()))
160         return false;
161
162     BasicPermission JavaDoc that = (BasicPermission JavaDoc) p;
163
164     if (this.wildcard) {
165         if (that.wildcard)
166         // one wildcard can imply another
167
return that.path.startsWith(path);
168         else
169         // make sure ap.path is longer so a.b.* doesn't imply a.b
170
return (that.path.length() > this.path.length()) &&
171             that.path.startsWith(this.path);
172     } else {
173         if (that.wildcard) {
174         // a non-wildcard can't imply a wildcard
175
return false;
176         }
177         else {
178         return this.path.equals(that.path);
179         }
180     }
181     }
182
183     /**
184      * Checks two BasicPermission objects for equality.
185      * Checks that <i>obj</i>'s class is the same as this object's class
186      * and has the same name as this object.
187      * <P>
188      * @param obj the object we are testing for equality with this object.
189      * @return true if <i>obj</i> is a BasicPermission, and has the same name
190      * as this BasicPermission object, false otherwise.
191      */

192     public boolean equals(Object JavaDoc obj) {
193     if (obj == this)
194         return true;
195
196     if ((obj == null) || (obj.getClass() != getClass()))
197         return false;
198
199     BasicPermission JavaDoc bp = (BasicPermission JavaDoc) obj;
200
201     return getName().equals(bp.getName());
202     }
203
204
205     /**
206      * Returns the hash code value for this object.
207      * The hash code used is the hash code of the name, that is,
208      * <code>getName().hashCode()</code>, where <code>getName</code> is
209      * from the Permission superclass.
210      *
211      * @return a hash code value for this object.
212      */

213
214     public int hashCode() {
215     return this.getName().hashCode();
216     }
217
218     /**
219      * Returns the canonical string representation of the actions,
220      * which currently is the empty string "", since there are no actions for
221      * a BasicPermission.
222      *
223      * @return the empty string "".
224      */

225     public String JavaDoc getActions()
226     {
227     return "";
228     }
229
230     /**
231      * Returns a new PermissionCollection object for storing BasicPermission
232      * objects.
233      * <p>
234      * A BasicPermissionCollection stores a collection of
235      * BasicPermission permissions.
236      *
237      * <p>BasicPermission objects must be stored in a manner that allows them
238      * to be inserted in any order, but that also enables the
239      * PermissionCollection <code>implies</code> method
240      * to be implemented in an efficient (and consistent) manner.
241      *
242      * @return a new PermissionCollection object suitable for
243      * storing BasicPermissions.
244      */

245
246     public PermissionCollection JavaDoc newPermissionCollection() {
247     return new BasicPermissionCollection JavaDoc();
248     }
249
250     /**
251      * readObject is called to restore the state of the BasicPermission from
252      * a stream.
253      */

254     private void readObject(ObjectInputStream JavaDoc s)
255          throws IOException JavaDoc, ClassNotFoundException JavaDoc
256     {
257     s.defaultReadObject();
258     // init is called to initialize the rest of the values.
259
init(getName());
260     }
261 }
262
263 /**
264  * A BasicPermissionCollection stores a collection
265  * of BasicPermission permissions. BasicPermission objects
266  * must be stored in a manner that allows them to be inserted in any
267  * order, but enable the implies function to evaluate the implies
268  * method in an efficient (and consistent) manner.
269  *
270  * A BasicPermissionCollection handles comparing a permission like "a.b.c.d.e"
271  * with a Permission such as "a.b.*", or "*".
272  *
273  * @see java.security.Permission
274  * @see java.security.Permissions
275  * @see java.security.PermissionsImpl
276  *
277  * @version 1.40 12/19/03
278  *
279  * @author Roland Schemers
280  *
281  * @serial include
282  */

283
284 final class BasicPermissionCollection
285 extends PermissionCollection JavaDoc
286 implements java.io.Serializable JavaDoc
287 {
288
289     private static final long serialVersionUID = 739301742472979399L;
290
291     /**
292       * Key is name, value is permission. All permission objects in
293       * collection must be of the same type.
294       * Not serialized; see serialization section at end of class.
295       */

296     private transient Map JavaDoc perms;
297
298     /**
299      * This is set to <code>true</code> if this BasicPermissionCollection
300      * contains a BasicPermission with '*' as its permission name.
301      *
302      * @see #serialPersistentFields
303      */

304     private boolean all_allowed;
305
306     /**
307      * The class to which all BasicPermissions in this
308      * BasicPermissionCollection belongs.
309      *
310      * @see #serialPersistentFields
311      */

312     private Class JavaDoc permClass;
313
314     /**
315      * Create an empty BasicPermissionCollection object.
316      *
317      */

318
319     public BasicPermissionCollection() {
320     perms = new HashMap JavaDoc(11);
321     all_allowed = false;
322     }
323
324     /**
325      * Adds a permission to the BasicPermissions. The key for the hash is
326      * permission.path.
327      *
328      * @param permission the Permission object to add.
329      *
330      * @exception IllegalArgumentException - if the permission is not a
331      * BasicPermission, or if
332      * the permission is not of the
333      * same Class as the other
334      * permissions in this collection.
335      *
336      * @exception SecurityException - if this BasicPermissionCollection object
337      * has been marked readonly
338      */

339
340     public void add(Permission JavaDoc permission)
341     {
342     if (! (permission instanceof BasicPermission JavaDoc))
343         throw new IllegalArgumentException JavaDoc("invalid permission: "+
344                            permission);
345     if (isReadOnly())
346         throw new SecurityException JavaDoc("attempt to add a Permission to a readonly PermissionCollection");
347
348     BasicPermission JavaDoc bp = (BasicPermission JavaDoc) permission;
349
350     if (perms.size() == 0) {
351         // adding first permission
352
permClass = bp.getClass();
353     } else {
354         // make sure we only add new BasicPermissions of the same class
355
if (bp.getClass() != permClass)
356         throw new IllegalArgumentException JavaDoc("invalid permission: " +
357                         permission);
358     }
359
360     synchronized (this) {
361         perms.put(bp.getName(), permission);
362     }
363
364     // No sync on all_allowed; staleness OK
365
if (!all_allowed) {
366         if (bp.getName().equals("*"))
367         all_allowed = true;
368     }
369     }
370
371     /**
372      * Check and see if this set of permissions implies the permissions
373      * expressed in "permission".
374      *
375      * @param p the Permission object to compare
376      *
377      * @return true if "permission" is a proper subset of a permission in
378      * the set, false if not.
379      */

380
381     public boolean implies(Permission JavaDoc permission)
382     {
383     if (! (permission instanceof BasicPermission JavaDoc))
384         return false;
385
386     BasicPermission JavaDoc bp = (BasicPermission JavaDoc) permission;
387
388     // random subclasses of BasicPermission do not imply each other
389
if (bp.getClass() != permClass)
390         return false;
391
392     // short circuit if the "*" Permission was added
393
if (all_allowed)
394         return true;
395
396     // strategy:
397
// Check for full match first. Then work our way up the
398
// path looking for matches on a.b..*
399

400     String JavaDoc path = bp.getName();
401     //System.out.println("check "+path);
402

403     Permission JavaDoc x;
404
405     synchronized (this) {
406         x = (Permission JavaDoc) perms.get(path);
407     }
408
409     if (x != null) {
410         // we have a direct hit!
411
return x.implies(permission);
412     }
413
414     // work our way up the tree...
415
int last, offset;
416
417     offset = path.length()-1;
418
419     while ((last = path.lastIndexOf(".", offset)) != -1) {
420
421         path = path.substring(0, last+1) + "*";
422         //System.out.println("check "+path);
423

424         synchronized (this) {
425         x = (Permission JavaDoc) perms.get(path);
426         }
427
428         if (x != null) {
429         return x.implies(permission);
430         }
431         offset = last -1;
432     }
433
434     // we don't have to check for "*" as it was already checked
435
// at the top (all_allowed), so we just return false
436
return false;
437     }
438
439     /**
440      * Returns an enumeration of all the BasicPermission objects in the
441      * container.
442      *
443      * @return an enumeration of all the BasicPermission objects.
444      */

445
446     public Enumeration JavaDoc elements() {
447         // Convert Iterator of Map values into an Enumeration
448
synchronized (this) {
449         return Collections.enumeration(perms.values());
450     }
451     }
452
453     // Need to maintain serialization interoperability with earlier releases,
454
// which had the serializable field:
455
//
456
// @serial the Hashtable is indexed by the BasicPermission name
457
//
458
// private Hashtable permissions;
459
/**
460      * @serialField permissions java.util.Hashtable
461      * The BasicPermissions in this BasicPermissionCollection.
462      * All BasicPermissions in the collection must belong to the same class.
463      * The Hashtable is indexed by the BasicPermission name; the value
464      * of the Hashtable entry is the permission.
465      * @serialField all_allowed boolean
466      * This is set to <code>true</code> if this BasicPermissionCollection
467      * contains a BasicPermission with '*' as its permission name.
468      * @serialField permClass java.lang.Class
469      * The class to which all BasicPermissions in this
470      * BasicPermissionCollection belongs.
471      */

472     private static final ObjectStreamField JavaDoc[] serialPersistentFields = {
473         new ObjectStreamField JavaDoc("permissions", Hashtable JavaDoc.class),
474     new ObjectStreamField JavaDoc("all_allowed", Boolean.TYPE),
475     new ObjectStreamField JavaDoc("permClass", Class JavaDoc.class),
476     };
477
478     /**
479      * @serialData Default fields.
480      */

481     /*
482      * Writes the contents of the perms field out as a Hashtable for
483      * serialization compatibility with earlier releases. all_allowed
484      * and permClass unchanged.
485      */

486     private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
487     // Don't call out.defaultWriteObject()
488

489     // Copy perms into a Hashtable
490
Hashtable JavaDoc permissions = new Hashtable JavaDoc(perms.size()*2);
491
492     synchronized (this) {
493         permissions.putAll(perms);
494     }
495
496     // Write out serializable fields
497
ObjectOutputStream.PutField JavaDoc pfields = out.putFields();
498     pfields.put("all_allowed", all_allowed);
499         pfields.put("permissions", permissions);
500     pfields.put("permClass", permClass);
501         out.writeFields();
502     }
503
504     /**
505      * readObject is called to restore the state of the
506      * BasicPermissionCollection from a stream.
507      */

508     private void readObject(java.io.ObjectInputStream JavaDoc in)
509      throws IOException JavaDoc, ClassNotFoundException JavaDoc
510     {
511     // Don't call defaultReadObject()
512

513     // Read in serialized fields
514
ObjectInputStream.GetField JavaDoc gfields = in.readFields();
515
516     // Get permissions
517
Hashtable JavaDoc permissions = (Hashtable JavaDoc)gfields.get("permissions", null);
518     perms = new HashMap JavaDoc(permissions.size()*2);
519     perms.putAll(permissions);
520
521     // Get all_allowed
522
all_allowed = gfields.get("all_allowed", false);
523
524     // Get permClass
525
permClass = (Class JavaDoc) gfields.get("permClass", null);
526
527     if (permClass == null) {
528         // set permClass
529
Enumeration JavaDoc e = permissions.elements();
530         if (e.hasMoreElements()) {
531         Permission JavaDoc p = (Permission JavaDoc)e.nextElement();
532         permClass = p.getClass();
533         }
534     }
535     }
536 }
537
Popular Tags