KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > io > FilePermission


1 /*
2  * @(#)FilePermission.java 1.76 04/01/12
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.io;
9
10 import java.security.*;
11 import java.util.Enumeration JavaDoc;
12 import java.util.List JavaDoc;
13 import java.util.ArrayList JavaDoc;
14 import java.util.StringTokenizer JavaDoc;
15 import java.util.Vector JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.io.ObjectStreamField JavaDoc;
18 import java.io.ObjectOutputStream JavaDoc;
19 import java.io.ObjectInputStream JavaDoc;
20 import java.io.IOException JavaDoc;
21 import sun.security.util.SecurityConstants;
22
23 /**
24  * This class represents access to a file or directory. A FilePermission consists
25  * of a pathname and a set of actions valid for that pathname.
26  * <P>
27  * Pathname is the pathname of the file or directory granted the specified
28  * actions. A pathname that ends in "/*" (where "/" is
29  * the file separator character, <code>File.separatorChar</code>) indicates
30  * all the files and directories contained in that directory. A pathname
31  * that ends with "/-" indicates (recursively) all files
32  * and subdirectories contained in that directory. A pathname consisting of
33  * the special token "&lt;&lt;ALL FILES&gt;&gt;" matches <b>any</b> file.
34  * <P>
35  * Note: A pathname consisting of a single "*" indicates all the files
36  * in the current directory, while a pathname consisting of a single "-"
37  * indicates all the files in the current directory and
38  * (recursively) all files and subdirectories contained in the current
39  * directory.
40  * <P>
41  * The actions to be granted are passed to the constructor in a string containing
42  * a list of one or more comma-separated keywords. The possible keywords are
43  * "read", "write", "execute", and "delete". Their meaning is defined as follows:
44  * <P>
45  * <DL>
46  * <DT> read <DD> read permission
47  * <DT> write <DD> write permission
48  * <DT> execute
49  * <DD> execute permission. Allows <code>Runtime.exec</code> to
50  * be called. Corresponds to <code>SecurityManager.checkExec</code>.
51  * <DT> delete
52  * <DD> delete permission. Allows <code>File.delete</code> to
53  * be called. Corresponds to <code>SecurityManager.checkDelete</code>.
54  * </DL>
55  * <P>
56  * The actions string is converted to lowercase before processing.
57  * <P>
58  * Be careful when granting FilePermissions. Think about the implications
59  * of granting read and especially write access to various files and
60  * directories. The "&lt;&lt;ALL FILES>>" permission with write action is
61  * especially dangerous. This grants permission to write to the entire
62  * file system. One thing this effectively allows is replacement of the
63  * system binary, including the JVM runtime environment.
64  *
65  * <p>Please note: Code can always read a file from the same
66  * directory it's in (or a subdirectory of that directory); it does not
67  * need explicit permission to do so.
68  *
69  * @see java.security.Permission
70  * @see java.security.Permissions
71  * @see java.security.PermissionCollection
72  *
73  * @version 1.76 04/01/12
74  *
75  * @author Marianne Mueller
76  * @author Roland Schemers
77  * @since 1.2
78  *
79  * @serial exclude
80  */

