jafs-library-20020725
[openafs.git] / src / JAVA / classes / org / openafs / jafs / ACL.java
1 /*
2  * @(#)ACL.java 2.0 04/18/2001
3  *
4  * Copyright (c) 2001 International Business Machines Corp.
5  * All rights reserved.
6  *
7  * This software has been released under the terms of the IBM Public
8  * License.  For details, see the LICENSE file in the top-level source
9  * directory or online at http://www.openafs.org/dl/license10.html
10  * 
11  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
12  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
13  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
15  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  */
23
24 package org.openafs.jafs;
25
26 import java.io.Serializable;
27 import java.util.ArrayList;
28 import java.util.StringTokenizer;
29
30 /**
31  * An abstract representation of AFS file and directory pathnames.
32  *
33  * This class is an extension of the standard Java File class with file-based 
34  * manipulation methods overridden by integrated AFS native methods.
35  *
36  * @version 2.0, 04/18/2001 - Completely revised class for efficiency.
37  */
38
39 public class ACL implements Serializable, Comparable
40 {
41   private ACL.Entry[] positiveEntries;
42   private ACL.Entry[] negativeEntries;
43
44   private String path;
45  
46   public ACL(String path) throws AFSException
47   {
48     int numberPositiveEntries = 0;
49     int numberNegativeEntries = 0;
50     ACL.Entry aclEntry;
51     String buffer;
52
53     this.path = path;
54
55     StringTokenizer st = new StringTokenizer(getACLString(path), "\n\t");
56
57     buffer = st.nextToken();
58     numberPositiveEntries = new Integer(buffer).intValue();
59     positiveEntries = new ACL.Entry[numberPositiveEntries];
60
61     buffer = st.nextToken();
62     numberNegativeEntries = new Integer(buffer).intValue();
63     negativeEntries = new ACL.Entry[numberNegativeEntries];
64
65     for(int i = 0; i < numberPositiveEntries; i++)
66     {
67       aclEntry = new ACL.Entry();
68       aclEntry.setUser(st.nextToken());
69       aclEntry.setPermissions(new Integer(st.nextToken()).intValue());
70       positiveEntries[i] = aclEntry;
71     }
72
73     for(int i = 0; i < numberNegativeEntries; i++)
74     {
75       aclEntry = new ACL.Entry();
76       aclEntry.setUser(st.nextToken());
77       aclEntry.setPermissions(new Integer(st.nextToken()).intValue());
78       negativeEntries[i] = aclEntry;
79     }
80   }
81   public int getEntryCount()
82   {
83     return positiveEntries.length + positiveEntries.length;
84   }
85   public String getPath()
86   {
87     return path;
88   }
89   public ACL.Entry[] getPositiveEntries()
90   {
91     return positiveEntries;
92   }
93   public void addPositiveEntry(ACL.Entry entry) throws AFSException
94   {
95     int n = positiveEntries.length;
96     ACL.Entry[] e = new ACL.Entry[n + 1];
97     System.arraycopy(positiveEntries, 0, e, 0, n);
98     e[n] = entry;
99     positiveEntries = e;
100     setACLString(path, getFormattedString());
101   }
102   public void setPositiveEntries(ACL.Entry[] entries) throws AFSException
103   {
104     this.positiveEntries = entries;
105     setACLString(path, getFormattedString());
106   }
107   public ACL.Entry[] getNegativeEntries()
108   {
109     return negativeEntries;
110   }
111   public void addNegativeEntry(ACL.Entry entry) throws AFSException
112   {
113     int n = negativeEntries.length;
114     ACL.Entry[] e = new ACL.Entry[n + 1];
115     System.arraycopy(negativeEntries, 0, e, 0, n);
116     e[n] = entry;
117     negativeEntries = e;
118     setACLString(path, getFormattedString());
119   }
120   public void setNegativeEntries(ACL.Entry[] entries) throws AFSException
121   {
122     this.negativeEntries = entries;
123     setACLString(path, getFormattedString());
124   }
125
126   public void flush() throws AFSException
127   {
128     setACLString(path, getFormattedString());
129   }
130
131   private ACL.Entry[] getNonEmptyEntries(ACL.Entry[] entries)
132   {
133     ArrayList response = new ArrayList(entries.length);
134     for (int i = 0; i < entries.length; i++)
135     {
136       boolean isNonEmpty = entries[i].canRead()   ||
137                            entries[i].canLookup() ||
138                            entries[i].canWrite()  ||
139                            entries[i].canInsert() ||
140                            entries[i].canDelete() ||
141                            entries[i].canLock()   ||
142                            entries[i].canAdmin();
143       if (isNonEmpty) response.add(entries[i]);
144     }
145     if (response.size() == entries.length) return entries;
146     return (ACL.Entry[])response.toArray(new ACL.Entry[response.size()]);
147   }
148
149   private void entriesToString(ACL.Entry[] entries, StringBuffer response)
150   {
151     for (int i = 0; i < entries.length; i++)
152     {
153       this.entryToString((ACL.Entry)entries[i], response);
154     }
155   }
156
157   private void entryToString(ACL.Entry entry, StringBuffer response)
158   {
159     response.append(entry.getUser() + '\t' + entry.getPermissionsMask() + '\n');
160   }
161
162   /**
163    * Returns a ViceIoctl formatted String representation of this 
164    * <CODE>ACL</CODE>.
165    *
166    * @return a ViceIoctl formatted String representation of this 
167    *         <CODE>ACL</CODE>.
168    */
169   private String getFormattedString()
170   {
171     StringBuffer out = null;
172     ACL.Entry[] nonEmptyPos = this.getNonEmptyEntries(this.getPositiveEntries());
173     ACL.Entry[] nonEmptyNeg = this.getNonEmptyEntries(this.getNegativeEntries());
174
175     out = new StringBuffer(nonEmptyPos.length + "\n" + nonEmptyNeg.length + "\n");
176     this.entriesToString(nonEmptyPos, out);
177     this.entriesToString(nonEmptyNeg, out);
178
179     return out.toString();
180   }
181
182   /////////////// custom override methods ////////////////////
183
184   /**
185    * Compares two ACL objects respective to their paths and does not
186    * factor any other attribute.    Alphabetic case is significant in 
187    * comparing names.
188    *
189    * @param     acl    The ACL object to be compared to this ACL
190    *                   instance
191    * 
192    * @return    Zero if the argument is equal to this ACL's path, a
193    *            value less than zero if this ACL's path is
194    *            lexicographically less than the argument, or a value greater
195    *            than zero if this ACL's path is lexicographically
196    *            greater than the argument
197    */
198   public int compareTo(ACL acl)
199   {
200     return this.getPath().compareTo(acl.getPath());
201   }
202
203   /**
204    * Comparable interface method.
205    *
206    * @see #compareTo(ACL)
207    */
208   public int compareTo(Object obj)
209   {
210     return compareTo((ACL)obj);
211   }
212
213   /**
214    * Tests whether two <code>ACL</code> objects are equal, based on their 
215    * paths and permission bits.
216    *
217    * @param acl the ACL to test
218    * @return whether the specifed ACL is the same as this ACL
219    */
220   public boolean equals( ACL acl )
221   {
222     return ( (this.getPath().equals(acl.getPath())) &&
223              (positiveEntries.equals(acl.getPositiveEntries())) &&
224              (negativeEntries.equals(acl.getNegativeEntries())) );
225   }
226
227   /**
228    * Returns a String representation of this <CODE>ACL</CODE>
229    *
230    * @return a String representation of this <CODE>ACL</CODE>
231    */
232   public String toString()
233   {
234     ACL.Entry[] nonEmptyPos = this.getNonEmptyEntries(this.getPositiveEntries());
235     ACL.Entry[] nonEmptyNeg = this.getNonEmptyEntries(this.getNegativeEntries());
236
237     StringBuffer out = new StringBuffer("ACL for ");
238     out.append(path);
239     out.append("\n");
240     out.append("Positive Entries:\n");
241     for (int i = 0; i < nonEmptyPos.length; i++) {
242       out.append("  ");
243       out.append(nonEmptyPos[i].toString());
244     }
245     if (nonEmptyNeg.length > 0) {
246       out.append("Negative Entries:\n");
247       for (int i = 0; i < nonEmptyNeg.length; i++) {
248         out.append("  ");
249         out.append(nonEmptyNeg[i].toString());
250       }
251     }
252
253     return out.toString();
254   }
255
256   /////////////// native methods ////////////////////
257
258   /**
259    * Returns a formatted String representing the ACL for the specified path.
260    *
261    * The string format is in the form of a ViceIoctl and is as follows:
262    * printf("%d\n%d\n", positiveEntriesCount, negativeEntriesCount);
263    * printf("%s\t%d\n", userOrGroupName, rightsMask);
264    *
265    * @param   path     the directory path
266    * @returns a formatted String representing the ACL for the specified path.
267    * @throws an AFSException if an AFS or JNI exception is encountered.
268    */
269   private native String getACLString(String path) throws AFSException;
270
271   /**
272    * Sets the ACL in the file system according to this abstract representation.
273    *
274    * @param path       the directory path
275    * @param aclString  string representation of ACL to be set
276    * @throws an AFSException if an AFS or JNI exception is encountered.
277    */
278   private native void setACLString(String path, String aclString) throws AFSException;
279
280   /*====================================================================*/
281   /* INNER CLASSES  */
282   /*====================================================================*/
283
284   /**
285    * AFS ACL Entry Class.
286    *
287    * <p> Documentation reference: 
288    * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ772">Managing Access Control Lists</A>
289    *
290    * @version 2.0, 04/18/2001 - Completely revised class for efficiency.
291    * @version 3.0, 05/01/2002 - Converted class to an inner class.
292    */
293   public static final class Entry implements Serializable
294   {
295     /** ACL Mask read constant */
296     public static final int READ   = 1;
297     /** ACL Mask write constant */
298     public static final int WRITE  = 2;
299     /** ACL Mask insert constant */
300     public static final int INSERT = 4;
301     /** ACL Mask lookup constant */
302     public static final int LOOKUP = 8;
303     /** ACL Mask delete constant */
304     public static final int DELETE = 16;
305     /** ACL Mask lock constant */
306     public static final int LOCK   = 32;
307     /** ACL Mask administer constant */
308     public static final int ADMIN  = 64;
309   
310     private String username;
311   
312     private boolean r = false;
313     private boolean l = false;
314     private boolean i = false;
315     private boolean d = false;
316     private boolean w = false;
317     private boolean k = false;
318     private boolean a = false;
319   
320     /** 
321      * Constructs a new ACL entry with all permission bits set to <code>false</code>.
322      */
323     public Entry()
324     {
325     }
326     /** 
327      * Constructs a new ACL entry with all permission bits set to <code>false</code>
328      * and sets the associated user or group name.
329      *
330      * @param           user    The user or group name associated with this entry
331      */
332     public Entry(String user)
333     {
334       this.setUser(user);
335     }
336     /** 
337      * Constructs a new ACL entry setting each permission bit to its appropriate 
338      * value according to the <code>permissionsMask</code> specified.
339      *
340      * @see #canRead
341      * @see #canWrite
342      * @see #canInsert
343      * @see #canLookup
344      * @see #canDelete
345      * @see #canLock
346      * @see #canAdmin
347      * @param           permissionsMask An integer representation of the permissoin 
348      *                                rights of this entry
349      */
350     public Entry(int permissionsMask)
351     {
352       this.setPermissions(permissionsMask);
353     }
354     /** 
355      * Constructs a new ACL entry setting each permission bit to its appropriate 
356      * value according to the <code>permissionsMask</code> specified
357      * and sets the associated user or group name.
358      *
359      * @see #canRead
360      * @see #canWrite
361      * @see #canInsert
362      * @see #canLookup
363      * @see #canDelete
364      * @see #canLock
365      * @see #canAdmin
366      * @see #setUser
367      * @param           permissionsMask An integer representation of the permissoin 
368      *                                rights of this entry
369      * @param           user                    The username or group associated with this entry
370      */
371     public Entry(String user, int permissionsMask)
372     {
373       this.setUser(user);
374       this.setPermissions(permissionsMask);
375     }
376     /*-------------------------------------------------------------------------*/
377     /** 
378      * Set this entry's permission bits according to the value of the 
379      * <code>permissionsMask</code> specified.
380      *
381      * @see     #getPermissionsMask
382      * @param           permissionsMask An integer representation of the permissoin 
383      *                                rights of this entry
384      */
385     public void setPermissions(int permissionsMask)
386     {
387       if ((permissionsMask & READ) != 0) {
388           this.setRead(true);
389       }
390       if ((permissionsMask & LOOKUP) != 0) {
391           this.setLookup(true);
392       }
393       if ((permissionsMask & INSERT) != 0) {
394           this.setInsert(true);
395       }
396       if ((permissionsMask & DELETE) != 0) {
397           this.setDelete(true);
398       }
399       if ((permissionsMask & WRITE) != 0) {
400           this.setWrite(true);
401       }
402       if ((permissionsMask & LOCK) != 0) {
403           this.setLock(true);
404       }
405       if ((permissionsMask & ADMIN) != 0) {
406           this.setAdmin(true);
407       }
408     }
409     /** 
410      * Returns this entry's permission mask.
411      *
412      * <p> <B>Permission Mask</B><BR>
413      * 01 - READ  <BR>
414      * 02 - WRITE <BR>
415      * 04 - INSERT<BR>
416      * 08 - LOOKUP<BR>
417      * 16 - DELETE<BR>
418      * 32 - LOCK  <BR>
419      * 64 - ADMIN <BR>
420      *
421      * <p> Any combination of the above mask values would equate to a valid combination of 
422      * permission settings.  For example, if the permission mask was <B>11</B>, the ACL permissions
423      * would be as follows: <code>read</code> (1), <code>write</code> (2), and <code>lookup</code> (8).<BR>
424      * [1 + 2 + 8 = 11]
425      *
426      * @return  An integer representation (mask) of the permissoin rights of this entry
427      */
428     public int getPermissionsMask()
429     {
430       int permissionsMask = 0;
431       if (canRead())   permissionsMask |= READ;
432       if (canWrite())  permissionsMask |= WRITE;
433       if (canInsert()) permissionsMask |= INSERT;
434       if (canLookup()) permissionsMask |= LOOKUP;
435       if (canDelete()) permissionsMask |= DELETE;
436       if (canLock())   permissionsMask |= LOCK;
437       if (canAdmin())  permissionsMask |= ADMIN;
438       return permissionsMask;
439     }
440     /** 
441      * Returns the user <B>or</B> group name associated with this ACL entry.
442      *
443      * @return  String representation of the user or group name associated with this entry.
444      */
445     public String getUser()
446     {
447       return username;
448     }
449     /** 
450      * Sets the user <B>or</B> group name associated with this ACL entry.
451      *
452      * @param   user    representation of the user or group name associated with this entry.
453      */
454     public void setUser(String user)
455     {
456       username = user;
457     }
458     /** 
459      * <IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits <code>read</code> access.
460      *
461      * <p> This permission enables a user to read the contents of files in the directory 
462      * and to obtain complete status information for the files (read/retrieve the file 
463      * attributes).
464      *
465      * <p><FONT COLOR="666699"><IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>File Permission</B></U></FONT><BR>
466      * This permission is meaningful with respect to files in 
467      * a directory, rather than the directory itself or its subdirectories. 
468      *
469      * <p> Documentation reference: 
470      * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
471      *
472      * @return  <code>true</code> if and only if the ACL permits <code>read</code> access of
473      *          files; <code>false</code> otherwise
474      */
475     public boolean canRead()
476     {
477       return r;
478     }
479     /** 
480      * Sets the ACL permission to accomodate <code>read</code> access for files.
481      *
482      * @see #canRead
483      * @param   flag    boolean flag that denotes the permission bit for <code>read</code> access.
484      */
485     public void setRead(boolean flag)
486     {
487       r = flag;
488     }
489     /** 
490      * <IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits lookup access.
491      *
492      * <p> This permission functions as something of a gate keeper for access to the directory 
493      * and its files, because a user must have it in order to exercise any other permissions. 
494      * In particular, a user must have this permission to access anything in the directory's 
495      * subdirectories, even if the ACL on a subdirectory grants extensive permissions.
496      *
497      * <p> This permission enables a user to list the names of the files and subdirectories in 
498      * the directory (this does not permit read access to its respective entries), obtain 
499      * complete status information for the directory element itself, and examine the directory's 
500      * ACL.
501      *
502      * <p> This permission does not enable a user to read the contents of a file in the 
503      * directory.
504      *
505      * <p> Similarly, this permission does not enable a user to lookup the contents of, 
506      * obtain complete status information for, or examine the ACL of the subdirectory of 
507      * the directory. Those operations require the <code>lookup</code> permission on the ACL
508      * of the subdirectory itself.
509      *
510      * <p><FONT COLOR="666699"><IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>Directory Permission</B></U></FONT><BR>
511      * This permission is meaningful with respect to the 
512      * directory itself. For example, the <code>insert</code> permission (see: {@link #canInsert})
513      * does not control addition of data to a file, but rather creation of a new file or 
514      * subdirectory. 
515      *
516      * <p> Documentation reference: 
517      * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
518      *
519      * @return  <code>true</code> if and only if the ACL permits <code>lookup</code> access for
520      *          directories; <code>false</code> otherwise
521      */
522     public boolean canLookup()
523     {
524       return l;
525     }
526     /** 
527      * Sets the ACL permission to accomodate <code>lookup</code> access for directories.
528      *
529      * @see #canLookup
530      * @param   flag    boolean flag that denotes the permission bit for <code>lookup</code> access.
531      */
532     public void setLookup(boolean flag)
533     {
534       l = flag;
535     }
536     /** 
537      * <IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits <code>insert</code> access.
538      *
539      * <p> This permission enables a user to add new files to the directory, either by creating 
540      * or copying, and to create new subdirectories. It does not extend into any subdirectories,
541      * which are protected by their own ACLs.
542      *
543      * <p><FONT COLOR="666699"><IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>Directory Permission</B></U></FONT><BR>
544      * This permission is meaningful with respect to the 
545      * directory itself. For example, the <code>insert</code> permission (see: {@link #canInsert})
546      * does not control addition of data to a file, but rather creation of a new file or 
547      * subdirectory. 
548      *
549      * <p> Documentation reference: 
550      * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
551      *
552      * @return  <code>true</code> if and only if the ACL permits <code>insert</code> access for
553      *          directories; <code>false</code> otherwise
554      */
555     public boolean canInsert()
556     {
557       return i;
558     }
559     /** 
560      * Sets the ACL permission to accomodate <code>insert</code> access for directories.
561      *
562      * @see #canInsert
563      * @param   flag    boolean flag that denotes the permission bit for <code>insert</code> access.
564      */
565     public void setInsert(boolean flag)
566     {
567       i = flag;
568     }
569     /** 
570      * <IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits <code>delete</code> access.
571      *
572      * <p> This permission enables a user to remove files and subdirectories from the directory 
573      * or move them into other directories (assuming that the user has the <code>insert</code>
574      * (see: {@link #canInsert}) permission on the ACL of the other directories).
575      *
576      * <p><FONT COLOR="666699"><IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>Directory Permission</B></U></FONT><BR>
577      * This permission is meaningful with respect to the 
578      * directory itself. For example, the <code>insert</code> permission (see: {@link #canInsert})
579      * does not control addition of data to a file, but rather creation of a new file or 
580      * subdirectory. 
581      *
582      * <p> Documentation reference: 
583      * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
584      *
585      * @return  <code>true</code> if and only if the ACL permits <code>delete</code> access for
586      *          directories; <code>false</code> otherwise
587      */
588     public boolean canDelete()
589     {
590       return d;
591     }
592     /** 
593      * Sets the ACL permission to accomodate <code>delete</code> access for directories.
594      *
595      * @see #canDelete
596      * @param   flag    boolean flag that denotes the permission bit for <code>delete</code> rights.
597      */
598     public void setDelete(boolean flag)
599     {
600       d = flag;
601     }
602     /** 
603      * <IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits <code>write</code> access.
604      *
605      * <p> This permission enables a user to modify the contents of files in the directory 
606      * and to change their operating system specific mode bits. 
607      *
608      * <p><FONT COLOR="666699"><IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>File Permission</B></U></FONT><BR>
609      * This permission is meaningful with respect to files in 
610      * a directory, rather than the directory itself or its subdirectories. 
611      *
612      * <p> Documentation reference: 
613      * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
614      *
615      * @return  <code>true</code> if and only if the ACL permits <code>write</code> access for
616      *          files; <code>false</code> otherwise
617      */
618     public boolean canWrite()
619     {
620       return w;
621     }
622     /** 
623      * Sets the ACL permission to accomodate <code>write</code> access for files.
624      *
625      * @see #canWrite
626      * @param   flag    boolean flag that denotes the permission bit for <code>write</code> access.
627      */
628     public void setWrite(boolean flag)
629     {
630       w = flag;
631     }
632     /** 
633      * <IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits the <code>lock</code> authority.
634      *
635      * <p> This permission enables the user to run programs that issue system calls to 
636      * lock files in the directory. 
637      *
638      * <p><FONT COLOR="666699"><IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>File Permission</B></U></FONT><BR>
639      * This permission is meaningful with respect to files in 
640      * a directory, rather than the directory itself or its subdirectories. 
641      *
642      * <p> Documentation reference: 
643      * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
644      *
645      * @return  <code>true</code> if and only if the ACL permits <code>lock</code> authority for
646      *          files; <code>false</code> otherwise
647      */
648     public boolean canLock()
649     {
650       return k;
651     }
652     /** 
653      * Sets the ACL permission to accomodate <code>lock</code> access for files.
654      *
655      * @see #canLock
656      * @param   flag    boolean flag that denotes the permission bit for <code>lock</code> rights.
657      */
658     public void setLock(boolean flag)
659     {
660       k = flag;
661     }
662     /** 
663      * <IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits <code>administer</code> access.
664      *
665      * <p> This permission enables a user to change the directory's ACL. Members of the 
666      * <code>system:administrators</code> group implicitly have this permission on every 
667      * directory (that is, even if that group does not appear on the ACL). Similarly, the 
668      * owner of a directory implicitly has this permission on its ACL and those of all 
669      * directories below it that he or she owns. 
670      *
671      * <p><FONT COLOR="666699"><IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>Directory Permission</B></U></FONT><BR>
672      * This permission is meaningful with respect to the 
673      * directory itself. For example, the <code>insert</code> permission (see: {@link #canInsert})
674      * does not control addition of data to a file, but rather creation of a new file or 
675      * subdirectory. 
676      *
677      * <p> Documentation reference: 
678      * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
679      *
680      * @return  <code>true</code> if and only if the ACL permits <code>administer</code> access for
681      *          directories; <code>false</code> otherwise
682      */
683     public boolean canAdmin()
684     {
685       return a;
686     }
687     /** 
688      * Sets the ACL permission to accomodate <code>administer</code> rights for directories.
689      *
690      * @see #canAdmin
691      * @param   flag    boolean flag that denotes the permission bit for <code>administer</code> rights.
692      */
693     public void setAdmin(boolean flag)
694     {
695       a = flag;
696     }
697
698     /////////////// custom override methods ////////////////////
699
700     /**
701      * Tests whether two <code>ACL.Entry</code> objects are equal, based on associated
702      * username and permission bits.
703      *
704      * @param entry the ACL.Entry to test
705      * @return whether the specifed ACL.Entry is the same as this ACL.Entry
706      */
707     public boolean equals( ACL.Entry entry )
708     {
709       return ( (this.getUser().equals( entry.getUser() )) &&
710                (this.getPermissionsMask() == entry.getPermissionsMask()) );
711     }
712   
713     /**
714      * Returns a String representation of this <CODE>ACL.Entry</CODE>
715      *
716      * @return a String representation of this <CODE>ACL.Entry</CODE>
717      */
718     public String toString()
719     {
720       StringBuffer out = new StringBuffer(username);
721       out.append("\t");
722       if (r) out.append("r");
723       if (l) out.append("l");
724       if (i) out.append("i");
725       if (d) out.append("d");
726       if (w) out.append("w");
727       if (k) out.append("k");
728       if (a) out.append("a");
729       out.append("\n");
730       return out.toString();
731     }
732
733   }
734 }
735
736
737
738
739
740
741
742
743