jafs-library-20020725
[openafs.git] / src / JAVA / classes / org / openafs / jafs / User.java
1 /*
2  * @(#)User.java        1.0 6/29/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.util.GregorianCalendar;
27 import java.util.Date;
28 import java.util.ArrayList;
29 import java.io.Serializable;
30
31 /**
32  * An abstract representation of an AFS user.  It holds information about 
33  * the user, such as what groups it belongs to.
34  * <BR><BR>
35  *
36  * Constructing an instance of a <code>User</code> does not mean an actual 
37  * AFS user is created in a cell -- usually a <code>User</code>
38  * object is a representation of an already existing AFS user.  If, 
39  * however, the <code>User</code> is constructed with the name of a 
40  * user that does not exist in the cell represented by the provided 
41  * <code>Cell</code>, a new user with that name can be
42  * created in that server by calling the {@link #create(String, int)} or
43  * {@link #create(String)} method. If such a user does already exist when 
44  * one of these methods is called, an exception will be thrown.<BR><BR>
45  *
46  * Each <code>User</code> object has its own individual set of
47  * <code>Group</code>s that it owns and <code>Group</code>s for which
48  * it is a member.  These represents the properties and attributes 
49  * of an actual AFS user.
50  * <BR><BR>
51  *
52  * Since this <code>User</code> object is a union of both the PTS and KAS
53  * properties of AFS users, some methods meant for users with a PTS entry
54  * will throw exceptions if used on a user with only a KAS entry, and vice
55  * versa.<BR><BR>  
56  *
57  * <!--Information on how member values are set-->
58  *
59  * Associated with an AFS user are many attributes, such as whether or not
60  * it can change its own password, or who is allowed to find out the groups
61  * to which this user belongs.  The <code>User</code> class has many
62  * "set" methods to indicate values for these attributes (i.e. 
63  * {@link #setChangePassword(boolean)} and {@link #setListMembership(int)}).  
64  * However, in order for these values to be written to the actual AFS user, 
65  * the {@link #flushInfo()} method needs to be called.  This writes all user
66  * attributes set through this API to AFS.  This is done to minimize calls 
67  * through JNI.<BR><BR>
68  *
69  * <!--Example of how to use class-->
70  * The following is a simple example of how to construct and use a 
71  * <code>User</code> object.  It iterates through the list of users 
72  * (a union of pts and kas users) for a cell, and prints out the name and 
73  * id of each.
74  *
75  * <PRE>
76  * import org.openafs.jafs.Cell;
77  * import org.openafs.jafs.AFSException;
78  * import org.openafs.jafs.User;
79  * ...
80  * public class ...
81  * {
82  *   ...
83  *   private Cell cell;
84  *   ...
85  *   public static void main(String[] args) throws Exception
86  *   {
87  *     String username   = arg[0];
88  *     String password   = arg[1];
89  *     String cellName   = arg[2];
90  * 
91  *     token  = new Token(username, password, cellName);
92  *     cell   = new Cell(token);
93  *     server = cell.getServer(serverName);
94  * 
95  *     System.out.println("Users in Cell " + cell.getName() + ":");
96  *     User[] users = cell.getUsers();
97  *     for (int i = 0; i < users.length; i++) {
98  *       System.out.println(" -> " + users[i] + ": " users[i].getID());
99  *     }
100  *   }
101  *   ...
102  * }
103  * </PRE>
104  *
105  */
106 public class User implements PTSEntry, Serializable, Comparable
107 {
108   /**
109    * Only the owner of the user has access
110    */
111   public static final int USER_OWNER_ACCESS = 0;
112   /**
113    * Any user has access
114    */
115   public static final int USER_ANYUSER_ACCESS = 1;
116
117   /**
118    * User has administrative kas privileges
119    */
120   public static final int ADMIN = 0;
121   /**
122    * User has no administrative kas privileges
123    */
124   public static final int NO_ADMIN = 1;
125
126   /**
127    * TGS will grant tickets for user
128    */
129   public static final int GRANT_TICKETS = 0;
130   /**
131    * TGS will not grant tickets for user
132    */
133   public static final int NO_GRANT_TICKETS = 1;
134
135   /**
136    * TGS can use user's key for an encryption key
137    */
138   public static final int ENCRYPT = 0;
139   /**
140    * TGS cannot use user's key for an encryption key
141    */
142   public static final int NO_ENCRYPT = 1;
143
144   /**
145    * User can change their password
146    */
147   public static final int CHANGE_PASSWORD = 0;
148   /**
149    * User cannot change their password
150    */
151   public static final int NO_CHANGE_PASSWORD = 1;
152
153   /**
154    * User can reuse their password
155    */
156   public static final int REUSE_PASSWORD = 0;
157   /**
158    * User cannot reuse their password
159    */
160   public static final int NO_REUSE_PASSWORD = 1;
161
162   protected Cell cell;
163   protected int cellHandle;
164   protected String name;
165
166   /**
167    * Does this user have a kas entry?
168    */
169   protected boolean kas;
170   /**
171    * Does this user have a pts entry?
172    */
173   protected boolean pts;
174
175   // pts fields
176   protected int groupCreationQuota;
177   protected int groupMembershipCount;
178   protected int nameUID;
179   protected int ownerUID;
180   protected int creatorUID;
181
182   /**
183    * who is allowed to execute pts examine for this user.  Valid values are:
184    *   <ul>
185    *   <li>{@link #USER_OWNER_ACCESS}  
186    *       -- only the owner has permission</li>
187    *   <li>{@link #USER_ANYUSER_ACCESS} 
188    *       -- any user has permission</li></ul>
189    */
190   protected int listStatus;
191   /**
192    * who is allowed to execute pts listowned for this user.  Valid values are:
193    *   <ul>
194    *   <li>{@link #USER_OWNER_ACCESS}  
195    *       -- only the owner has permission</li>
196    *   <li>{@link #USER_ANYUSER_ACCESS} 
197    *       -- any user has permission</li></ul>
198    */
199   protected int listGroupsOwned;
200   /**
201    * who is allowed to execute pts membership for this user.  Valid values are:
202    *   <ul>
203    *   <li>{@link #USER_OWNER_ACCESS} 
204    *       -- only the owner has permission</li>
205    *   <li>{@link #USER_ANYUSER_ACCESS} 
206    *       -- any user has permission</li></ul>
207    */
208   protected int listMembership;
209   protected String owner;
210   protected String creator;
211   
212   // lists
213   protected ArrayList groups;
214   protected ArrayList groupNames;
215   protected ArrayList groupsOwned;
216   protected ArrayList groupsOwnedNames;
217
218   // kas fields
219   /**
220    * whether or not this user has kas administrative privileges. 
221    *   Valid values are:
222    *   <ul>
223    *   <li>{@link #ADMIN}</li>
224    *   <li>{@link #NO_ADMIN}</li></ul>
225    */
226   protected int adminSetting;
227   /**
228    * whether the TGS will grant tickets for this user. Valid values are:
229    *   <ul>
230    *   <li>{@link #GRANT_TICKETS}</li>
231    *   <li>{@link #NO_GRANT_TICKETS}</li></ul>
232    */
233   protected int tgsSetting;
234   /**
235    * whether the TGS can use this user's key as an encryption key. Valid values are:
236    *   <ul>
237    *   <li>{@link #ENCRYPT}</li>
238    *   <li>{@link #NO_ENCRYPT}</li></ul>
239    */
240   protected int encSetting;
241   /**
242    * whether this user is allowed to change its password. Valid values are:
243    *   <ul>
244    *   <li>{@link #CHANGE_PASSWORD}</li>
245    *   <li>{@link #NO_CHANGE_PASSWORD}</li></ul>
246    */
247   protected int cpwSetting;
248   /**
249    * whether this user is allowed to reuse its password. Valid values are:
250    *   <ul>
251    *   <li>{@link #REUSE_PASSWORD}</li>
252    *   <li>{@link #NO_REUSE_PASSWORD}</li></ul>
253    */
254   protected int rpwSetting;
255   protected int userExpiration;
256   protected int lastModTime;
257   protected String lastModName;
258   protected int lastChangePasswordTime;
259   protected int maxTicketLifetime;
260   protected int keyVersion;
261   protected String encryptionKey;
262   protected long keyCheckSum;
263   protected int daysToPasswordExpire;
264   protected int failLoginCount;
265   protected int lockTime;
266   protected int lockedUntil;
267
268   // Dates and times
269   protected GregorianCalendar lockedUntilDate;
270   protected GregorianCalendar userExpirationDate;
271   protected GregorianCalendar lastModTimeDate;
272   protected GregorianCalendar lastChangePasswordTimeDate;
273
274   /**
275    * Whether or not the information fields of this user have been filled.
276    */
277   protected boolean cachedInfo;
278
279   /**
280    * Constructs a new <code>User</code> object instance given the name 
281    * of the AFS user and the AFS cell, represented by 
282    * <CODE>cell</CODE>, to which it belongs.   This does not actually
283    * create a new AFS user, it just represents one.
284    * If <code>name</code> is not an actual AFS user, exceptions
285    * will be thrown during subsequent method invocations on this 
286    * object, unless the {@link #create(String, int)} or {@link #create(String)}
287    * method is explicitly called to create it.
288    *
289    * @param name  the name of the user to represent
290    * @param cell  the cell to which the user belongs.
291    * @exception AFSException      If an error occurs in the native code
292    */
293   public User( String name, Cell cell ) throws AFSException
294   {
295     this.name = name;
296     this.cell = cell;
297     cellHandle = cell.getCellHandle();
298     
299     groups = null;
300     groupNames = null;
301     groupsOwned = null;
302     groupsOwnedNames = null;
303     cachedInfo = false;
304     kas = false;
305     pts = false;
306   }
307
308   /**
309    * Constructs a new <code>User</code> object instance given the name 
310    * of the AFS user and the AFS cell, represented by 
311    * <CODE>cell</CODE>, to which it belongs.   This does not actually
312    * create a new AFS user, it just represents one.
313    * If <code>name</code> is not an actual AFS user, exceptions
314    * will be thrown during subsequent method invocations on this 
315    * object, unless the {@link #create(String, int)} or {@link #create(String)}
316    * method is explicitly called to create it.   Note that if the process
317    * doesn't exist and <code>preloadAllMembers</code> is true, an exception
318    * will be thrown.
319    *
320    * <P> This constructor is ideal for point-in-time representation and 
321    * transient applications. It ensures all data member values are set and 
322    * available without calling back to the filesystem at the first request 
323    * for them.  Use the {@link #refresh()} method to address any coherency 
324    * concerns.
325    *
326    * @param name               the name of the user to represent 
327    * @param cell               the cell to which the user belongs.
328    * @param preloadAllMembers  true will ensure all object members are 
329    *                           set upon construction;
330    *                           otherwise members will be set upon access, 
331    *                           which is the default behavior.
332    * @exception AFSException      If an error occurs in the native code
333    * @see #refresh
334    */
335   public User( String name, Cell cell, boolean preloadAllMembers ) 
336       throws AFSException
337   {
338     this(name, cell);
339     if (preloadAllMembers) refresh(true);
340   }
341   
342   /**
343    * Constructs a blank <code>User</code> object given the cell to which 
344    * the user belongs.  This blank object can then be passed into other 
345    * methods to fill out its properties.
346    *
347    * @exception AFSException      If an error occurs in the native code
348    * @param cell       the cell to which the user belongs.
349    */
350   User( Cell cell ) throws AFSException
351   {
352     this( null, cell );
353   }
354
355   /*-------------------------------------------------------------------------*/
356
357   /**
358    * Creates the kas and pts entries for a new user in this cell.  
359    * Automatically assigns a user id.
360    *   *
361    * @param password      the password for the new user
362    * @exception AFSException  If an error occurs in the native code
363    */    
364   public void create( String password ) throws AFSException
365   {
366     create( password, 0 );
367   }
368
369   /**
370    * Creates the kas and pts entries for a new user in this cell.
371    *
372    * @param password      the password for the new user
373    * @param uid       the user id to assign to the new user
374    *
375    * @exception AFSException  If an error occurs in the native code
376    */ 
377   public void create( String password, int uid ) throws AFSException
378   {
379     create( cell.getCellHandle(), name, password, uid );
380   }
381
382   /**
383    * Deletes the pts and kas entries for a user in this cell. Deletes this user
384    * from the membership list of the groups to which it belonged, but does not 
385    * delete the groups owned by this user.  Also nullifies this corresponding 
386    * Java object.
387    *
388    * @exception AFSException  If an error occurs in the native code
389    */ 
390   public void delete() throws AFSException
391   {
392         delete( cell.getCellHandle(), name );
393
394         cell = null;
395         name = null;
396         kas = false;
397         pts = false;
398         owner = null;
399         creator = null;
400         groups = null;
401         groupsOwned = null;
402         groupNames = null;
403         groupsOwnedNames = null;
404         lastModName = null;
405         encryptionKey = null;
406         lockedUntilDate = null;
407         userExpirationDate = null;
408         lastModTimeDate = null;
409         lastChangePasswordTimeDate = null;
410         try {
411             finalize();
412         } catch( java.lang.Throwable t ) {
413             throw new AFSException( t.getMessage() );
414         }
415   }
416
417   /**
418    * Unlocks the given user if they were locked out of the cell.
419    *
420    * @param userName      the name of the user to unlock
421    * @exception AFSException  If an error occurs in the native code
422    */ 
423   public void unlock() throws AFSException
424   {
425     unlock( cell.getCellHandle(), name );
426     lockedUntil = 0;
427     lockedUntilDate = null;
428   }
429
430   /**
431    * Flushes the current information of this <code>User</code> object to disk.
432    * This will update the information of the actual AFS user to match the 
433    * settings that have been modified within this <code>User</code> object.  
434    * This function must be called before any changes made to the information 
435    * fields of this user will be seen by AFS.
436    *
437    * @exception AFSException      If an error occurs in the native code
438    */
439   public void flushInfo() throws AFSException
440   {
441     setUserInfo( cell.getCellHandle(), name, this );
442   }
443
444   /**
445    * Change the name of this user.  Automatically flushes the info of this 
446    * user in order to update kas entry of the new name.  NOTE:  renaming a 
447    * locked user will unlock that user.
448    *
449    * @param newName    the new name for this user
450    * @exception AFSException  If an error occurs in the native code
451    */
452   public void rename( String newName ) throws AFSException
453   {
454     rename( cell.getCellHandle(), name, newName );
455     name = newName;
456     flushInfo();
457   }
458
459   /**
460    * Refreshes the properties of this User object instance with values from 
461    * the AFS user it represents.  All properties that have been initialized 
462    * and/or accessed will be renewed according to the values of the AFS user 
463    * this User object instance represents.
464    *
465    * <P>Since in most environments administrative changes can be administered
466    * from an AFS command-line program or an alternate GUI application, this
467    * method provides a means to refresh the Java object representation and
468    * thereby ascertain any possible modifications that may have been made
469    * from such alternate administrative programs.  Using this method before
470    * an associated instance accessor will ensure the highest level of 
471    * representative accuracy, accommodating changes made external to the
472    * Java application space.  If administrative changes to the underlying AFS 
473    * system are only allowed via this API, then the use of this method is 
474    * unnecessary.
475    * 
476    * @exception AFSException  If an error occurs in the native code
477    */
478   public void refresh() throws AFSException
479   {
480     refresh(false);
481   }
482
483   /**
484    * Refreshes the properties of this User object instance with values from 
485    * the AFS user it represents.  If <CODE>all</CODE> is <CODE>true</CODE> 
486    * then <U>all</U> of the properties of this User object instance will be 
487    * set, or renewed, according to the values of the AFS user it represents, 
488    * disregarding any previously set properties.
489    *
490    * <P> Thus, if <CODE>all</CODE> is <CODE>false</CODE> then properties that 
491    * are currently set will be refreshed and properties that are not set will 
492    * remain uninitialized. See {@link #refresh()} for more information.
493    *
494    * @param all   if true set or renew all object properties; otherwise renew 
495    *              all set properties
496    * @exception AFSException  If an error occurs in the native code
497    * @see #refresh()
498    */
499   protected void refresh(boolean all) throws AFSException
500   {
501     if ( all || cachedInfo ) {
502       refreshInfo();
503     }
504     if ( all || groupsOwned != null ) {
505       refreshGroupsOwned();
506     }
507     if ( all || groupsOwnedNames != null ) {
508       refreshGroupsOwnedNames();
509     }
510     if ( all || groups != null ) {
511       refreshGroups();
512     }
513     if ( all || groupNames != null ) {
514       refreshGroupNames();
515     }
516   }
517
518   /**
519    * Refreshes the information fields of this <code>User</code> to reflect 
520    * the current state of the AFS user.  Does not refresh the groups to which 
521    * the user belongs or groups owned by the user.
522    *
523    * @exception AFSException      If an error occurs in the native code
524    */
525   protected void refreshInfo() throws AFSException
526   {
527     getUserInfo( cell.getCellHandle(), name, this );
528     cachedInfo = true;
529     lastModTimeDate = null;
530     lastChangePasswordTimeDate = null;
531     lockedUntilDate = null;
532     userExpirationDate = null;
533   }
534
535   /**
536    * Refreshes the current information about the group names to which the 
537    * user belongs.  Does not refresh the information fields of the user or 
538    * the groups owned.
539    *
540    * @exception AFSException  If an error occurs in the native code
541    */
542   protected void refreshGroupNames() throws AFSException
543   {
544     String currName;
545     int iterationID = getUserGroupsBegin( cell.getCellHandle(), name );
546     groupNames = new ArrayList();
547     while( ( currName = getUserGroupsNextString( iterationID ) ) != null ) {
548       groupNames.add( currName );
549     } 
550     getUserGroupsDone( iterationID );
551   }
552   
553   /**
554    * Refreshes the current information about the group objects to which the 
555    * user belongs.  Does not refresh the information fields of the user or 
556    * the groups owned.
557    *
558    * @exception AFSException  If an error occurs in the native code
559    */
560   protected void refreshGroups() throws AFSException
561   {
562     Group currGroup;
563     int iterationID = getUserGroupsBegin( cell.getCellHandle(), name );
564
565     groups = new ArrayList();
566
567     currGroup = new Group( cell );
568     while( getUserGroupsNext( cellHandle, iterationID, currGroup ) != 0 ) {
569       groups.add( currGroup );
570       currGroup = new Group( cell );
571     } 
572     getUserGroupsDone( iterationID );
573   }
574
575   /**
576    * Refreshes the current information about the group names that the user 
577    * owns.  Does not refresh the information fields of the user or the groups 
578    * belonged to.
579    *
580    * @exception AFSException  If an error occurs in the native code
581    */
582   protected void refreshGroupsOwnedNames() throws AFSException
583   {
584     String currName;
585     int iterationID = this.getGroupsOwnedBegin( cell.getCellHandle(), name );
586     groupsOwnedNames = new ArrayList();
587     while( ( currName = this.getGroupsOwnedNextString( iterationID ) ) 
588            != null ) {
589       groupsOwnedNames.add( currName );
590     } 
591     this.getGroupsOwnedDone( iterationID );
592   }
593   
594   /**
595    * Refreshes the current information about the group objects that the user \
596    * owns.  Does not refresh the information fields of the user or the groups 
597    * belonged to.
598    *
599    * @exception AFSException  If an error occurs in the native code
600    */
601   protected void refreshGroupsOwned() throws AFSException
602   {
603     Group currGroup;
604     int iterationID = getGroupsOwnedBegin( cell.getCellHandle(), name );
605     groupsOwned = new ArrayList();
606     currGroup = new Group( cell );
607     while( getGroupsOwnedNext( cellHandle, iterationID, currGroup ) != 0 ) {
608       groupsOwned.add( currGroup );
609       currGroup = new Group( cell );
610     } 
611     getGroupsOwnedDone( iterationID );
612   }
613
614   /**
615    * Adds an access control list entry for some AFS directory for this user.
616    *
617    * @param directory    the full path of the place in the AFS file system 
618    *                     for which to add an entry
619    * @param read    whether or not to allow read access to this user
620    * @param write    whether or not to allow write access to this user
621    * @param lookup    whether or not to allow lookup access to this user
622    * @param delete    whether or not to allow deletion access to this user
623    * @param insert    whether or not to allow insertion access to this user
624    * @param lock    whether or not to allow lock access to this user
625    * @param admin    whether or not to allow admin access to this user
626    * @exception AFSException  If an error occurs in the native code
627   public void setACL( String directory, boolean read, boolean write, boolean lookup, boolean delete, boolean insert, boolean lock, boolean admin ) throws AFSException
628   {
629     cell.setACL( directory, name, read, write, lookup, delete, insert, lock, admin );
630   }
631    */
632
633   //////////////// ACCESSORS ////////////////////////
634
635   /**
636    * Returns the name of this user.
637    *
638    * @return the name of this user
639    */
640   public String getName()
641   {
642     return name;
643   }
644
645   /**
646    * Returns the Cell this user belongs to.
647    *
648    * @return the Cell this user belongs to
649    */
650   public Cell getCell()
651   {
652     return cell;
653   }
654
655   /**
656    * Returns whether or not this user has a kas entry.
657    *
658    * @return whether or not this user has a kas entry
659    * @exception AFSException  If an error occurs in the native code
660    * @see #refresh()
661    */
662   public boolean isKAS() throws AFSException
663   {
664     if ( !cachedInfo ) refreshInfo();
665     return kas;
666   }
667
668   /**
669    * Returns whether or not this user has a pts entry.
670    *
671    * @return whether or not this user has a pts entry
672    * @exception AFSException  If an error occurs in the native code
673    * @see #refresh()
674    */
675   public boolean isPTS() throws AFSException
676   {
677     if( !cachedInfo ) refreshInfo();
678     return pts;
679   }
680
681   /**
682    * PTS: Returns an array of the <code>Group</code> objects 
683    * to which this user belongs.
684    *
685    * @return      an array of the groups to which this user belongs
686    * @exception AFSException  If an error occurs in the native code
687    * @see #refresh()
688    */
689   public Group[] getGroups() throws AFSException
690   {
691     if( groups == null ) refreshGroups();
692     return (Group[]) groups.toArray( new Group[groups.size()] );
693   }
694
695   /**
696    * PTS: Returns the total count of groups this user owns.
697    *
698    * <P>If the total list of groups or group names have already been 
699    * collected (see {@link #getGroupsOwned()}), then the returning value 
700    * will be calculated based upon the current list.  Otherwise, PTS will 
701    * be explicitly queried for the information.
702    *
703    * @return      total count of groups this user owns
704    * @exception AFSException  If an error occurs in the native code
705    * @see #getGroupsOwned()
706    * @see #getGroupsOwnedNames()
707    */
708   public int getGroupsOwnedCount() throws AFSException
709   {
710     if( groupsOwned != null ) {
711       return groupsOwned.size();
712     } else if ( groupsOwnedNames != null ) {
713       return groupsOwnedNames.size();
714     } else {
715       return getGroupsOwnedCount( cell.getCellHandle(), name );
716     }
717   }
718
719   /**
720    * PTS: Returns an array of the <code>Group</code> objects 
721    * this user owns.
722    *
723    * @return     an array of the <code>Groups</code> this user owns
724    * @exception AFSException  If an error occurs in the native code
725    * @see #refresh()
726    */
727   public Group[] getGroupsOwned() throws AFSException
728   {
729     if( groupsOwned == null ) refreshGroupsOwned();
730     return (Group[]) groupsOwned.toArray( new Group[groupsOwned.size()] );
731   }
732
733   /**
734    * PTS: Returns a <code>String</code> array of the group names 
735    * to which this user belongs.
736    *
737    * @return      a <code>String</code> array of the groups to which this 
738    *              user belongs
739    * @exception AFSException  If an error occurs in the native code
740    * @see #refresh()
741    */
742   public String[] getGroupNames() throws AFSException
743   {
744     if( groupNames == null ) refreshGroupNames();
745     return (String []) groupNames.toArray( new String[groupNames.size() ] );
746   }
747
748   /**
749    * PTS: Returns a <code>String</code> array of the group names 
750    * this user owns.
751    *
752    * @return     a <code>String</code> array of the groups this user owns
753    * @exception AFSException  If an error occurs in the native code
754    * @see #refresh()
755    */
756   public String[] getGroupsOwnedNames() throws AFSException
757   {
758     if( groupsOwnedNames == null ) refreshGroupsOwnedNames();
759     return (String []) groupsOwnedNames.toArray( new String[groupsOwnedNames.size() ] );
760   }
761
762   /**
763    * PTS: Returns the numeric AFS id of this user.
764    *
765    * @return the AFS id of this user
766    * @exception AFSException  If an error occurs in the native code
767    * @see #refresh()
768    */
769   public int getUID() throws AFSException
770   {
771     if( !cachedInfo ) refreshInfo();
772     return nameUID;
773   }
774
775   /**
776    * PTS: Returns how many more groups this user is allowed to create.  
777    * -1 indicates unlimited.
778    *
779    * @return the group creation quota
780    * @exception AFSException  If an error occurs in the native code
781    * @see #refresh()
782    */
783   public int getGroupCreationQuota() throws AFSException
784   {
785     if( !cachedInfo ) refreshInfo();
786     return groupCreationQuota;
787   }
788
789   /**
790    * PTS: Returns the number of groups to which this user belongs.
791    *
792    * @return the group membership count
793    * @exception AFSException  If an error occurs in the native code
794    * @see #refresh()
795    */
796   public int getGroupMembershipCount() throws AFSException
797   {
798     if( !cachedInfo ) refreshInfo();
799     return groupMembershipCount;
800   }
801
802   /**
803    * PTS: Returns the owner of this user in the form of a {@link PTSEntry}.
804    *
805    * <P>The returning object could be either a {@link User} or {@link Group};
806    * to determine what type of object the {@link PTSEntry} represents,
807    * call the {@link PTSEntry#getType()} method.
808    *
809    * @return the owner of this user
810    * @exception AFSException  If an error occurs in the native code
811    * @see PTSEntry
812    * @see PTSEntry#getType()
813    * @see #refresh()
814    */
815   public PTSEntry getOwner() throws AFSException
816   {
817     if (!cachedInfo) refreshInfo();
818     if (owner == null) return null;
819     if (ownerUID > 0) {
820       return new User(owner, cell);
821     } else {
822       return new Group(owner, cell);
823     }
824   }
825
826   /**
827    * PTS: Returns the creator of this user in the form of a {@link PTSEntry}.
828    *
829    * <P>The returning object could be either a {@link User} or {@link Group};
830    * to determine what type of object the {@link PTSEntry} represents,
831    * call the {@link PTSEntry#getType()} method.
832    *
833    * @return the creator of this user
834    * @exception AFSException  If an error occurs in the native code
835    * @see PTSEntry
836    * @see PTSEntry#getType()
837    * @see #refresh()
838    */
839   public PTSEntry getCreator() throws AFSException
840   {
841     if (!cachedInfo) refreshInfo();
842     if (creator == null) return null;
843     if (creatorUID > 0) {
844       return new User(creator, cell);
845     } else {
846       return new Group(creator, cell);
847     }
848   }
849
850   /**
851    * Returns the type of {@link PTSEntry} this object represents.
852    *
853    * <P>This method will always return {@link PTSEntry#PTS_USER}.
854    *
855    * @return  the type of PTSEntry this object represents 
856               (will always return {@link PTSEntry#PTS_USER})
857    * @see PTSEntry
858    * @see PTSEntry#getType()
859    */
860   public short getType()
861   {
862     return PTSEntry.PTS_USER;
863   }
864
865   /**
866    * PTS: Returns who can list the status (pts examine) of this user.  
867    * Valid values are:
868    * <ul>
869    * <li><code>{@link #USER_OWNER_ACCESS}</code> 
870    *           -- only the owner has permission</li>
871    * <li><code>{@link #USER_ANYUSER_ACCESS}</code> 
872    *           -- any user has permission</li>
873    * </ul>
874    *
875    * @return the status listing permission
876    * @exception AFSException  If an error occurs in the native code
877    * @see #refresh()
878    */
879   public int getListStatus() throws AFSException
880   {
881     if( !cachedInfo ) refreshInfo();
882     return listStatus;
883   }
884
885   /**
886    * PTS: Returns who can list the groups owned (pts listowned) by this user.  
887    * Valid values are:
888    * <ul>
889    * <li><code>{@link #USER_OWNER_ACCESS}</code> 
890    *           -- only the owner has permission</li>
891    * <li><code>{@link #USER_ANYUSER_ACCESS}</code> 
892    *           -- any user has permission</li>
893    * </ul>
894    *
895    * @return the groups owned listing permission
896    * @exception AFSException  If an error occurs in the native code
897    * @see #refresh()
898    */
899   public int getListGroupsOwned() throws AFSException
900   {
901     if( !cachedInfo ) refreshInfo();
902     return listGroupsOwned;
903   }
904
905   /**
906    * PTS: Returns who can list the groups (pts membership) to which this 
907    * user belongs.  
908    * Valid values are:
909    * <ul>
910    * <li><code>{@link #USER_OWNER_ACCESS}</code> 
911    *           -- only the owner has permission</li>
912    * <li><code>{@link #USER_ANYUSER_ACCESS}</code> 
913    *           -- any user has permission</li>
914    * </ul>
915    *
916    * @return the membership listing permission
917    * @exception AFSException  If an error occurs in the native code
918    * @see #refresh()
919    */
920   public int getListMembership() throws AFSException
921   {
922     if( !cachedInfo ) refreshInfo();
923     return listMembership;
924   }
925
926   /**
927    * KAS: Returns whether or not this user has kas administrative privileges
928    *
929    * @return whether or not this user has kas administrative priveleges
930    * @exception AFSException  If an error occurs in the native code
931    * @see #refresh()
932    */
933   public boolean isAdmin() throws AFSException
934   {
935     if( !cachedInfo ) refreshInfo();
936     return (adminSetting == this.ADMIN);
937   }
938
939   /**
940    * KAS: Returns whether or not TGS will issue tickets for this user
941    *
942    * @return whether or not TGS will issue tickets for this user
943    * @exception AFSException  If an error occurs in the native code
944    * @see #refresh()
945    */
946   public boolean willGrantTickets() throws AFSException
947   {
948     if( !cachedInfo ) refreshInfo();
949     return (tgsSetting == this.GRANT_TICKETS);
950   }
951
952   /**
953    * KAS: Returns whether or not TGS can use this users ticket for an encryption key
954    *
955    * @return whether or not TGS can use this users ticket for an encryption key
956    * @exception AFSException  If an error occurs in the native code
957    * @see #refresh()
958    */
959   public boolean canEncrypt() throws AFSException
960   {
961     if( !cachedInfo ) refreshInfo();
962     return (encSetting == this.ENCRYPT);
963   }
964
965   /**
966    * KAS: Returns whether or not the user can change their password
967    *
968    * @return whether or not the user can change their password
969    * @exception AFSException  If an error occurs in the native code
970    * @see #refresh()
971    */
972   public boolean canChangePassword() throws AFSException
973   {
974     if( !cachedInfo ) refreshInfo();
975     return (cpwSetting == this.CHANGE_PASSWORD);
976   }
977
978   /**
979    * KAS: Returns whether or not the user can reuse their password
980    *
981    * @return whether or not the user can reuse their password
982    * @exception AFSException  If an error occurs in the native code
983    * @see #refresh()
984    */
985   public boolean canReusePassword() throws AFSException
986   {
987     if( !cachedInfo ) refreshInfo();
988     return (rpwSetting == this.REUSE_PASSWORD);
989   }
990
991   /**
992    * KAS: Returns the date and time the user expires.  
993    * A <code>null</code> value indicates the user never exipres (or that
994    * there is no kas entry for this user).
995    *
996    * @return the date and time the user expires
997    * @exception AFSException  If an error occurs in the native code
998    * @see #refresh()
999    */
1000   public int getUserExpiration() throws AFSException
1001   {
1002     if( !cachedInfo ) refreshInfo();
1003     return userExpiration;
1004   }
1005   /**
1006    * KAS: Returns the date and time the user expires.  
1007    * A <code>null</code> value indicates the user never expires (or that
1008    * there is no kas entry for this user).
1009    *
1010    * @return the date and time the user expires
1011    * @exception AFSException  If an error occurs in the native code
1012    * @see #refresh()
1013    */
1014   public GregorianCalendar getUserExpirationDate() throws AFSException
1015   {
1016     if( !cachedInfo ) refreshInfo();
1017     if( userExpirationDate == null && userExpiration != 0 ) {
1018       // make it into a date . . .
1019       if( userExpiration == 0 ) {
1020         userExpirationDate = null;
1021       } else {
1022         userExpirationDate = new GregorianCalendar();
1023         long longTime = ((long) userExpiration)*1000;
1024         Date d = new Date( longTime );
1025         userExpirationDate.setTime( d );
1026       }
1027     }
1028     return userExpirationDate;
1029   }
1030
1031   /**
1032    * KAS: Returns the date and time (in UTC) the user's KAS entry was 
1033    * last modified.
1034    *
1035    * @return the date and time (in UTC) the user was last modified
1036    * @exception AFSException  If an error occurs in the native code
1037    * @see #refresh()
1038    */
1039   public int getLastModTime() throws AFSException
1040   {
1041     if( !cachedInfo ) refreshInfo();
1042     return lastModTime;
1043   }
1044   /**
1045    * KAS: Returns the date and time the user was last modified.
1046    *
1047    * @return the date and time the user was last modified
1048    * @exception AFSException  If an error occurs in the native code
1049    * @see #refresh()
1050    */
1051   public GregorianCalendar getLastModTimeDate() throws AFSException
1052   {
1053     if( !cachedInfo ) refreshInfo();
1054     if( lastModTimeDate == null ) {
1055       // make it into a date . . .
1056       lastModTimeDate = new GregorianCalendar();
1057       long longTime = ((long) lastModTime)*1000;
1058       Date d = new Date( longTime );
1059       lastModTimeDate.setTime( d );
1060     }
1061     return lastModTimeDate;
1062   }
1063
1064   /**
1065    * KAS: Returns the name of the user that last modified this user.
1066    *
1067    * @return the name of this user that last modified this user.
1068    * @exception AFSException  If an error occurs in the native code
1069    * @see #refresh()
1070    */
1071   public String getLastModName() throws AFSException
1072   {
1073     if( !cachedInfo ) refreshInfo();
1074     return lastModName;
1075   }
1076
1077   /**
1078    * KAS: Returns the last date and time the user changed its password.
1079    *
1080    * @return the last date and time the user changed its password.
1081    * @exception AFSException  If an error occurs in the native code
1082    * @see #refresh()
1083    */
1084   public GregorianCalendar getLastChangePasswordTimeDate() 
1085       throws AFSException
1086   {
1087     if( !cachedInfo ) refreshInfo();
1088     if( lastChangePasswordTimeDate == null ) {
1089       // make it into a date . . .
1090       lastChangePasswordTimeDate = new GregorianCalendar();
1091       long longTime = ((long) lastChangePasswordTime)*1000;
1092       Date d = new Date( longTime );
1093       lastChangePasswordTimeDate.setTime( d );
1094     }
1095     return lastChangePasswordTimeDate;
1096   }
1097
1098   /**
1099    * KAS: Returns the last date and time (in UTC) the user changed 
1100    * its password.
1101    *
1102    * @return the last date and time (in UTC) the user changed its password.
1103    * @exception AFSException  If an error occurs in the native code
1104    * @see #refresh()
1105    */
1106   public int getLastChangePasswordTime() throws AFSException
1107   {
1108     if( !cachedInfo ) refreshInfo();
1109     return lastChangePasswordTime;
1110   }
1111
1112   /**
1113    * KAS: Returns the maximum lifetime of a ticket issued to this user 
1114    * (in seconds).
1115    *
1116    * @return the maximum lifetime of a ticket issued to this user (in seconds).
1117    * @exception AFSException  If an error occurs in the native code
1118    * @see #refresh()
1119    */
1120   public int getMaxTicketLifetime() throws AFSException
1121   {
1122     if( !cachedInfo ) refreshInfo();
1123     return maxTicketLifetime;
1124   }
1125
1126   /**
1127    * KAS: Returns the number of days a password is valid before it expires.  
1128    * A value of 0 indicates passwords never expire.
1129    *
1130    * @return the number of days for which a password is valid
1131    * @exception AFSException  If an error occurs in the native code
1132    * @see #refresh()
1133    */
1134   public int getDaysToPasswordExpire() throws AFSException
1135   {
1136     if( !cachedInfo ) refreshInfo();
1137     return daysToPasswordExpire;
1138   }
1139
1140   /**
1141    * KAS: Returns the number of failed login attempts this user is allowed 
1142    * before being locked out.  A value of 0 indicates there is no limit.
1143    *
1144    * @return the number of failed login attempts a user is allowed
1145    * @exception AFSException  If an error occurs in the native code
1146    * @see #refresh()
1147    */
1148   public int getFailLoginCount() throws AFSException
1149   {
1150     if( !cachedInfo ) refreshInfo();
1151     return failLoginCount;
1152   }
1153
1154   /**
1155    * KAS: Returns the amount of time (in seconds) a user is locked out when 
1156    * it exceeds the maximum number of allowable failed login attempts.  
1157    * A value of 0 indicates an infinite lockout time.
1158    *
1159    * @return the number of failed login attempts a user is allowed
1160    * @exception AFSException  If an error occurs in the native code
1161    * @see #refresh()
1162    */
1163   public int getLockTime() throws AFSException
1164   {
1165     if( !cachedInfo ) refreshInfo();
1166     return lockTime;
1167   }
1168
1169   /**
1170    * KAS: Returns the encryption key, in octal form, of this user.  An
1171    * example of a key in octal form is:    
1172    * '\040\205\211\241\345\002\023\211'.
1173    *
1174    * @return the encryption key
1175    * @exception AFSException  If an error occurs in the native code
1176    * @see #refresh()
1177    */
1178   public String getEncryptionKey() throws AFSException
1179   {
1180     if( !cachedInfo ) refreshInfo();
1181     return encryptionKey;
1182   }
1183
1184   /**
1185    * KAS: Returns the check sum of this user's key.
1186    *
1187    * @return the check sum
1188    * @exception AFSException  If an error occurs in the native code
1189    * @see #refresh()
1190    */
1191   public long getKeyCheckSum() throws AFSException
1192   {
1193     if( !cachedInfo ) refreshInfo();
1194     return keyCheckSum;
1195   }
1196
1197   /**
1198    * KAS: Returns the version number of the user's key.
1199    *
1200    * @return the key version
1201    * @exception AFSException  If an error occurs in the native code
1202    * @see #refresh()
1203    */
1204   public int getKeyVersion() throws AFSException
1205   {
1206     if( !cachedInfo ) refreshInfo();
1207     return keyVersion;
1208   }
1209
1210   /**
1211    * KAS: Returns the date and time (in UTC) at which the user stops 
1212    * being locked out. A value of 0 indicates the user is not currently 
1213    * locked out. If the user is locked out forever, the value 
1214    * will be equal to -1.
1215    *
1216    * @return the date and time (in UTC) at which the user stops being 
1217    *         locked out
1218    * @exception AFSException  If an error occurs in the native code
1219    * @see #refresh()
1220    */
1221   public int getLockedUntil() throws AFSException
1222   {
1223     if( !cachedInfo ) refreshInfo();
1224     return lockedUntil;
1225   }
1226
1227   /**
1228    * KAS: Returns the date and time at which the user stops being locked out.
1229    * A value of <code>null</code> indicates the user is not currently locked 
1230    * out. If the user is locked out forever, the value 
1231    * <code>getLockedUntil().getTime().getTime()</code> will be equal to -1.
1232    *
1233    * @return the date and time at which the user stops being locked out
1234    * @exception AFSException  If an error occurs in the native code
1235    * @see #refresh()
1236    */
1237   public GregorianCalendar getLockedUntilDate() throws AFSException
1238   {
1239     if( !cachedInfo ) refreshInfo();
1240     if( lockedUntilDate == null ) {
1241       // make it into a date . . .
1242       Date d;
1243       if( lockedUntil == 0 ) {
1244         lockedUntilDate = null;
1245       } else if( lockedUntil == -1 ) {
1246         d = new Date( lockedUntil );
1247         lockedUntilDate = new GregorianCalendar();
1248         lockedUntilDate.setTime( d );
1249       } else {
1250         d = new Date( ((long) lockedUntil)*1000 );
1251         lockedUntilDate = new GregorianCalendar();
1252         lockedUntilDate.setTime( d );
1253       }
1254     }
1255     return lockedUntilDate;
1256   }
1257
1258   /////////////// mutators ////////////////////
1259
1260   /**
1261    * PTS: Sets how many more groups this user is allowed to create.  
1262    * -1 indicates unlimited.
1263    *
1264    * @param quota    the new group creation quota
1265    */
1266   public void setGroupCreationQuota( int quota )
1267   {
1268     groupCreationQuota = quota;
1269   }
1270
1271
1272   /**
1273    * PTS: Sets who can list the status (pts examine) of this user.  
1274    * Valid values are:
1275    * <ul>
1276    * <li><code>{@link #USER_OWNER_ACCESS}</code> 
1277    *           -- only the owner has permission</li>
1278    * <li><code>{@link #USER_ANYUSER_ACCESS}</code> 
1279    *           -- any user has permission</li>
1280    * </ul>
1281    *
1282    * @param value    the value of the new list status permission
1283    * @exception AFSException      if an error occurs in the native code
1284    * @exception IllegalArgumentException   if an invalud argument is provided
1285    */
1286   public void setListStatus( int value ) throws AFSException
1287   {
1288     if( (value != this.USER_OWNER_ACCESS) && 
1289         (value != this.USER_ANYUSER_ACCESS) ) {
1290         throw new IllegalArgumentException( "Cannot set listStatus to " 
1291                                             + value );
1292     } else {
1293         listStatus = value;
1294     }
1295   }
1296
1297   /**
1298    * PTS: Sets who can list the groups owned (pts listowned) by this user.  
1299    * Valid values are:
1300    * <ul>
1301    * <li><code>{@link #USER_OWNER_ACCESS}</code> 
1302    *           -- only the owner has permission</li>
1303    * <li><code>{@link #USER_ANYUSER_ACCESS}</code> 
1304    *           -- any user has permission</li>
1305    * </ul>
1306    *
1307    * @param value    the value of the new list groups owned permission
1308    * @exception AFSException      if an error occurs in the native code
1309    * @exception IllegalArgumentException   if an invalud argument is provided
1310    */
1311   public void setListGroupsOwned( int value ) throws AFSException
1312   {
1313     if( (value != this.USER_OWNER_ACCESS) && 
1314         (value != this.USER_ANYUSER_ACCESS) ) {
1315         throw new IllegalArgumentException( "Cannot set listGroupsOwned to " 
1316                                             + value );
1317     } else {
1318         listGroupsOwned = value;
1319     }
1320   }
1321
1322   /**
1323    * PTS: Sets who can list the groups (pts membership) to which this 
1324    *      user belongs.  
1325    * Valid values are:
1326    * <ul>
1327    * <li><code>{@link #USER_OWNER_ACCESS}</code> 
1328    *           -- only the owner has permission</li>
1329    * <li><code>{@link #USER_ANYUSER_ACCESS}</code> 
1330    *           -- any user has permission</li>
1331    * </ul>
1332    *
1333    * @param value    the value of the new list membership permission
1334    * @exception AFSException      if an error occurs in the native code
1335    * @exception IllegalArgumentException   if an invalud argument is provided
1336    */
1337   public void setListMembership( int value ) throws AFSException
1338   {
1339     if( (value != this.USER_OWNER_ACCESS) && 
1340         (value != this.USER_ANYUSER_ACCESS) ) {
1341         throw new IllegalArgumentException( "Cannot set listMembership to " 
1342                                             + value );
1343     } else {
1344         listMembership = value;
1345     }
1346   }
1347
1348   /**
1349    * KAS: Sets whether or not this user has kas administrative privileges
1350    *
1351    * @param setting     whether or not this user has kas 
1352    *                    administrative privileges
1353    */
1354   public void setAdmin( boolean setting )
1355   {
1356     if ( setting ) {
1357         adminSetting = this.ADMIN;
1358     } else {
1359         adminSetting = this.NO_ADMIN;
1360     }
1361   }
1362
1363   /**
1364    * KAS: Sets whether or not TGS will issue tickets for this user
1365    *
1366    * @param setting    whether or not TGS will issue tickets for this user
1367    */
1368   public void setGrantTickets( boolean setting )
1369   {
1370     if ( setting ) {
1371         tgsSetting = this.GRANT_TICKETS;
1372     } else {
1373         tgsSetting = this.NO_GRANT_TICKETS;
1374     }
1375   }
1376
1377   /**
1378    * KAS: Sets whether or not TGS can use this users ticket for an 
1379    *      encryption key
1380    *
1381    * @param setting     whether or not TGS can use this users ticket for an 
1382    *                    encryption key
1383    */
1384   public void setEncrypt( boolean setting )
1385   {
1386     if ( setting ) {
1387         encSetting = this.ENCRYPT;
1388     } else {
1389         encSetting = this.NO_ENCRYPT;
1390     }
1391   }
1392
1393   /**
1394    * KAS: Sets whether or not the user can change their password
1395    *
1396    * @param setting     whether or not the user can change their password
1397    */
1398   public void setChangePassword( boolean setting )
1399   {
1400     if ( setting ) {
1401         cpwSetting = this.CHANGE_PASSWORD;
1402     } else {
1403         cpwSetting = this.NO_CHANGE_PASSWORD;
1404     }
1405   }
1406
1407   /**
1408    * KAS: Sets whether or not the user can reuse their password
1409    *
1410    * @param setting      whether or not the user can reuse their password
1411    */
1412   public void setReusePassword( boolean setting )
1413   {
1414     if ( setting ) {
1415         rpwSetting = this.REUSE_PASSWORD;
1416     } else {
1417         rpwSetting = this.NO_REUSE_PASSWORD;
1418     }
1419   }
1420
1421   /**
1422    * KAS: Sets the date and time the user expires.  
1423    * A <code>null</code> value indicates the user never exipres.
1424    *
1425    * @param expirationDate     the date and time the user expires
1426    */
1427   public void setUserExpiration( GregorianCalendar expirationDate )
1428   {
1429     userExpirationDate = expirationDate;
1430     if( expirationDate == null ) {
1431       userExpiration = -1;
1432     } else {
1433       Date d = expirationDate.getTime();
1434       long millis = d.getTime();
1435       userExpiration = (int) (millis/((long)1000));
1436     }
1437   }
1438
1439   /**
1440    * KAS: Sets the maximum lifetime of a ticket issued to this user 
1441    *      (in seconds).
1442    *
1443    * @param seconds    the maximum lifetime of a ticket issued to this user (in seconds).
1444    */
1445   public void setMaxTicketLifetime( int seconds )
1446   {
1447     maxTicketLifetime = seconds;
1448   }
1449
1450   /**
1451    * KAS: Sets the number of days a password is valid before it expires.  
1452    * A value of 0 indicates passwords never expire.
1453    *
1454    * @param days     the number of days for which a password is valid
1455    */
1456   public void setDaysToPasswordExpire( int days )
1457   {
1458     daysToPasswordExpire = days;
1459   }
1460
1461   /**
1462    * KAS: Sets the number of failed login attempts this user is allowed before 
1463    * being locked out.  A value of 0 indicates there is no limit.
1464    *
1465    * @param logins      the number of failed login attempts a user is allowed
1466    */
1467   public void setFailLoginCount( int logins )
1468   {
1469     failLoginCount = logins;
1470   }
1471
1472   /**
1473    * KAS: Sets the amount of time (in seconds) a user is locked out when it 
1474    * exceeds the maximum number of allowable failed login attempts. 
1475    * A value of 0 indicates an infinite lockout time.  Any nonzero value gets
1476    * rounded up to the next highest multiple of 8.5 minutes, and any value over
1477    * 36 hours gets rounded down to 36 hours.
1478    *
1479    * @param seconds      the number of failed login attempts a user is allowed
1480    */
1481   public void setLockTime( int seconds )
1482   {
1483     lockTime = seconds;
1484   }
1485
1486   /**
1487    * Sets the password of this user to something new.  Sets the key version 
1488    * to 0 automatically.
1489    *
1490    * @param newPassword     the new password for this user
1491    * @exception AFSException  If an error occurs in the native code
1492    */
1493   public void setPassword( String newPassword ) throws AFSException
1494   {
1495     this.setPassword( cell.getCellHandle(), name, newPassword );
1496   }
1497   
1498   /////////////// custom information methods ////////////////////
1499
1500   /**
1501    * Returns a <code>String</code> representation of this <code>User</code>.  
1502    * Contains the information fields and groups.
1503    *
1504    * @return a <code>String</code> representation of the <code>User</code>
1505    */
1506   protected String getInfo()
1507   {
1508     String r;
1509     try {
1510     
1511         r = "User: " + name;
1512
1513         if( pts ) {
1514             r += ", uid: " + getUID();
1515         }
1516         r += "\n";
1517         r += "\tKAS: " + isKAS() + "\tPTS: " + isPTS() + "\n";
1518
1519         if( pts ) { 
1520             r += "\towner: " + getOwner().getName() + ", uid: " 
1521                 + getOwner().getUID() + "\n";
1522             r += "\tcreator: " + getCreator().getName() + ", uid: " 
1523                 + getCreator().getUID() + "\n";
1524             r += "\tGroup creation quota: " + getGroupCreationQuota() + "\n";
1525             r += "\tGroup membership count: " + getGroupMembershipCount() 
1526                 + "\n";
1527             r += "\tList status: " + getListStatus() + "\n";
1528             r += "\tList groups owned: " + getListGroupsOwned() + "\n";
1529             r += "\tList membership: " + getListMembership() + "\n";
1530         }
1531         
1532         if( kas ) {
1533             r += "\tKAS admin status: ";
1534
1535             if( isAdmin() ) {
1536                 r += "Yes\n";
1537             } else {
1538                 r += "No\n";
1539             }
1540
1541             r += "\tTGS grant tickets: ";
1542             if( willGrantTickets() ) {
1543             r += "Yes\n";
1544             } else {
1545                 r += "No\n";
1546             }
1547             
1548             r += "\tUse key as encryption key: ";
1549             if( canEncrypt() ) {
1550                 r += "Yes\n";
1551             } else {
1552                 r += "No\n";
1553             }
1554             
1555         
1556             r += "\tCan change password: ";
1557             
1558             if( canChangePassword() ) {
1559                 r += "Yes\n";
1560             } else {
1561                 r += "No\n";
1562             }
1563             
1564             r += "\tCan reuse password: ";
1565             if( canReusePassword() ) {
1566                 r += "Yes\n";
1567             } else {
1568                 r += "No\n";
1569             }
1570
1571             if( userExpiration != 0 ) {
1572                 r += "\tExpiration date: " 
1573                     + getUserExpirationDate().getTime() + "\n";
1574             } else {
1575                 r += "\tUser never expires\n";
1576             }
1577             r += "\tLast modified " + getLastModTimeDate().getTime() 
1578                 + " by " + getLastModName() + "\n";
1579             r += "\tLast changed password " 
1580                 + getLastChangePasswordTimeDate().getTime() + "\n";
1581             r += "\tMax ticket lifetime: " + getMaxTicketLifetime() + "\n";
1582             r += "\tKey: " + getEncryptionKey() + ", version: " 
1583                 + getKeyVersion() + ", checksum: " + getKeyCheckSum() + "\n";
1584             r += "\tDays till password expires: " + getDaysToPasswordExpire() 
1585                 + "\n";
1586             r += "\tAllowed failed logins: " + getFailLoginCount() + "\n";
1587             r += "\tLock time after failed logins: " + getLockTime() + "\n";
1588             if( lockedUntil == 0 ) { 
1589                 r += "\tNot locked\n";
1590             } else if( getLockedUntilDate().getTime().getTime() == -1 ) {
1591                 r += "\tLocked forever\n";
1592             } else {
1593                 r += "\tLocked until: " + getLockedUntilDate().getTime() 
1594                     + "\n";
1595             }      
1596             
1597         }
1598         if( pts ) {
1599   
1600             r += "\tBelongs to groups: \n";
1601             
1602             String grps[] = getGroupNames();
1603             for( int i = 0; i < grps.length; i++ ) {
1604                 r += "\t\t" + grps[i] + "\n";
1605             }
1606             
1607             r += "\tOwns groups: \n";
1608             grps = getGroupsOwnedNames();
1609             for( int i = 0; i < grps.length; i++ ) {
1610                 r += "\t\t" + grps[i] + "\n";
1611             }
1612             
1613         }
1614     } catch( AFSException e ) {
1615         return e.toString();
1616     }
1617     return r;
1618   }
1619
1620   /**
1621    * Returns a <code>String</code> containing the <code>String</code> 
1622    * representations of all the groups to which this user belongs.
1623    *
1624    * @return    a <code>String</code> representation of the groups belonged to
1625    * @see       Group#toString
1626    */
1627   protected String getInfoGroups() throws AFSException
1628   {
1629         String r;
1630         r = "User: " + name + "\n\n";
1631         r += "--Member of Groups:--\n";
1632
1633         Group grps[] = getGroups();
1634         for( int i = 0; i < grps.length; i++ ) {
1635             r += grps[i].getInfo() + "\n";
1636         }
1637         return r;
1638   }
1639
1640   /**
1641    * Returns a <code>String</code> containing the <code>String</code> 
1642    * representations of all the groups that this user owns.
1643    *
1644    * @return    a <code>String</code> representation of the groups owned
1645    * @see       Group#toString
1646    */
1647   protected String getInfoGroupsOwned() throws AFSException
1648   {
1649         String r;
1650         r = "User: " + name + "\n\n";
1651         r += "--Owns Groups:--\n";
1652         Group grps[] = getGroupsOwned();
1653         for( int i = 0; i < grps.length; i++ ) {
1654             r += grps[i].getInfo() + "\n";
1655         }
1656         return r;
1657   }
1658
1659   /////////////// custom override methods ////////////////////
1660
1661   /**
1662    * Compares two User objects respective to their names and does not
1663    * factor any other attribute.    Alphabetic case is significant in 
1664    * comparing names.
1665    *
1666    * @param     user    The User object to be compared to this User instance
1667    * 
1668    * @return    Zero if the argument is equal to this User's name, a
1669    *            value less than zero if this User's name is
1670    *            lexicographically less than the argument, or a value greater
1671    *            than zero if this User's name is lexicographically
1672    *            greater than the argument
1673    */
1674   public int compareTo(User user)
1675   {
1676     return this.getName().compareTo(user.getName());
1677   }
1678
1679   /**
1680    * Comparable interface method.
1681    *
1682    * @see #compareTo(User)
1683    */
1684   public int compareTo(Object obj)
1685   {
1686     return compareTo((User)obj);
1687   }
1688
1689   /**
1690    * Tests whether two <code>User</code> objects are equal, based on their 
1691    * names.
1692    *
1693    * @param otherUser   the user to test
1694    * @return whether the specifed user is the same as this user
1695    */
1696   public boolean equals( User otherUser )
1697   {
1698     return name.equals(otherUser.getName());
1699   }
1700
1701   /**
1702    * Returns the name of this <CODE>User</CODE>
1703    *
1704    * @return the name of this <CODE>User</CODE>
1705    */
1706   public String toString()
1707   {
1708     return getName();
1709   }
1710
1711
1712   /////////////// native methods ////////////////////
1713
1714   /**
1715    * Creates the kas and pts entries for a new user.  Pass in 0 for the uid 
1716    * if pts is to automatically assign the user id.
1717    *
1718    * @param cellHandle    the handle of the cell to which the user belongs
1719    * @see Cell#getCellHandle
1720    * @param userName      the name of the user to create
1721    * @param password      the password for the new user
1722    * @param uid     the user id to assign to the user (0 to have one 
1723    *                automatically assigned)
1724    * @exception AFSException  If an error occurs in the native code
1725    */
1726   protected static native void create( int cellHandle, String userName, 
1727                                        String password, int uid )
1728         throws AFSException;
1729
1730   /**
1731    * Deletes the pts and kas entry for a user.  Deletes this user from the 
1732    * membership list of the groups to which it belonged, but does not delete 
1733    * the groups owned by this user.
1734    *
1735    * @param cellHandle    the handle of the cell to which the user belongs
1736    * @see Cell#getCellHandle
1737    * @param groupName      the name of the user to delete
1738    * @exception AFSException  If an error occurs in the native code
1739    */
1740   protected static native void delete( int cellHandle, String userName )
1741         throws AFSException;
1742
1743   /**
1744    * Unlocks a user.
1745    *
1746    * @param cellHandle    the handle of the cell to which the user belongs
1747    * @see Cell#getCellHandle
1748    * @param groupName      the name of the user to unlock
1749    * @exception AFSException  If an error occurs in the native code
1750    */
1751   protected static native void unlock( int cellHandle, String userName )
1752         throws AFSException;
1753
1754   /**
1755    * Fills in the information fields of the provided <code>User</code>.  
1756    * Fills in values based on the current pts and kas information of the user.
1757    *
1758    * @param cellHandle    the handle of the cell to which the user belongs
1759    * @see Cell#getCellHandle
1760    * @param name     the name of the user for which to get the information
1761    * @param user     the <code>User</code> object in which to fill in the 
1762    *                 information
1763    * @see User
1764    * @exception AFSException   If an error occurs in the native code
1765    */
1766   protected static native void getUserInfo( int cellHandle, String name, 
1767                                             User user ) 
1768         throws AFSException;
1769
1770   /**
1771    * Sets the information values of this AFS user to be the parameter values.  
1772    * Sets both kas and pts fields.
1773    *
1774    * @param cellHandle    the handle of the cell to which the user belongs
1775    * @see Cell#getCellHandle
1776    * @param name     the name of the user for which to set the information
1777    * @param theUser  the <code>User</code> object containing the desired 
1778    *                 information
1779    * @exception AFSException   If an error occurs in the native code
1780    */
1781   protected static native void setUserInfo( int cellHandle, String name, 
1782                                             User theUser ) 
1783         throws AFSException;
1784
1785   /**
1786    * Renames the given user.  Does not update the info fields of the kas entry
1787    *  -- the calling code is responsible for that.
1788    *
1789    * @param cellHandle    the handle of the cell to which the user belongs
1790    * @see Cell#getCellHandle
1791    * @param oldName     the name of the user to rename
1792    * @param newName     the new name for the user
1793    * @exception AFSException   If an error occurs in the native code
1794    */
1795   protected static native void rename( int cellHandle, String oldName, 
1796                                        String newName )
1797         throws AFSException;
1798
1799   /**
1800    * Sets the password of the given user.  Sets the key version to 0.
1801    *
1802    * @param cellHandle    the handle of the cell to which the user belongs
1803    * @see Cell#getCellHandle
1804    * @param userName     the name of the user for which to set the password
1805    * @param newPassword     the new password for the user
1806    * @exception AFSException   If an error occurs in the native code
1807    */
1808   protected static native void setPassword( int cellHandle, String userName, 
1809                                             String newPassword )
1810         throws AFSException;
1811
1812   /**
1813    * Begin the process of getting the groups to which the user belongs.  
1814    * Returns an iteration ID to be used by subsequent calls to 
1815    * <code>getUserGroupsNext</code> and <code>getUserGroupsDone</code>.  
1816    *
1817    * @param cellHandle    the handle of the cell to which the user belongs
1818    * @see Cell#getCellHandle
1819    * @param name          the name of the user for which to get the groups
1820    * @return an iteration ID
1821    * @exception AFSException   If an error occurs in the native code
1822    */
1823   protected static native int getUserGroupsBegin( int cellHandle, String name )
1824         throws AFSException;
1825
1826   /**
1827    * Returns the next group to which the user belongs.  Returns 
1828    * <code>null</code> if there are no more groups.
1829    *
1830    * @param iterationId   the iteration ID of this iteration
1831    * @see getUserGroupsBegin
1832    * @return the name of the next group
1833    * @exception AFSException   If an error occurs in the native code
1834    */
1835   protected static native String getUserGroupsNextString( int iterationId )
1836         throws AFSException;
1837
1838   /**
1839    * Fills the next group object of which the user belongs.  Returns 0 if there
1840    * are no more groups, != 0 otherwise.
1841    *
1842    * @param cellHandle    the handle of the cell to which the users belong
1843    * @see Cell#getCellHandle
1844    * @param iterationId   the iteration ID of this iteration
1845    * @see getUserGroupsBegin
1846    * @param theGroup   a Group object to be populated with the values of the 
1847    *                   next group
1848    * @return 0 if there are no more users, != 0 otherwise
1849    * @exception AFSException  If an error occurs in the native code
1850    */
1851   protected static native int getUserGroupsNext( int cellHandle, 
1852                                                  int iterationId, 
1853                                                  Group theGroup )
1854     throws AFSException;
1855
1856   /**
1857    * Signals that the iteration is complete and will not be accessed anymore.
1858    *
1859    * @param iterationId   the iteration ID of this iteration
1860    * @see getUserGroupsBegin
1861    * @exception AFSException   If an error occurs in the native code
1862    */
1863   protected static native void getUserGroupsDone( int iterationId )
1864         throws AFSException;
1865
1866   /**
1867    * Returns the total number of groups owned by the user.  
1868    *
1869    * @param cellHandle    the handle of the cell to which the user belongs
1870    * @param name          the name of the user for which to get the groups
1871    * @return total number of groups owned by the user
1872    * @exception AFSException   If an error occurs in the native code
1873    * @see Cell#getCellHandle
1874    */
1875   protected static native int getGroupsOwnedCount( int cellHandle, String name )
1876         throws AFSException;
1877
1878   /**
1879    * Begin the process of getting the groups that a user or group owns.  
1880    * Returns an iteration ID to be used by subsequent calls to 
1881    * <code>getGroupsOwnedNext</code> and <code>getGroupsOwnedDone</code>.  
1882    *
1883    * @param cellHandle    the handle of the cell to which the user belongs
1884    * @see Cell#getCellHandle
1885    * @param name  the name of the user or group for which to get the groups
1886    * @return an iteration ID
1887    * @exception AFSException   If an error occurs in the native code
1888    */
1889   protected static native int getGroupsOwnedBegin( int cellHandle, 
1890                                                    String name )
1891         throws AFSException;
1892
1893   /**
1894    * Returns the next group the user or group owns.  Returns <code>null</code> 
1895    * if there are no more groups.
1896    *
1897    * @param iterationId   the iteration ID of this iteration
1898    * @see getGroupsOwnedBegin
1899    * @return the name of the next group
1900    * @exception AFSException   If an error occurs in the native code
1901    */
1902   protected static native String getGroupsOwnedNextString( int iterationId )
1903         throws AFSException;
1904
1905   /**
1906    * Fills the next group object that the user or group owns.  Returns 0 if 
1907    * there are no more groups, != 0 otherwise.
1908    *
1909    * @param cellHandle    the handle of the cell to which the users belong
1910    * @see Cell#getCellHandle
1911    * @param iterationId   the iteration ID of this iteration
1912    * @see getGroupsOwnedBegin
1913    * @param theGroup   a Group object to be populated with the values of the 
1914    *                   next group
1915    * @return 0 if there are no more users, != 0 otherwise
1916    * @exception AFSException  If an error occurs in the native code
1917    */
1918   protected static native int getGroupsOwnedNext( int cellHandle, 
1919                                                   int iterationId, 
1920                                                   Group theGroup )
1921     throws AFSException;
1922
1923   /**
1924    * Signals that the iteration is complete and will not be accessed anymore.
1925    *
1926    * @param iterationId   the iteration ID of this iteration
1927    * @see getGroupsOwnedBegin
1928    * @exception AFSException   If an error occurs in the native code
1929    */
1930   protected static native void getGroupsOwnedDone( int iterationId )
1931         throws AFSException;
1932
1933   /**
1934    * Reclaims all memory being saved by the user portion of the native library.
1935    * This method should be called when no more <code>Users</code> are expected
1936    * to be used.
1937    */
1938   protected static native void reclaimUserMemory();
1939 }
1940
1941
1942
1943
1944
1945
1946
1947
1948