81
82 public final class FilePermission extends Permission implements Serializable JavaDoc {
83
84     /**
85      * Execute action.
86      */

87     private final static int EXECUTE = 0x1;
88     /**
89      * Write action.
90      */

91     private final static int WRITE = 0x2;
92     /**
93      * Read action.
94      */

95     private final static int READ = 0x4;
96     /**
97      * Delete action.
98      */

99     private final static int DELETE = 0x8;
100
101     /**
102      * All actions (read,write,execute,delete)
103      */

104     private final static int ALL = READ|WRITE|EXECUTE|DELETE;
105     /**
106      * No actions.
107      */

108     private final static int NONE = 0x0;
109
110     // the actions mask
111
private transient int mask;
112
113     // does path indicate a directory? (wildcard or recursive)
114
private transient boolean directory;
115
116     // is it a recursive directory specification?
117
private transient boolean recursive;
118
119     /**
120      * the actions string.
121      *
122      * @serial
123      */

124     private String JavaDoc actions; // Left null as long as possible, then
125
// created and re-used in the getAction function.
126

127     // canonicalized dir path. In the case of
128
// directories, it is the name "/blah/*" or "/blah/-" without
129
// the last character (the "*" or "-").
130

131     private transient String JavaDoc cpath;
132
133     // static Strings used by init(int mask)
134
private static final char RECURSIVE_CHAR = '-';
135     private static final char WILD_CHAR = '*';
136
137 /*
138     public String toString()
139     {
140         StringBuffer sb = new StringBuffer();
141     sb.append("***\n");
142     sb.append("cpath = "+cpath+"\n");
143     sb.append("mask = "+mask+"\n");
144     sb.append("actions = "+getActions()+"\n");
145     sb.append("directory = "+directory+"\n");
146     sb.append("recursive = "+recursive+"\n");
147     sb.append("***\n");
148     return sb.toString();
149     }
150 */

151
152     private static final long serialVersionUID = 7930732926638008763L;
153
154     /**
155      * initialize a FilePermission object. Common to all constructors.
156      * Also called during de-serialization.
157      *
158      * @param mask the actions mask to use.
159      *
160      */

161     private void init(int mask)
162     {
163
164     if ((mask & ALL) != mask)
165         throw new IllegalArgumentException JavaDoc("invalid actions mask");
166
167     if (mask == NONE)
168         throw new IllegalArgumentException JavaDoc("invalid actions mask");
169
170     if ((cpath = getName()) == null)
171         throw new NullPointerException JavaDoc("name can't be null");
172
173     this.mask = mask;
174
175     if (cpath.equals("<<ALL FILES>>")) {
176         directory = true;
177         recursive = true;
178         cpath = "";
179         return;
180     }
181
182     int len = cpath.length();
183     char last = ((len > 0) ? cpath.charAt(len - 1) : 0);
184
185     if (last == RECURSIVE_CHAR &&
186         (len == 1 || cpath.charAt(len - 2) == File.separatorChar)) {
187         directory = true;
188         recursive = true;
189         cpath = cpath.substring(0, --len);
190     } else if (last == WILD_CHAR &&
191         (len == 1 || cpath.charAt(len - 2) == File.separatorChar)) {
192         directory = true;
193         //recursive = false;
194
cpath = cpath.substring(0, --len);
195     } else {
196         // overkill since they are initialized to false, but
197
// commented out here to remind us...
198
//directory = false;
199
//recursive = false;
200
}
201
202     if (len == 0) {
203         cpath = (String JavaDoc) java.security.AccessController.doPrivileged(
204                new sun.security.action.GetPropertyAction("user.dir"));
205     }
206
207     // store only the canonical cpath if possible
208

209     // need a doPrivileged block as getCanonicalPath
210
// might attempt to access user.dir to turn a relative
211
// path into an absolute path.
212
cpath = (String JavaDoc)
213         AccessController.doPrivileged(
214             new java.security.PrivilegedAction JavaDoc() {
215         public Object JavaDoc run() {
216         try {
217             File JavaDoc file = new File JavaDoc(cpath);
218             String JavaDoc canonical_path = file.getCanonicalPath();
219             int ln;
220             if (directory &&
221             ((ln=canonical_path.length()) == 0 ||
222             canonical_path.charAt(ln - 1) != File.separatorChar)) {
223             return canonical_path + File.separator;
224             } else {
225             return canonical_path;
226             }
227         } catch (IOException JavaDoc ioe) {
228             // ignore if we can't canonicalize path?
229
}
230         return cpath;
231         }
232     });
233
234     // XXX: at this point the path should be absolute. die if it isn't?
235
}
236
237     /**
238      * Creates a new FilePermission object with the specified actions.
239      * <i>path</i> is the pathname of a
240      * file or directory, and <i>actions</i> contains a comma-separated list of the
241      * desired actions granted on the file or directory. Possible actions are
242      * "read", "write", "execute", and "delete".
243      *
244      * <p>A pathname that ends in "/*" (where "/" is
245      * the file separator character, <code>File.separatorChar</code>) indicates
246      * a directory and all the files contained in that directory. A pathname
247      * that ends with "/-" indicates a directory and (recursively) all files
248      * and subdirectories contained in that directory. The special pathname
249      * "&lt;&lt;ALL FILES&gt;&gt;" matches all files.
250      *
251      * <p>A pathname consisting of a single "*" indicates all the files
252      * in the current directory, while a pathname consisting of a single "-"
253      * indicates all the files in the current directory and
254      * (recursively) all files and subdirectories contained in the current
255      * directory.
256      *
257      * @param path the pathname of the file/directory.
258      * @param actions the action string.
259      */

260
261     public FilePermission(String JavaDoc path, String JavaDoc actions)
262     {
263     super(path);
264     init(getMask(actions));
265     }
266
267     /**
268      * Creates a new FilePermission object using an action mask.
269      * More efficient than the FilePermission(String, String) constructor.
270      * Can be used from within
271      * code that needs to create a FilePermission object to pass into the
272      * <code>implies</code> method.
273      *
274      * @param path the pathname of the file/directory.
275      * @param mask the action mask to use.
276      */

277
278     // package private for use by the FilePermissionCollection add method
279
FilePermission(String JavaDoc path, int mask)
280     {
281     super(path);
282     init(mask);
283     }
284
285     /**
286      * Checks if this FilePermission object "implies" the specified permission.
287      * <P>
288      * More specifically, this method returns true if:<p>
289      * <ul>
290      * <li> <i>p</i> is an instanceof FilePermission,<p>
291      * <li> <i>p</i>'s actions are a proper subset of this
292      * object's actions, and <p>
293      * <li> <i>p</i>'s pathname is implied by this object's
294      * pathname. For example, "/tmp/*" implies "/tmp/foo", since
295      * "/tmp/*" encompasses the "/tmp" directory and all files in that
296      * directory, including the one named "foo".
297      * </ul>
298      * @param p the permission to check against.
299      *
300      * @return true if the specified permission is implied by this object,
301      * false if not.
302      */

303     public boolean implies(Permission p) {
304     if (!(p instanceof FilePermission JavaDoc))
305         return false;
306
307     FilePermission JavaDoc that = (FilePermission JavaDoc) p;
308
309     // we get the effective mask. i.e., the "and" of this and that.
310
// They must be equal to that.mask for implies to return true.
311

312     return ((this.mask & that.mask) == that.mask) && impliesIgnoreMask(that);
313     }
314
315     /**
316      * Checks if the Permission's actions are a proper subset of the
317      * this object's actions. Returns the effective mask iff the
318      * this FilePermission's path also implies that FilePermission's path.
319      *
320      * @param that the FilePermission to check against.
321      * @param exact return immediately if the masks are not equal
322      * @return the effective mask
323      */

324     boolean impliesIgnoreMask(FilePermission JavaDoc that) {
325     if (this.directory) {
326         if (this.recursive) {
327         // make sure that.path is longer then path so
328
// something like /foo/- does not imply /foo
329
if (that.directory) {
330             return (that.cpath.length() >= this.cpath.length()) &&
331                 that.cpath.startsWith(this.cpath);
332         } else {
333             return ((that.cpath.length() > this.cpath.length()) &&
334                 that.cpath.startsWith(this.cpath));
335         }
336         } else {
337         if (that.directory) {
338             // if the permission passed in is a directory
339
// specification, make sure that a non-recursive
340
// permission (i.e., this object) can't imply a recursive
341
// permission.
342
if (that.recursive)
343             return false;
344             else
345             return (this.cpath.equals(that.cpath));
346         } else {
347             int last = that.cpath.lastIndexOf(File.separatorChar);
348             if (last == -1)
349             return false;
350             else {
351             // this.cpath.equals(that.cpath.substring(0, last+1));
352
// Use regionMatches to avoid creating new string
353

354             return (this.cpath.length() == (last + 1)) &&
355                 this.cpath.regionMatches(0, that.cpath, 0, last+1);
356             }
357         }
358         }
359     } else {
360         return (this.cpath.equals(that.cpath));
361     }
362     }
363
364     /**
365      * Checks two FilePermission objects for equality. Checks that <i>obj</i> is
366      * a FilePermission, and has the same pathname and actions as this object.
367      * <P>
368      * @param obj the object we are testing for equality with this object.
369      * @return true if obj is a FilePermission, and has the same pathname and
370      * actions as this FilePermission object.
371      */

372     public boolean equals(Object JavaDoc obj) {
373     if (obj == this)
374         return true;
375
376     if (! (obj instanceof FilePermission JavaDoc))
377         return false;
378
379     FilePermission JavaDoc that = (FilePermission JavaDoc) obj;
380
381     return (this.mask == that.mask) &&
382         this.cpath.equals(that.cpath) &&
383         (this.directory == that.directory) &&
384         (this.recursive == that.recursive);
385     }
386
387     /**
388      * Returns the hash code value for this object.
389      *
390      * @return a hash code value for this object.
391      */

392
393     public int hashCode() {
394     return this.cpath.hashCode();
395     }
396
397     /**
398      * Converts an actions String to an actions mask.
399      *
400      * @param action the action string.
401      * @return the actions mask.
402      */

403     private static int getMask(String JavaDoc actions) {
404
405     int mask = NONE;
406
407     // Null action valid?
408
if (actions == null) {
409         return mask;
410     }
411     // Check against use of constants (used heavily within the JDK)
412
if (actions == SecurityConstants.FILE_READ_ACTION) {
413         return READ;
414     } else if (actions == SecurityConstants.FILE_WRITE_ACTION) {
415         return WRITE;
416     } else if (actions == SecurityConstants.FILE_EXECUTE_ACTION) {
417         return EXECUTE;
418     } else if (actions == SecurityConstants.FILE_DELETE_ACTION) {
419         return DELETE;
420     }
421     
422     char[] a = actions.toCharArray();
423
424     int i = a.length - 1;
425     if (i < 0)
426         return mask;
427
428     while (i != -1) {
429         char c;
430
431         // skip whitespace
432
while ((i!=-1) && ((c = a[i]) == ' ' ||
433                    c == '\r' ||
434                    c == '\n' ||
435                    c == '\f' ||
436                    c == '\t'))
437         i--;
438
439         // check for the known strings
440
int matchlen;
441
442         if (i >= 3 && (a[i-3] == 'r' || a[i-3] == 'R') &&
443               (a[i-2] == 'e' || a[i-2] == 'E') &&
444               (a[i-1] == 'a' || a[i-1] == 'A') &&
445               (a[i] == 'd' || a[i] == 'D'))
446         {
447         matchlen = 4;
448         mask |= READ;
449
450         } else if (i >= 4 && (a[i-4] == 'w' || a[i-4] == 'W') &&
451                  (a[i-3] == 'r' || a[i-3] == 'R') &&
452                  (a[i-2] == 'i' || a[i-2] == 'I') &&
453                  (a[i-1] == 't' || a[i-1] == 'T') &&
454                  (a[i] == 'e' || a[i] == 'E'))
455         {
456         matchlen = 5;
457         mask |= WRITE;
458
459         } else if (i >= 6 && (a[i-6] == 'e' || a[i-6] == 'E') &&
460                          (a[i-5] == 'x' || a[i-5] == 'X') &&
461                  (a[i-4] == 'e' || a[i-4] == 'E') &&
462                  (a[i-3] == 'c' || a[i-3] == 'C') &&
463                  (a[i-2] == 'u' || a[i-2] == 'U') &&
464                  (a[i-1] == 't' || a[i-1] == 'T') &&
465                  (a[i] == 'e' || a[i] == 'E'))
466         {
467         matchlen = 7;
468         mask |= EXECUTE;
469
470         } else if (i >= 5 && (a[i-5] == 'd' || a[i-5] == 'D') &&
471                  (a[i-4] == 'e' || a[i-4] == 'E') &&
472                  (a[i-3] == 'l' || a[i-3] == 'L') &&
473                  (a[i-2] == 'e' || a[i-2] == 'E') &&
474                  (a[i-1] == 't' || a[i-1] == 'T') &&
475                  (a[i] == 'e' || a[i] == 'E'))
476         {
477         matchlen = 6;
478         mask |= DELETE;
479
480         } else {
481         // parse error
482
throw new IllegalArgumentException JavaDoc(
483             "invalid permission: " + actions);
484         }
485
486         // make sure we didn't just match the tail of a word
487
// like "ackbarfaccept". Also, skip to the comma.
488
boolean seencomma = false;
489         while (i >= matchlen && !seencomma) {
490         switch(a[i-matchlen]) {
491         case ',':
492             seencomma = true;
493             /*FALLTHROUGH*/
494         case ' ': case '\r': case '\n':
495         case '\f': case '\t':
496             break;
497         default:
498             throw new IllegalArgumentException JavaDoc(
499                 "invalid permission: " + actions);
500         }
501         i--;
502         }
503
504         // point i at the location of the comma minus one (or -1).
505
i -= matchlen;
506     }
507
508     return mask;
509     }
510
511     /**
512      * Return the current action mask. Used by the FilePermissionCollection.
513      *
514      * @return the actions mask.
515      */

516
517     int getMask() {
518     return mask;
519     }
520
521     /**
522      * Return the canonical string representation of the actions.
523      * Always returns present actions in the following order:
524      * read, write, execute, delete.
525      *
526      * @return the canonical string representation of the actions.
527      */

528     private static String JavaDoc getActions(int mask)
529     {
530     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
531         boolean comma = false;
532
533     if ((mask & READ) == READ) {
534         comma = true;
535         sb.append("read");
536     }
537
538     if ((mask & WRITE) == WRITE) {
539         if (comma) sb.append(',');
540             else comma = true;
541         sb.append("write");
542     }
543
544     if ((mask & EXECUTE) == EXECUTE) {
545         if (comma) sb.append(',');
546             else comma = true;
547         sb.append("execute");
548     }
549
550     if ((mask & DELETE) == DELETE) {
551         if (comma) sb.append(',');
552             else comma = true;
553         sb.append("delete");
554     }
555
556     return sb.toString();
557     }
558
559     /**
560      * Returns the "canonical string representation" of the actions.
561      * That is, this method always returns present actions in the following order:
562      * read, write, execute, delete. For example, if this FilePermission object
563      * allows both write and read actions, a call to <code>getActions</code>
564      * will return the string "read,write".
565      *
566      * @return the canonical string representation of the actions.
567      */

568     public String JavaDoc getActions()
569     {
570     if (actions == null)
571         actions = getActions(this.mask);
572
573     return actions;
574     }
575
576
577     /**
578      * Returns a new PermissionCollection object for storing FilePermission
579      * objects.
580      * <p>
581      * FilePermission objects must be stored in a manner that allows them
582      * to be inserted into the collection in any order, but that also enables the
583      * PermissionCollection <code>implies</code>
584      * method to be implemented in an efficient (and consistent) manner.
585      *
586      * <p>For example, if you have two FilePermissions:
587      * <OL>
588      * <LI> <code>"/tmp/-", "read"</code>
589      * <LI> <code>"/tmp/scratch/foo", "write"</code>
590      * </OL>
591      *
592      * <p>and you are calling the <code>implies</code> method with the FilePermission:
593      *
594      * <pre>
595      * "/tmp/scratch/foo", "read,write",
596      * </pre>
597      *
598      * then the <code>implies</code> function must
599      * take into account both the "/tmp/-" and "/tmp/scratch/foo"
600      * permissions, so the effective permission is "read,write",
601      * and <code>implies</code> returns true. The "implies" semantics for
602      * FilePermissions are handled properly by the PermissionCollection object
603      * returned by this <code>newPermissionCollection</code> method.
604      *
605      * @return a new PermissionCollection object suitable for storing
606      * FilePermissions.
607      */

608
609     public PermissionCollection newPermissionCollection() {
610     return new FilePermissionCollection();
611     }
612
613     /**
614      * WriteObject is called to save the state of the FilePermission
615      * to a stream. The actions are serialized, and the superclass
616      * takes care of the name.
617      */

618     private void writeObject(ObjectOutputStream JavaDoc s)
619         throws IOException JavaDoc
620     {
621     // Write out the actions. The superclass takes care of the name
622
// call getActions to make sure actions field is initialized
623
if (actions == null)
624         getActions();
625     s.defaultWriteObject();
626     }
627
628     /**
629      * readObject is called to restore the state of the FilePermission from
630      * a stream.
631      */

632     private void readObject(ObjectInputStream JavaDoc s)
633          throws IOException JavaDoc, ClassNotFoundException JavaDoc
634     {
635     // Read in the actions, then restore everything else by calling init.
636
s.defaultReadObject();
637     init(getMask(actions));
638     }
639 }
640
641 /**
642  * A FilePermissionCollection stores a set of FilePermission permissions.
643  * FilePermission objects
644  * must be stored in a manner that allows them to be inserted in any
645  * order, but enable the implies function to evaluate the implies
646  * method.
647  * For example, if you have two FilePermissions:
648  * <OL>
649  * <LI> "/tmp/-", "read"
650  * <LI> "/tmp/scratch/foo", "write"
651  * </OL>
652  * And you are calling the implies function with the FilePermission:
653  * "/tmp/scratch/foo", "read,write", then the implies function must
654  * take into account both the /tmp/- and /tmp/scratch/foo
655  * permissions, so the effective permission is "read,write".
656  *
657  * @see java.security.Permission
658  * @see java.security.Permissions
659  * @see java.security.PermissionCollection
660  *
661  * @version 1.76 01/12/04
662  *
663  * @author Marianne Mueller
664  * @author Roland Schemers
665  *
666  * @serial include
667  *
668  */

669
670 final class FilePermissionCollection extends PermissionCollection
671 implements Serializable JavaDoc {
672
673     // Not serialized; see serialization section at end of class
674
private transient List JavaDoc perms;
675
676     /**
677      * Create an empty FilePermissions object.
678      *
679      */

680
681     public FilePermissionCollection() {
682     perms = new ArrayList JavaDoc();
683     }
684
685     /**
686      * Adds a permission to the FilePermissions. The key for the hash is
687      * permission.path.
688      *
689      * @param permission the Permission object to add.
690      *
691      * @exception IllegalArgumentException - if the permission is not a
692      * FilePermission
693      *
694      * @exception SecurityException - if this FilePermissionCollection object
695      * has been marked readonly
696      */

697
698     public void add(Permission permission)
699     {
700     if (! (permission instanceof FilePermission JavaDoc))
701         throw new IllegalArgumentException JavaDoc("invalid permission: "+
702                            permission);
703     if (isReadOnly())
704         throw new SecurityException JavaDoc(
705         "attempt to add a Permission to a readonly PermissionCollection");
706         
707     synchronized (this) {
708         perms.add(permission);
709     }
710     }
711
712     /**
713      * Check and see if this set of permissions implies the permissions
714      * expressed in "permission".
715      *
716      * @param p the Permission object to compare
717      *
718      * @return true if "permission" is a proper subset of a permission in
719      * the set, false if not.
720      */

721
722     public boolean implies(Permission permission)
723     {
724     if (! (permission instanceof FilePermission JavaDoc))
725         return false;
726
727     FilePermission JavaDoc fp = (FilePermission JavaDoc) permission;
728
729     int desired = fp.getMask();
730     int effective = 0;
731     int needed = desired;
732
733     synchronized (this) {
734         int len = perms.size();
735         for (int i = 0; i < len; i++) {
736         FilePermission JavaDoc x = (FilePermission JavaDoc) perms.get(i);
737         if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(fp)) {
738             effective |= x.getMask();
739             if ((effective & desired) == desired)
740             return true;
741             needed = (desired ^ effective);
742         }
743         }
744     }
745     return false;
746     }
747
748     /**
749      * Returns an enumeration of all the FilePermission objects in the
750      * container.
751      *
752      * @return an enumeration of all the FilePermission objects.
753      */

754
755     public Enumeration JavaDoc elements() {
756         // Convert Iterator into Enumeration
757
synchronized (this) {
758         return Collections.enumeration(perms);
759     }
760     }
761
762     private static final long serialVersionUID = 2202956749081564585L;
763
764     // Need to maintain serialization interoperability with earlier releases,
765
// which had the serializable field:
766
// private Vector permissions;
767

768     /**
769      * @serialField permissions java.util.Vector
770      * A list of FilePermission objects.
771      */

772     private static final ObjectStreamField JavaDoc[] serialPersistentFields = {
773         new ObjectStreamField JavaDoc("permissions", Vector JavaDoc.class),
774     };
775
776     /**
777      * @serialData "permissions" field (a Vector containing the FilePermissions).
778      */

779     /*
780      * Writes the contents of the perms field out as a Vector for
781      * serialization compatibility with earlier releases.
782      */

783     private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
784     // Don't call out.defaultWriteObject()
785

786     // Write out Vector
787
Vector JavaDoc permissions = new Vector JavaDoc(perms.size());
788     synchronized (this) {
789         permissions.addAll(perms);
790     }
791
792         ObjectOutputStream.PutField JavaDoc pfields = out.putFields();
793         pfields.put("permissions", permissions);
794         out.writeFields();
795     }
796
797     /*
798      * Reads in a Vector of FilePermissions and saves them in the perms field.
799      */

800     private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc,
801     ClassNotFoundException JavaDoc {
802     // Don't call defaultReadObject()
803

804     // Read in serialized fields
805
ObjectInputStream.GetField JavaDoc gfields = in.readFields();
806
807     // Get the one we want
808
Vector JavaDoc permissions = (Vector JavaDoc)gfields.get("permissions", null);
809     perms = new ArrayList JavaDoc(permissions.size());
810     perms.addAll(permissions);
811     }
812 }
813
Popular Tags