venus: Remove dedebug
[openafs.git] / src / JAVA / classes / org / openafs / jafs / Server.java
1 /*
2  * @(#)Server.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.io.Serializable;
27 import java.text.DecimalFormat;
28 import java.util.ArrayList;
29 import java.util.Calendar;
30 import java.util.GregorianCalendar;
31
32 /**
33  * An abstract representation of an AFS server.  It holds information about 
34  * the server, such as what its processes are.
35  * <BR><BR>
36  *
37  * Constructing an instance of a <code>Server</code> does not mean an actual 
38  * AFS server is created and added to a cell -- on the contrary, a 
39  * <code>Server</code> object must be a representation of an already existing 
40  * AFS server.  There is no way to create a new AFS server through this API.  
41  * See <a href="http://www.openafs.org">OpenAFS.org</a> for information on how
42  * to create a new AFS server.<BR><BR>
43  *
44  * A <code>Server</code> object may represent either an AFS file server,
45  * an AFS database server, or both if the same machine serves both
46  * purposes.<BR><BR>
47  *
48  * Each <code>Server</code> object has its own individual set of
49  * <code>Partition</code>s, <code>Process</code>es, and <code>Key</code>s.
50  * This represents the properties and attributes of an actual AFS server.
51  * <BR><BR>
52  *    
53  * <!--Example of how to use class-->
54  * The following is a simple example of how to construct and use a Server 
55  * object.  This example constructs a <code>Server</code> using the 
56  * <code>Cell</code> representing teh AFS cell to which the server belongs, 
57  * and prints out the names of all the partitions residing on the server.
58  * <BR><BR>
59  *
60  * <PRE>
61  * import org.openafs.jafs.Cell;
62  * import org.openafs.jafs.AFSException;
63  * import org.openafs.jafs.Partition;
64  * import org.openafs.jafs.Server;
65  * ...
66  * public class ...
67  * {
68  *   ...
69  *   private Cell cell;
70  *   private Server server;
71  *   ...
72  *   public static void main(String[] args) throws Exception
73  *   {
74  *     String username   = arg[0];
75  *     String password   = arg[1];
76  *     String cellName   = arg[2];
77  *     String serverName = arg[3];
78  * 
79  *     token = new Token(username, password, cellName);
80  *     cell   = new Cell(token);
81  *     server = new Server(serverName, cell);
82  * 
83  *     System.out.println("Partitions in Server " + server.getName() + ":");
84  *     if( server.isFileServer() ) {
85  *       Partition[] partitions = server.getPartitions();
86  *       for (int i = 0; i < partitions.length; i++) {
87  *         System.out.println(" -> " + partitions[i]);
88  *       }
89  *     }
90  *   }
91  *   ...
92  * }
93  * </PRE>
94  *
95  */
96 public class Server implements Serializable, Comparable
97 {
98   /**
99    * Used for binary restart time types.
100    */
101   private static final int RESTART_BINARY = 0;
102
103   /**
104    * Used for general restart time types.
105    */
106   private static final int RESTART_GENERAL = 1;
107
108   protected String name;
109   protected Cell cell;
110
111   protected long vosHandle;
112   protected long bosHandle;
113
114   protected boolean database;
115   protected boolean fileServer;
116
117   // these will be true if the machine is supposedly listed as a server 
118   // but that's wrong, or the machine is down 
119   protected boolean badFileServer;  
120   protected boolean badDatabase;
121
122   // String IP Address of address[0]
123   protected String[] ipAddresses;
124
125   protected ArrayList partitionNames;
126   protected ArrayList partitions;
127   protected ArrayList adminNames;
128   protected ArrayList admins;
129   protected ArrayList keys;
130   protected ArrayList processNames;
131   protected ArrayList processes;
132
133   // Storage information
134   protected int totalSpace;
135   protected int totalQuota;
136   protected int totalFreeSpace;
137   protected int totalUsedSpace;
138
139   protected ExecutableTime genRestartTime;
140   protected ExecutableTime binRestartTime;
141
142   protected boolean cachedInfo;
143
144   /**
145    * Constructs a new <CODE>Server</CODE> object instance given the 
146    * name of the AFS server and the AFS cell, represented by 
147    * <CODE>cell</CODE>, to which it belongs.  This does not actually
148    * create a new AFS server, it just represents an existing one.
149    * If <code>name</code> is not an actual AFS server, exceptions
150    * will be thrown during subsequent method invocations on this 
151    * object.
152    *
153    * @param name  the name of the server to represent
154    * @param cell  the cell to which the server belongs.
155    * @exception AFSException      If an error occurs in the native code
156    */
157   public Server( String name, Cell cell ) throws AFSException
158   {
159     this.name = name;
160     this.cell = cell;
161     
162     cachedInfo = false;
163
164     vosHandle = 0;
165     bosHandle = 0;
166
167     ipAddresses = new String[16];
168
169     partitionNames = null;
170     partitions = null;
171     adminNames = null;
172     admins = null;
173     keys = null;
174     processNames = null;
175     processes = null;
176   }
177
178   /**
179    * Constructs a new <CODE>Server</CODE> object instance given the name 
180    * of the AFS server and the AFS cell, represented by <CODE>cell</CODE>, 
181    * to which it belongs.   This does not actually
182    * create a new AFS server, it just represents an existing one.
183    * If <code>name</code> is not an actual AFS server, exceptions
184    * will be thrown during subsequent method invocations on this 
185    * object.
186    *
187    * <P> This constructor is ideal for point-in-time representation and 
188    * transient applications.  It ensures all data member values are set 
189    * and available without calling back to the filesystem at the first 
190    * request for them.  Use the {@link #refresh()} method to address any 
191    * coherency concerns.
192    *
193    * @param name               the name of the server to represent 
194    * @param cell               the cell to which the server belongs.
195    * @param preloadAllMembers  true will ensure all object members are 
196    *                           set upon construction;
197    *                           otherwise members will be set upon access, 
198    *                           which is the default behavior.
199    * @exception AFSException      If an error occurs in the native code
200    * @see #refresh
201    */
202   public Server( String name, Cell cell, boolean preloadAllMembers ) 
203       throws AFSException
204   {
205     this(name, cell);
206     if (preloadAllMembers) refresh(true);
207   }
208   
209   /**
210    * Constructs a blank <code>Server</code> object instance given the cell to 
211    * which the server belongs.  This blank object can then be passed into 
212    * other methods to fill out its properties.
213    *
214    * @param cell       the cell to which the server belongs.
215    * @exception AFSException      If an error occurs in the native code
216    */
217   Server( Cell cell ) throws AFSException
218   {
219     this( null, cell );
220   }
221
222   /*-------------------------------------------------------------------------*/
223
224   /**
225    * Refreshes the properties of this Server object instance with values 
226    * from the AFS server it represents.  All properties that have been 
227    * initialized and/or accessed will be renewed according to the values 
228    * of the AFS server this Server object instance represents.
229    *
230    * <P>Since in most environments administrative changes can be administered
231    * from an AFS command-line program or an alternate GUI application, this
232    * method provides a means to refresh the Java object representation and
233    * thereby ascertain any possible modifications that may have been made
234    * from such alternate administrative programs.  Using this method before
235    * an associated instance accessor will ensure the highest level of 
236    * representative accuracy, accommodating changes made external to the
237    * Java application space.  If administrative changes to the underlying AFS 
238    * system are only allowed via this API, then the use of this method is 
239    * unnecessary.
240    * 
241    * @exception AFSException  If an error occurs in the native code
242    */
243   public void refresh() throws AFSException
244   {
245     refresh(false);
246   }
247
248   /**
249    * Refreshes the properties of this Server object instance with values 
250    * from the AFS server it represents.  If <CODE>all</CODE> is 
251    * <CODE>true</CODE> then <U>all</U> of the properties of this Server 
252    * object instance will be set, or renewed, according to the values of the 
253    * AFS server it represents, disregarding any previously set properties.
254    *
255    * <P> Thus, if <CODE>all</CODE> is <CODE>false</CODE> then properties that 
256    * are currently set will be refreshed and properties that are not set 
257    * will remain uninitialized.
258    * See {@link #refresh()} for more information.
259    *
260    * @param all   if true set or renew all object properties; 
261    *              otherwise renew all set properties
262    * @exception AFSException  If an error occurs in the native code
263    * @see #refresh()
264    */
265   protected void refresh(boolean all) throws AFSException
266   {
267     if ( all ) {
268       refreshProcesses();
269       refreshProcessNames();
270       refreshKeys();
271       refreshAdminNames();
272       refreshAdmins();
273       refreshPartitionNames();
274       refreshPartitions(all);
275       refreshInfo();
276       refreshGeneralRestart();
277       refreshBinaryRestart();
278     } else {
279       if ( processes      != null ) refreshProcesses();
280       if ( processNames   != null ) refreshProcessNames();
281       if ( keys           != null ) refreshKeys();
282       if ( adminNames     != null ) refreshAdminNames();
283       if ( admins         != null ) refreshAdmins();
284       if ( partitionNames != null ) refreshPartitionNames();
285       if ( partitions     != null ) refreshPartitions(all);
286       if ( genRestartTime != null ) refreshGeneralRestart();
287       if ( binRestartTime != null ) refreshBinaryRestart();
288       if ( cachedInfo )             refreshInfo();
289     }
290   }
291
292   /**
293    * Refreshes the information fields of this <code>Server</code> to 
294    * reflect the current state of the AFS server.  These fields include
295    * the IP addresses and the fileserver types.
296    *
297    * @exception AFSException      If an error occurs in the native code
298    */
299   protected void refreshInfo() throws AFSException
300   {
301     getServerInfo( cell.getCellHandle(), name, this );
302     cachedInfo = true;
303   }
304
305   /**
306    * Refreshes the general restart time fields of this <code>Server</code> 
307    * to reflect the current state of the AFS server.
308    *
309    * @exception AFSException      If an error occurs in the native code
310    */
311   protected void refreshGeneralRestart() throws AFSException
312   {
313     if (genRestartTime == null) genRestartTime = new ExecutableTime();
314     getRestartTime( getBosHandle(), RESTART_GENERAL, genRestartTime );
315   }
316
317   /**
318    * Refreshes the binary restart time fields of this <code>Server</code> 
319    * to reflect the current state of the AFS server.
320    *
321    * @exception AFSException      If an error occurs in the native code
322    */
323   protected void refreshBinaryRestart() throws AFSException
324   {
325     if (binRestartTime == null) binRestartTime = new ExecutableTime();
326     getRestartTime( getBosHandle(), RESTART_BINARY, binRestartTime );
327   }
328
329   /**
330    * Obtains the most current list of <code>Partition</code> objects 
331    * of this server.
332    *
333    * @exception AFSException  If an error occurs in the native code
334    */
335   protected void refreshPartitions() throws AFSException
336   {
337     this.refreshPartitions(false);
338   }
339
340   /**
341    * Obtains the most current list of <code>Partition</code> objects of 
342    * this server.
343    *
344    * @param refreshVolumes force all volumes contained in each 
345    *                       partition to be refreshed.
346    *
347    * @exception AFSException  If an error occurs in the native code
348    */
349   protected void refreshPartitions(boolean refreshVolumes) 
350       throws AFSException
351   {
352     if (!isFileServer() || isBadFileServer()) return;
353
354     Partition currPartition;
355
356     long iterationID = getPartitionsBegin( cell.getCellHandle(), 
357                                           getVosHandle() );
358     
359     partitions = new ArrayList();
360     
361     currPartition = new Partition( this );
362     while( getPartitionsNext( iterationID, currPartition ) != 0 ) {
363       //Only volumes are necessary since volume information 
364       //is populated at time of construction
365       if (refreshVolumes) currPartition.refreshVolumes();
366       partitions.add( currPartition );
367       currPartition = new Partition( this );
368     } 
369     getPartitionsDone( iterationID );
370     totalSpace = 0;
371     totalQuota = 0;
372     totalUsedSpace = 0;
373     totalFreeSpace = 0;
374   }
375
376   /**
377    * Obtains the most current list of partition names of this server.
378    *
379    * @exception AFSException  If an error occurs in the native code
380    */
381   protected void refreshPartitionNames() throws AFSException
382   {
383     if (!isFileServer() || isBadFileServer()) return;
384
385     String currName;
386
387     long iterationID = getPartitionsBegin( cell.getCellHandle(), 
388                                           getVosHandle() );
389     
390     partitionNames = new ArrayList();
391     
392     while( ( currName = getPartitionsNextString( iterationID ) ) != null ) {
393         partitionNames.add( currName );
394     } 
395     getPartitionsDone( iterationID );
396   }
397
398   /**
399    * Obtains the most current list of bos admin names of this server.
400    *
401    * @exception AFSException  If an error occurs in the native code
402    */
403   protected void refreshAdminNames() throws AFSException
404   {
405     String currName;
406
407     long iterationID = getBosAdminsBegin( getBosHandle() );
408     
409     adminNames = new ArrayList();
410     
411     while( ( currName = getBosAdminsNextString( iterationID ) ) != null ) {
412         adminNames.add( currName );
413     } 
414     getBosAdminsDone( iterationID );
415   }
416
417   /**
418    * Obtains the most current list of admin <code>User</code> objects of 
419    * this server.
420    *
421    * @exception AFSException  If an error occurs in the native code
422    */
423   protected void refreshAdmins() throws AFSException
424   {
425     User currUser;
426
427     long iterationID = getBosAdminsBegin( getBosHandle() );
428         
429     admins = new ArrayList();
430         
431     currUser = new User( cell );
432     while( getBosAdminsNext( cell.getCellHandle(), iterationID, currUser ) 
433            != 0 ) {
434       admins.add( currUser );
435       currUser = new User( cell );
436     } 
437     getBosAdminsDone( iterationID );
438   }
439
440   /**
441    * Obtains the most current list of <code>Key</code> objects of this server.
442    *
443    * @exception AFSException  If an error occurs in the native code
444    */
445   protected void refreshKeys() throws AFSException
446   {
447     Key currKey;
448
449     long iterationID = getKeysBegin( getBosHandle() );
450     
451     keys = new ArrayList();
452     
453     currKey = new Key( this );
454     while( getKeysNext( iterationID, currKey ) != 0 ) {
455         keys.add( currKey );
456         currKey = new Key( this );
457     } 
458     getKeysDone( iterationID );
459   }
460
461   /**
462    * Obtains the most current list of process names of this server.
463    *
464    * @exception AFSException  If an error occurs in the native code
465    */
466   protected void refreshProcessNames() throws AFSException
467   {
468     String currName;
469
470     long iterationID = getProcessesBegin( getBosHandle() );
471     
472     processNames = new ArrayList();
473     
474     while( ( currName = getProcessesNextString( iterationID ) ) != null ) {
475         processNames.add( currName );
476     } 
477     getProcessesDone( iterationID );
478   }
479
480   /**
481    * Obtains the most current list of <code>Process</code> objects of 
482    * this server.
483    *
484    * @exception AFSException  If an error occurs in the native code
485    */
486   protected void refreshProcesses() throws AFSException
487   {
488     Process currProcess;
489
490     long iterationID = getProcessesBegin( getBosHandle() );
491     
492     processes = new ArrayList();
493     
494     currProcess = new Process( this );
495     while( getProcessesNext( getBosHandle(), iterationID, currProcess ) 
496            != 0 ) {
497         processes.add( currProcess );
498         currProcess = new Process( this );
499     } 
500     getProcessesDone( iterationID );
501   }
502
503   /**
504    * Add a bos admin to the UserList file of this server, in order to
505    * given the AFS user represented by <code>admin</code> full bos
506    * administrative privileges on this server.
507    *
508    * @param admin   the admin to add
509    * @exception AFSException  If an error occurs in the native code
510    */
511   public void addAdmin( User admin ) throws AFSException
512   {
513     String adminName = admin.getName();
514     
515     addBosAdmin( getBosHandle(), adminName );
516     if ( adminNames != null ) {
517         adminNames.add( adminName );
518     }
519   }
520
521   /**
522    * Remove a bos admin from the UserList file of this server, in order to
523    * take away from the AFS user represented by <code>admin</code> bos
524    * administrative privileges on this machine.
525    *
526    * @param admin   the admin to remove
527    * @exception AFSException  If an error occurs in the native code
528    */
529   public void removeAdmin( User admin ) throws AFSException
530   {
531     String adminName = admin.getName();
532     
533     removeBosAdmin( getBosHandle(), adminName );
534     if ( adminNames != null ) {
535         adminNames.remove( adminNames.indexOf( adminName ) );
536         adminNames.trimToSize();
537     }
538   }
539
540   /**
541    * Syncs this server to the VLDB.
542    *
543    * @exception AFSException  If an error occurs in the native code
544    */
545   public void syncServer() throws AFSException
546   {
547     syncServerWithVLDB( cell.getCellHandle(), getVosHandle(), -1 );
548   }
549
550   /**
551    * Syncs the VLDB to this server.
552    *
553    * @exception AFSException  If an error occurs in the native code
554    */
555   public void syncVLDB() throws AFSException
556   {
557     syncVLDBWithServer( cell.getCellHandle(), getVosHandle(), -1, false );
558   }
559
560   /**
561    * Salvages (restores consistency to) this server. Uses default values for
562    * most salvager options in order to simplify the API.
563    *
564    * @exception AFSException  If an error occurs in the native code
565    */ 
566   public void salvage() throws AFSException
567   {
568     salvage( cell.getCellHandle(), getBosHandle(), null, null, 4, null, null, 
569              false, false, false, false, false, false );
570   }
571
572   /**
573    * Starts up all bos processes on this server.
574    *
575    * @exception AFSException  If an error occurs in the native code
576    */
577   public void startAllProcesses() throws AFSException
578   {
579     startAllProcesses( getBosHandle() );
580   }
581
582   /**
583    * Stops all bos processes on this server.
584    *
585    * @exception AFSException  If an error occurs in the native code
586    */
587   public void stopAllProcesses() throws AFSException
588   {
589     stopAllProcesses( getBosHandle() );
590   }
591
592   /**
593    * Restarts all bos processes on this server.
594    *
595    * @exception AFSException  If an error occurs in the native code
596    */
597   public void restartAllProcesses() throws AFSException
598   {
599     restartAllProcesses( getBosHandle(), false );
600   }
601
602   /**
603    * Restarts bos server and all bos processes on this server.
604    *
605    * @exception AFSException  If an error occurs in the native code
606    */
607   public void restartBosServer() throws AFSException
608   {
609     restartAllProcesses( getBosHandle(), true );
610   }
611
612   /**
613    * Gets the contents of a log file, in one large <code>String</code>.  
614    * The log cannot be in AFS file space.
615    *
616    * @return a <code>String</code> containing the contents of the log file
617    * @exception AFSException  If an error occurs in the native code
618    */
619   public String getLog( String logLocation ) throws AFSException
620   {
621     return getLog( getBosHandle(), logLocation );
622   }
623
624   /**
625    * Unauthenticates all server-related tokens that have been obtained by 
626    * this <code>Server</code> object, and shuts this server object down.
627    * This method should only be called when this <code>Server</code> or any 
628    * of the objects constructed using this <code>Server</code> will not be 
629    * used anymore.  Note that this does not effect the actual AFS server;
630    * it merely closes the representation.
631    *
632    * @exception AFSException  If an error occurs in the native code
633    */
634   public void close() throws AFSException
635   {
636     if ( vosHandle != 0 ) {
637         closeVosServerHandle( vosHandle );
638     }
639     if ( bosHandle != 0 ) {
640         closeBosServerHandle( bosHandle );
641     }
642
643     cachedInfo = false;
644
645     vosHandle = 0;
646     bosHandle = 0;
647
648     partitionNames = null;
649     partitions = null;
650     adminNames = null;
651     admins = null;
652     keys = null;
653     processNames = null;
654     processes = null;
655   }
656
657   //////////////// accessors:  ////////////////////////
658
659   /**
660    * Returns the name of this server.
661    *
662    * @return the name of this server
663    */
664   public String getName()
665   {
666     return name;
667   }
668
669   /**
670    * Returns the <code>Cell</code> object with which this <code>Server</code>
671    * was constructed.  It represents the actual AFS cell to which this
672    * server belongs.
673    *
674    * @return this server's cell
675    */
676   public Cell getCell()
677   {
678     return cell;
679   }
680
681   /**
682    * Returns the number of BOS administrators assigned to this server.
683    *
684    * <P>If the total list of admins or admin names have already been 
685    * collected (see {@link #getAdmins()}), then the returning value will
686    * be calculated based upon the current list.  Otherwise, AFS will be
687    * explicitly queried for the information.
688    *
689    * <P> The product of this method is not saved, and is recalculated
690    * with every call.
691    *
692    * @return the number of admins on this server.
693    * @exception AFSException  If an error occurs 
694    *                               in any of the associated native methods
695    * @see #getAdmins()
696    * @see #getAdminNames()
697    */
698   public int getAdminCount() throws AFSException
699   {
700     if (adminNames != null) {
701       return adminNames.size();
702     } else if (admins != null) {
703       return admins.size();
704     } else {
705       return getBosAdminCount(getBosHandle());
706     }
707   }
708
709   /**
710    * Retrieves an array containing all of the admin <code>User</code> objects 
711    * associated with this <code>Server</code>, each of which are an abstract 
712    * representation of an actual bos administrator of the AFS server.  
713    * After this method is called once, it saves the array of 
714    * <code>User</code>s and returns that saved array on subsequent calls, 
715    * until the {@link #refresh()} method is called and a more current list 
716    * is obtained.
717    *
718    * @return a <code>User</code> array of the admins of the server.
719    * @exception AFSException  If an error occurs in the native code
720    * @see #refresh()
721    */
722   public User[] getAdmins() throws AFSException
723   {
724     if ( admins == null ) refreshAdmins();
725     return (User[]) admins.toArray( new User[admins.size()] );
726   }
727
728   /**
729    * Retrieves an array containing all of the names of bos admins 
730    * associated with this <code>Server</code>. After this method
731    * is called once, it saves the array of <code>String</code>s and returns
732    * that saved array on subsequent calls, until the {@link #refresh()} method
733    * is called and a more current list is obtained.
734    *
735    * @return a <code>String</code> array of the bos admin of the server.
736    * @exception AFSException  If an error occurs in the native code
737    * @see #refresh()
738    */
739   public String[] getAdminNames() throws AFSException
740   {
741     if ( adminNames == null ) refreshAdminNames();
742     return (String []) adminNames.toArray( new String[adminNames.size()] );
743   }
744
745   /**
746    * Returns the number of partitions on this server.
747    *
748    * <P>If the total list of partitions or partition names have already been 
749    * collected (see {@link #getPartitions()}), then the returning value will
750    * be calculated based upon the current list.  Otherwise, AFS will be
751    * explicitly queried for the information.
752    *
753    * <P> The product of this method is not saved, and is recalculated
754    * with every call.
755    *
756    * @return the number of partitions on this server.
757    * @exception AFSException  If an error occurs 
758    *                               in any of the associated native methods
759    * @see #getPartitions()
760    * @see #getPartitionNames()
761    */
762   public int getPartitionCount() throws AFSException
763   {
764     if (partitionNames != null) {
765       return partitionNames.size();
766     } else if (partitions != null) {
767       return partitions.size();
768     } else {
769       return getPartitionCount(cell.getCellHandle(), getVosHandle());
770     }
771   }
772
773   /**
774    * Retrieves the <CODE>Partition</CODE> object (which is an abstract 
775    * representation of an actual AFS partition of this server) designated 
776    * by <code>name</code> (i.e. "/vicepa", etc.).  If a partition by 
777    * that name does not actually exist in AFS on the server
778    * represented by this object, an {@link AFSException} will be
779    * thrown.
780    *
781    * @param name the name of the partition to retrieve
782    * @return <CODE>Partition</CODE> designated by <code>name</code>.
783    * @exception AFSException  If an error occurs in the native code
784    * @exception NullPointerException  If <CODE>name</CODE> is 
785    *                                  <CODE>null</CODE>.
786    */
787   public Partition getPartition(String name) throws AFSException
788   {
789     if (name == null) throw new NullPointerException();
790     if (isFileServer() && !isBadFileServer()) {
791       Partition partition = new Partition(name, this);
792       partition.refresh(true);
793       return partition;
794     } else {
795       //Throw "No such entry" error
796       throw new AFSException("Server is not a file server.", 363524);
797     }
798   }
799
800   /**
801    * Retrieves an array containing all of the <code>Partition</code> objects 
802    * associated with this <code>Server</code>, each of which are an abstract 
803    * representation of an actual AFS partition of the AFS server.  
804    * After this method is called once, it saves the array of 
805    * <code>Partition</code>s and returns that saved array on subsequent calls, 
806    * until the {@link #refresh()} method is called and a more current list 
807    * is obtained.
808    *
809    * @return a <code>Partition</code> array of the <code>Partition</code> 
810    *         objects of the server.
811    * @exception AFSException  If an error occurs in the native code
812    * @see #refresh()
813    */
814   public Partition[] getPartitions() throws AFSException
815   {
816     if ( partitions == null ) refreshPartitions();
817     if ( partitions != null) {
818         return (Partition []) partitions.toArray( new Partition[partitions.size()] );
819     } else {
820         return null;
821     }
822   }
823
824   /**
825    * Retrieves an array containing all of the names of partitions
826    * associated with this <code>Server</code> (i.e. "vicepa", etc.). 
827    * After this method is called once, it saves the array of 
828    * <code>String</code>s and returns that saved array on subsequent calls, 
829    * until the {@link #refresh()} method is called and a more current 
830    * list is obtained.
831    *
832    * @return a <code>String</code> array of the partitions of the server.
833    * @exception AFSException  If an error occurs in the native code
834    * @see #refresh()
835    */
836   public String[] getPartitionNames() throws AFSException
837   {
838     if ( partitionNames == null ) refreshPartitionNames();
839     return (String []) 
840         partitionNames.toArray( new String[partitionNames.size()] );
841   }
842
843   /**
844    * Retrieves the <CODE>Key</CODE> object (which is an abstract 
845    * representation of an actual AFS partition of this server) designated 
846    * by <code>nkeyVersion</code>.  If a key with 
847    * that version does not actually exist in AFS on the server
848    * represented by this object, <code>null</code> is returned.
849    *
850    * @param keyVersion the version of the key to retrieve
851    * @return <CODE>Key</CODE> designated by <code>keyVersion</code>.
852    * @exception AFSException  If an error occurs in the native code
853    */
854   public Key getKey(int keyVersion) throws AFSException
855   {
856     try {
857       Key[] keys = this.getKeys();
858       for (int i = 0; i < keys.length; i++) {
859         if (keys[i].getVersion() == keyVersion) {
860           return keys[i];
861         }
862       }
863     } catch (Exception e) {
864       e.printStackTrace();
865     }
866     return null;
867   }
868
869   /**
870    * Returns the number of keys on this server.
871    *
872    * <P>If the total list of keys has already been 
873    * collected (see {@link #getKeys()}), then the returning value will
874    * be calculated based upon the current list.  Otherwise, AFS will be
875    * explicitly queried for the information.
876    *
877    * <P> The product of this method is not saved, and is recalculated
878    * with every call.
879    *
880    * @return the number of keys on this server.
881    * @exception AFSException  If an error occurs 
882    *                               in any of the associated native methods
883    * @see #getKeys()
884    */
885   public int getKeyCount() throws AFSException
886   {
887     if (keys != null) {
888       return keys.size();
889     } else {
890       return getKeyCount(getBosHandle());
891     }
892   }
893
894   /**
895    * Retrieves an array containing all of the <code>Key</code> objects 
896    * associated with this <code>Server</code>, each of which are an abstract 
897    * representation of an actual AFS key of the AFS server.  
898    * After this method is called once, it saves the array of 
899    * <code>Key</code>s and returns that saved array on subsequent calls, 
900    * until the {@link #refresh()} method is called and a more current list 
901    * is obtained.
902    *
903    * @return a <code>Key</code> array of the <code>Key</code> objects 
904    *         of the server.
905    * @exception AFSException  If an error occurs in the native code
906    * @see #refresh()
907    */
908   public Key[] getKeys() throws AFSException
909   {
910     if ( keys == null ) refreshKeys();
911     return (Key[]) keys.toArray( new Key[keys.size()] );
912   }
913
914   /**
915    * Retrieves the <CODE>Process</CODE> object (which is an abstract 
916    * representation of an actual AFS process of this server) designated 
917    * by <code>name</code> (i.e. "kaserver", etc.).  If a process by 
918    * that name does not actually exist in AFS on the server
919    * represented by this object, an {@link AFSException} will be
920    * thrown.
921    *
922    * @param name the name of the process to retrieve
923    * @return <CODE>Process</CODE> designated by <code>name</code>.
924    * @exception AFSException  If an error occurs in the native code
925    * @exception NullPointerException  If <CODE>name</CODE> is 
926    *                                  <CODE>null</CODE>.
927    */
928   public Process getProcess(String name) throws AFSException
929   {
930     if (name == null) throw new NullPointerException();
931     //if (isFileServer() && !isBadFileServer()) {
932       Process process = new Process(name, this);
933       process.refresh(true);
934       return process;
935     //}
936   }
937
938   /**
939    * Returns the number of processes hosted by this server.
940    *
941    * <P>If the total list of processes or process names have already been 
942    * collected (see {@link #getProcesses()}), then the returning value will
943    * be calculated based upon the current list.  Otherwise, AFS will be
944    * explicitly queried for the information.
945    *
946    * <P> The product of this method is not saved, and is recalculated
947    * with every call.
948    *
949    * @return the number of processes on this server.
950    * @exception AFSException  If an error occurs 
951    *                               in any of the associated native methods
952    * @see #getProcesses()
953    * @see #getProcessNames()
954    */
955   public int getProcessCount() throws AFSException
956   {
957     if (processNames != null) {
958       return processNames.size();
959     } else if (processes != null) {
960       return processes.size();
961     } else {
962       return getProcessCount(getBosHandle());
963     }
964   }
965
966   /**
967    * Retrieves an array containing all of the <code>Process</code> objects 
968    * associated with this <code>Server</code>, each of which are an abstract 
969    * representation of an actual AFS process of the AFS server.  
970    * After this method is called once, it saves the array of 
971    * <code>Process</code>es and returns that saved array on subsequent calls, 
972    * until the {@link #refresh()} method is called and a more current list 
973    * is obtained.
974    *
975    * @return a <code>Process</code> array of the <code>Process</code> 
976    *         objects of the server.
977    * @exception AFSException  If an error occurs in the native code
978    * @see #refresh()
979    */
980   public Process[] getProcesses() throws AFSException
981   {
982     if ( processes == null ) refreshProcesses();
983     if ( processes != null) {
984         return (Process[]) processes.toArray( new Process[processes.size()] );
985     }
986     return null;
987   }
988
989   /**
990    * Retrieves an array containing all of the names of processes
991    * associated with this <code>Server</code> (i.e. "kaserver", etc.). 
992    * After this method is called once, it saves the array of 
993    * <code>String</code>s and returns that saved array on subsequent calls, 
994    * until the {@link #refresh()} method is called and a more current 
995    * list is obtained.
996    *
997    * @return a <code>String</code> array of the processes of the server.
998    * @exception AFSException  If an error occurs in the native code
999    * @see #refresh()
1000    */
1001   public String[] getProcessNames() throws AFSException
1002   {
1003     if ( processNames == null ) refreshProcessNames();
1004     return (String[]) processNames.toArray( new String[processNames.size()] );
1005   }
1006
1007   /**
1008    * Returns whether or not this server is a database machine, meaning it runs
1009    * processes such as the "kaserver" and "vlserver", and participates in 
1010    * elections.
1011    *
1012    * @return whether or not this user this server is a database machine.
1013    * @exception AFSException  If an error occurs in the native code
1014    * @see #refresh()
1015    */
1016   public boolean isDatabase() throws AFSException
1017   {
1018     if (!cachedInfo) refreshInfo();
1019     return database;
1020   }
1021
1022   /**
1023    * Returns whether or not this server is a file server machine, meaning it
1024    * runs the "fs" process and stores AFS volumes.
1025    *
1026    * @return whether or not this user this server is a file server machine.
1027    * @exception AFSException  If an error occurs in the native code
1028    * @see #refresh()
1029    */
1030   public boolean isFileServer() throws AFSException
1031   {
1032     if (!cachedInfo) refreshInfo();
1033     return fileServer;
1034   }
1035
1036   /**
1037    * Returns whether or not this server is a database machine AND 
1038    * either it isn't in reality (e.g. it's incorrectly configured) 
1039    * or it's currently down.
1040    *
1041    * @return whether or not this server is a database machine 
1042    *         AND either it isn't in reality or it's currently down
1043    * @exception AFSException  If an error occurs in the native code
1044    * @see #refresh()
1045    */
1046   public boolean isBadDatabase() throws AFSException
1047   {
1048     if (!cachedInfo) refreshInfo();
1049     return badDatabase;
1050   }
1051
1052   /**
1053    * Returns whether this machine thinks it's a file server AND 
1054    * either it isn't in reality (e.g. it's incorrectly configured) 
1055    * or it's currently down.
1056    *
1057    * @return whether or not this server is a file server machine AND 
1058    *         either it isn't in reality or it's currently down
1059    * @exception AFSException  If an error occurs in the native code
1060    * @see #refresh()
1061    */
1062   public boolean isBadFileServer() throws AFSException
1063   {
1064     if (!cachedInfo) refreshInfo();
1065     return badFileServer;
1066   }
1067
1068   /**
1069    * Returns this server's IP address as a String.  It returns it in 
1070    * dotted quad notation (i.e. 123.123.123.123).  
1071    *
1072    * @return this server's IP address as a String
1073    * @exception AFSException  If an error occurs in the native code
1074    * @see #refresh()
1075    */
1076   public String[] getIPAddresses() throws AFSException
1077   {
1078     if (!cachedInfo) refreshInfo();
1079     int n = 16;
1080     for (int i = 0; i < n; i++) {
1081       if (ipAddresses[i] == null) {
1082         n = i;
1083         break;
1084       }
1085     }
1086     String[] addresses = new String[n];
1087     System.arraycopy(ipAddresses, 0, addresses, 0, n);
1088     return addresses;
1089   }
1090
1091   /**
1092    * Returns the BOS Server's general restart time in the form of an
1093    * ExecutableTime object.  This is the time at which the bos server
1094    * restarts itself and all running processes.  After this method
1095    * is called once, it saves the time and returns
1096    * that value on subsequent calls, until the {@link #refresh()} method
1097    * is called and a more current value is obtained.
1098    *
1099    * @return the general restart time
1100    * @exception AFSException  If an error occurs in the native code
1101    * @see Server.ExecutableTime
1102    * @see #refresh()
1103    */
1104   public ExecutableTime getGeneralRestartTime() throws AFSException
1105   {
1106     if (genRestartTime == null) refreshGeneralRestart();
1107     return genRestartTime;
1108   }
1109
1110   /**
1111    * Returns the BOS Server's binary restart time in the form of an
1112    * ExecutableTime object.  This is the time at which all new or newly
1113    * modified AFS binaries are restarted.  After this method
1114    * is called once, it saves the time and returns
1115    * that value on subsequent calls, until the {@link #refresh()} method
1116    * is called and a more current value is obtained.
1117    *
1118    * @return the binary restart time
1119    * @exception AFSException  If an error occurs in the native code
1120    * @see Server.ExecutableTime
1121    * @see #refresh()
1122    */
1123   public ExecutableTime getBinaryRestartTime() throws AFSException
1124   {
1125     if (binRestartTime == null) refreshBinaryRestart();
1126     return binRestartTime;
1127   }
1128
1129   /**
1130    * Returns the total space on this server (a sum of the space of all the 
1131    * partitions associated with this server).  If this server is not a 
1132    * file server, zero will be returned. After this method
1133    * is called once, it saves the total space and returns
1134    * that value on subsequent calls, until the {@link #refresh()} method
1135    * is called and a more current value is obtained.
1136    *
1137    * @return the total space on this server
1138    * @exception AFSException  If an error occurs in the native code
1139    * @see #refresh()
1140    */
1141   public int getTotalSpace() throws AFSException
1142   {
1143     if (partitions == null) refreshPartitions(true);
1144     if (!isFileServer() || isBadFileServer()) return 0;
1145     if (totalSpace == 0) {
1146       Partition[] partitions = getPartitions();
1147       for (int i = 0; i < partitions.length; i++) {
1148         totalSpace += partitions[i].getTotalSpace();
1149       }
1150     }
1151     return totalSpace;
1152   }
1153
1154   /**
1155    * Returns the total free space on this server (a sum of the free space of 
1156    * all the partitions associated with this server).  If this server is not a 
1157    * file server, zero will be returned. After this method
1158    * is called once, it saves the total free space and returns
1159    * that value on subsequent calls, until the {@link #refresh()} method
1160    * is called and a more current value is obtained.
1161    *
1162    * @return the total free space on this server
1163    * @exception AFSException  If an error occurs in the native code
1164    * @see #refresh()
1165    */
1166   public int getTotalFreeSpace() throws AFSException
1167   {
1168     if (partitions == null) refreshPartitions(true);
1169     if (!isFileServer() || isBadFileServer()) return 0;
1170     if (totalFreeSpace == 0) {
1171       Partition[] partitions = getPartitions();
1172       for (int i = 0; i < partitions.length; i++) {
1173         totalFreeSpace += partitions[i].getTotalFreeSpace();
1174       }
1175     }
1176     return totalFreeSpace;
1177   }
1178
1179   /**
1180    * Returns the total used space on this server (a sum of the used space of 
1181    * all the partitions associated with this server).  If this server is not a 
1182    * file server, zero will be returned. After this method
1183    * is called once, it saves the total used space and returns
1184    * that value on subsequent calls, until the {@link #refresh()} method
1185    * is called and a more current value is obtained.
1186    *
1187    * @return the total space on this partition
1188    * @exception AFSException  If an error occurs in the native code
1189    * @see #getTotalSpace()
1190    * @see #getTotalFreeSpace()
1191    */
1192   public int getTotalUsedSpace() throws AFSException
1193   {
1194     if (totalUsedSpace == 0) {
1195       totalUsedSpace = getTotalSpace() - getTotalFreeSpace();
1196     }
1197     return totalUsedSpace;
1198   }
1199
1200   /**
1201    * Returns this server's vos handle.
1202    *
1203    * @return this server's vos handle
1204    * @exception AFSException  If an error occurs in the native code
1205    */
1206   protected long getVosHandle() throws AFSException
1207   {
1208     if ( vosHandle == 0 ) {
1209       vosHandle = getVosServerHandle( cell.getCellHandle(), name );
1210     }
1211     return vosHandle;
1212   }
1213
1214   /**
1215    * Returns this server's bos handle.
1216    *
1217    * @return this server's bos handle
1218    * @exception AFSException  If an error occurs in the native code
1219    */
1220   protected long getBosHandle() throws AFSException
1221   {
1222     if ( bosHandle == 0 ) {
1223       bosHandle = getBosServerHandle( cell.getCellHandle(), name );
1224     }
1225     return bosHandle;
1226   }
1227
1228   //////////////// mutators:  ////////////////////////
1229
1230   /**
1231    * Sets the BOS general restart time.   This is the time at which the bos 
1232    * server restarts itself and all running processes.
1233    *
1234    * @param executableTime  Executable time object that represents what 
1235    * the BOS Server's general restart time should be. 
1236    * @exception AFSException  If an error occurs in the native code
1237    * @see Server.ExecutableTime
1238    */
1239   public void setGeneralRestartTime( ExecutableTime executableTime ) 
1240       throws AFSException
1241   {
1242     this.setRestartTime( getBosHandle(), RESTART_GENERAL, executableTime );
1243   }
1244
1245   /**
1246    * Sets the BOS binary restart time.   This is the time at which all new 
1247    * or newly modified AFS binaries are restarted.
1248    *
1249    * @param executableTime  Executable time object that represents what 
1250    *                        the BOS Server's binary restart time should be.
1251    * @exception AFSException  If an error occurs in the native code
1252    * @see Server.ExecutableTime
1253    */
1254   public void setBinaryRestartTime( ExecutableTime executableTime ) 
1255       throws AFSException
1256   {
1257     this.setRestartTime( getBosHandle(), RESTART_BINARY, executableTime );
1258   }
1259
1260   /////////////// custom information methods ////////////////////
1261
1262   /**
1263    * Returns a <code>String</code> representation of this <code>Server</code>.
1264    * Contains the information fields and a list of partitions, admin, and 
1265    * processes.
1266    *
1267    * @return a <code>String</code> representation of the <code>Server</code>
1268    */
1269   public String getInfo()
1270   {
1271     String r;
1272     try {
1273     
1274     r = "Server: " + name + "\n";
1275
1276     r += "\tdatabase: " + isDatabase() + "\t\tfileServer: " + 
1277         isFileServer() + "\n";
1278     r += "\tbad database: " + isBadDatabase() + "\tbad fileServer: " + 
1279         isBadFileServer() + "\n";
1280     //r += "\tAddress: " + getIPAddress()[0] + "\n";
1281
1282     // restart times:
1283     r += "\tGeneral restart date: " + getGeneralRestartTime() + "\n";
1284     r += "\tBinary restart date: " + getBinaryRestartTime() + "\n";
1285     
1286     if ( isFileServer() && !isBadFileServer() ) {
1287       r += "\tPartitions:\n";
1288       
1289       String parts[] = getPartitionNames();
1290       
1291       for( int i = 0; i < parts.length; i++ ) {
1292         r += "\t\t" + parts[i] + "\n";
1293       }
1294     }
1295
1296     if ( (isDatabase() && !isBadDatabase()) || 
1297          (isFileServer() && !isBadFileServer()) ) {
1298         r += "\tAdmins:\n";
1299         
1300         String ads[] = getAdminNames();
1301     
1302         for( int i = 0; i < ads.length; i++ ) {
1303         r += "\t\t" + ads[i] + "\n";
1304         }
1305     }
1306
1307     if ( (isDatabase() && !isBadDatabase()) || 
1308          (isFileServer() && !isBadFileServer()) ) {
1309         r += "\tProcesses:\n";
1310         
1311         String pros[] = getProcessNames();
1312     
1313         for( int i = 0; i < pros.length; i++ ) {
1314         r += "\t\t" + pros[i] + "\n";
1315         }
1316     }
1317
1318     } catch( Exception e ) {
1319     return e.toString();
1320     }
1321     return r;
1322   }
1323
1324   /**
1325    * Returns a <code>String</code> containing the <code>String</code> 
1326    * representations of all the partitions of this <code>Server</code>.
1327    *
1328    * @return    a <code>String</code> representation of the partitions
1329    * @see       Partition#getInfo
1330    */
1331   public String getInfoPartitions() throws AFSException
1332   {
1333     String r;
1334     r = "Server: " + name + "\n\n";
1335     r += "--Partitions--\n";
1336
1337     Partition parts[] = getPartitions();
1338
1339     for( int i = 0; i < parts.length; i++ ) {
1340         r += parts[i].getInfo() + "\n";
1341     }
1342     return r;
1343   }
1344
1345   /**
1346    * Returns a <code>String</code> containing the <code>String</code> 
1347    * representations of all the keys of this <code>Server</code>.
1348    *
1349    * @return    a <code>String</code> representation of the keys
1350    * @see       Key#getInfo
1351    */
1352   public String getInfoKeys() throws AFSException
1353   {
1354     String r;
1355
1356     r = "Server: " + name + "\n\n";
1357     r += "--Keys--\n";
1358
1359     Key kys[] = getKeys();
1360
1361     for( int i = 0; i < kys.length; i++ ) {
1362         r += kys[i].getInfo() + "\n";
1363     }
1364
1365     return r;
1366   }
1367
1368   /**
1369    * Returns a <code>String</code> containing the <code>String</code> 
1370    * representations of all the processes of this <code>Server</code>.
1371    *
1372    * @return    a <code>String</code> representation of the processes
1373    * @see       Process#getInfo
1374    */
1375   public String getInfoProcesses() throws AFSException
1376   {
1377     String r;
1378
1379     r = "Server: " + name + "\n\n";
1380     r += "--Processes--\n";
1381
1382     Process pros[] = getProcesses();
1383
1384     for( int i = 0; i < pros.length; i++ ) {
1385         r += pros[i].getInfo() + "\n";
1386     }
1387     return r;
1388   }
1389
1390   /////////////// custom override methods ////////////////////
1391
1392   /**
1393    * Compares two Server objects respective to their names and does not
1394    * factor any other attribute.  Alphabetic case is significant in 
1395    * comparing names.
1396    *
1397    * @param     server    The Server object to be compared to this 
1398    *                      Server instance
1399    * 
1400    * @return    Zero if the argument is equal to this Server's name, a
1401    *            value less than zero if this Server's name is
1402    *            lexicographically less than the argument, or a value greater
1403    *            than zero if this Server's name is lexicographically
1404    *            greater than the argument
1405    */
1406   public int compareTo(Server server)
1407   {
1408     return this.getName().compareTo(server.getName());
1409   }
1410
1411   /**
1412    * Comparable interface method.
1413    *
1414    * @see #compareTo(Server)
1415    */
1416   public int compareTo(Object obj)
1417   {
1418     return compareTo((Server)obj);
1419   }
1420
1421   /**
1422    * Tests whether two <code>Server</code> objects are equal, based on their 
1423    * names and hosting Cell.
1424    *
1425    * @param otherServer   the Server to test
1426    * @return whether the specifed Server is the same as this Server
1427    */
1428   public boolean equals( Server otherServer )
1429   {
1430     return ( name.equals(otherServer.getName()) ) &&
1431            ( this.getCell().equals(otherServer.getCell()) );
1432   }
1433
1434   /**
1435    * Returns the name of this <CODE>Server</CODE>
1436    *
1437    * @return the name of this <CODE>Server</CODE>
1438    */
1439   public String toString()
1440   {
1441     return getName();
1442   }
1443
1444   /////////////// native methods ////////////////////
1445
1446   /**
1447    * Opens a server for administrative vos use, based on the cell handle 
1448    * provided.  Returns a vos server handle to be used by other 
1449    * methods as a means of identification.
1450    *
1451    * @param cellHandle    a cell handle previously returned by 
1452    *                      a call to {@link #getCellHandle}
1453    * @param serverName    the name of the server for which to retrieve 
1454    *                      a vos handle
1455    * @return a vos handle to the server
1456    * @exception AFSException  If an error occurs in the native code
1457    * @see #getCellHandle
1458    */
1459   protected static native long getVosServerHandle( long cellHandle, 
1460                                                   String serverName )
1461         throws AFSException;
1462
1463   /**
1464    * Closes the given currently open vos server handle.
1465    *
1466    * @param vosHandle   the vos server handle to close
1467    * @exception AFSException  If an error occurs in the native code
1468    */
1469   protected static native void closeVosServerHandle( long vosHandle ) 
1470         throws AFSException; 
1471
1472   /**
1473    * Opens a server for administrative bos use, based on the cell handle 
1474    * provided.  Returns a bos server handle to be used by other methods 
1475    * as a means of identification.
1476    *
1477    * @param cellHandle    a cell handle previously returned by a call 
1478    *                      to {@link #getCellHandle}
1479    * @param serverName    the name of the server for which to retrieve 
1480    *                      a bos handle
1481    * @return a bos handle to the server
1482    * @exception AFSException  If an error occurs in the native code
1483    * @see #getCellHandle
1484    */
1485   protected static native long getBosServerHandle( long cellHandle, 
1486                                                   String serverName )
1487         throws AFSException;
1488
1489   /**
1490    * Closes the given currently open bos server handle.
1491    *
1492    * @param bosHandle   the bos server handle to close
1493    * @exception AFSException  If an error occurs in the native code
1494    */
1495   protected static native void closeBosServerHandle( long bosHandle ) 
1496         throws AFSException; 
1497
1498   /**
1499    * Fills in the information fields of the provided <code>Server</code>. 
1500    *
1501    * @param cellHandle    the handle of the cell to which the server belongs
1502    * @see Cell#getCellHandle
1503    * @param name     the name of the server for which to get the information
1504    * @param server     the <code>Server</code> object in which to fill in 
1505    *                   the information
1506    * @see Server
1507    * @exception AFSException   If an error occurs in the native code
1508    */
1509   protected static native void getServerInfo( long cellHandle, String name, 
1510                                               Server server ) 
1511         throws AFSException;
1512
1513   /**
1514    * Returns the total number of partitions hosted by the server denoted by
1515    * <CODE>serverHandle</CODE>, if the server is a fileserver.
1516    *
1517    * @param cellHandle    the handle of the cell to which the server belongs
1518    * @param serverHandle  the vos handle of the server to which the 
1519    *                      partitions belong
1520    * @return total number of partitions
1521    * @exception AFSException  If an error occurs in the native code
1522    * @see Cell#getCellHandle
1523    * @see #getVosServerHandle
1524    */
1525   protected static native int getPartitionCount( long cellHandle, 
1526                                                   long serverHandle )
1527     throws AFSException;
1528
1529   /**
1530    * Begin the process of getting the partitions on a server.  Returns 
1531    * an iteration ID to be used by subsequent calls to 
1532    * <code>getPartitionsNext</code> and <code>getPartitionsDone</code>.  
1533    *
1534    * @param cellHandle    the handle of the cell to which the server belongs
1535    * @see Cell#getCellHandle
1536    * @param serverHandle  the vos handle of the server to which the 
1537    *                      partitions belong
1538    * @see #getVosServerHandle
1539    * @return an iteration ID
1540    * @exception AFSException  If an error occurs in the native code
1541    */
1542   protected static native long getPartitionsBegin( long cellHandle, 
1543                                                   long serverHandle )
1544     throws AFSException;
1545
1546   /**
1547    * Returns the next partition of the server.  Returns <code>null</code> 
1548    * if there are no more partitions.
1549    *
1550    * @param iterationId   the iteration ID of this iteration
1551    * @see #getPartitionsBegin
1552    * @return the name of the next partition of the server
1553    * @exception AFSException  If an error occurs in the native code
1554    */
1555   protected static native String getPartitionsNextString( long iterationId )
1556     throws AFSException;
1557
1558   /**
1559    * Fills the next partition object of the server.  Returns 0 if there
1560    * are no more partitions, != 0 otherwise
1561    *
1562    * @param iterationId   the iteration ID of this iteration
1563    * @param thePartition   the Partition object in which to fill the 
1564    *                       values of the next partition
1565    * @see #getPartitionsBegin
1566    * @return 0 if there are no more servers, != 0 otherwise
1567    * @exception AFSException  If an error occurs in the native code
1568    */
1569   protected static native int getPartitionsNext( long iterationId, 
1570                                                  Partition thePartition )
1571     throws AFSException;
1572
1573   /**
1574    * Signals that the iteration is complete and will not be accessed anymore.
1575    *
1576    * @param iterationId   the iteration ID of this iteration
1577    * @see #getPartitionsBegin
1578    * @exception AFSException  If an error occurs in the native code
1579    */
1580   protected static native void getPartitionsDone( long iterationId )
1581     throws AFSException;
1582   
1583   /**
1584    * Returns the total number of processes hosted by the server denoted by
1585    * <CODE>serverHandle</CODE>.
1586    *
1587    * @param serverHandle  the vos handle of the server to which the 
1588    *                      processes belong
1589    * @return total number of processes
1590    * @exception AFSException  If an error occurs in the native code
1591    * @see #getVosServerHandle
1592    */
1593   protected static native int getProcessCount( long serverHandle )
1594     throws AFSException;
1595
1596   /**
1597    * Begin the process of getting the processes on a server.  Returns 
1598    * an iteration ID to be used by subsequent calls to 
1599    * <code>getProcessesNext</code> and <code>getProcessesDone</code>.  
1600    *
1601    * @param serverHandle  the bos handle of the server to which the 
1602    *                      processes belong
1603    * @see #getBosServerHandle
1604    * @return an iteration ID
1605    * @exception AFSException  If an error occurs in the native code
1606    */
1607   protected static native long getProcessesBegin( long serverHandle )
1608     throws AFSException;
1609
1610   /**
1611    * Returns the next process of the server.  Returns <code>null</code> 
1612    * if there are no more processes.
1613    *
1614    * @param iterationId   the iteration ID of this iteration
1615    * @see #getProcessesBegin
1616    * @return the name of the next process of the cell
1617    * @exception AFSException  If an error occurs in the native code
1618    */
1619   protected static native String getProcessesNextString( long iterationId )
1620     throws AFSException;
1621
1622   /**
1623    * Fills the next process object of the server.  Returns 0 if there
1624    * are no more processes, != 0 otherwise.
1625    *
1626    * @param serverHandle    the handle of the BOS server that hosts the process
1627    * @see #getBosHandle
1628    * @param iterationId   the iteration ID of this iteration
1629    * @param theProcess    the Process object in which to fill the 
1630    *                      values of the next process
1631    * @see #getProcessesBegin
1632    * @return 0 if there are no more processes, != otherwise
1633    * @exception AFSException  If an error occurs in the native code
1634    */
1635   protected static native int getProcessesNext( long serverHandle, 
1636                                                 long iterationId, 
1637                                                 Process theProcess )
1638     throws AFSException;
1639
1640   /**
1641    * Signals that the iteration is complete and will not be accessed anymore.
1642    *
1643    * @param iterationId   the iteration ID of this iteration
1644    * @see #getProcessesBegin
1645    * @exception AFSException  If an error occurs in the native code
1646    */
1647   protected static native void getProcessesDone( long iterationId )
1648     throws AFSException;
1649
1650   /**
1651    * Returns the total number of keys hosted by the server denoted by
1652    * <CODE>serverHandle</CODE>.
1653    *
1654    * @param serverHandle  the vos handle of the server to which the 
1655    *                      keys belong
1656    * @return total number of keys
1657    * @exception AFSException  If an error occurs in the native code
1658    * @see #getVosServerHandle
1659    */
1660   protected static native int getKeyCount( long serverHandle )
1661     throws AFSException;
1662
1663   /**
1664    * Begin the process of getting the keys of a server.  Returns 
1665    * an iteration ID to be used by subsequent calls to 
1666    * <code>getKeysNext</code> and <code>getKeysDone</code>.  
1667    *
1668    * @param serverHandle  the bos handle of the server to which the keys belong
1669    * @see #getBosServerHandle
1670    * @return an iteration ID
1671    * @exception AFSException  If an error occurs in the native code
1672    */
1673   protected static native long getKeysBegin( long serverHandle )
1674     throws AFSException;
1675
1676   /**
1677    * Returns the next key of the server.  Returns 0 if there
1678    * are no more keys, != 0 otherwise.
1679    *
1680    * @param iterationId   the iteration ID of this iteration
1681    * @param theKey   a {@link Key Key} object, in which to fill in the
1682    *                 properties of the next key.
1683    * @see #getKeysBegin
1684    * @return 0 if there are no more keys, != 0 otherwise
1685    * @exception AFSException  If an error occurs in the native code
1686    */
1687   protected static native int getKeysNext( long iterationId, Key theKey )
1688     throws AFSException;
1689
1690   /**
1691    * Signals that the iteration is complete and will not be accessed anymore.
1692    *
1693    * @param iterationId   the iteration ID of this iteration
1694    * @see #getKeysBegin
1695    * @exception AFSException  If an error occurs in the native code
1696    */
1697   protected static native void getKeysDone( long iterationId )
1698     throws AFSException;
1699
1700   /**
1701    * Returns the total number of BOS administrators associated with the server 
1702    * denoted by <CODE>serverHandle</CODE>.
1703    *
1704    * @param serverHandle  the vos handle of the server to which the 
1705    *                      BOS admins belong
1706    * @return total number of BOS administrators
1707    * @exception AFSException  If an error occurs in the native code
1708    * @see #getVosServerHandle
1709    */
1710   protected static native int getBosAdminCount( long serverHandle )
1711     throws AFSException;
1712
1713   /**
1714    * Begin the process of getting the bos amdinistrators on a server.  Returns 
1715    * an iteration ID to be used by subsequent calls to 
1716    * <code>getBosAdminsNext</code> and <code>getBosAdminsDone</code>.  
1717    *
1718    * @param serverHandle  the bos handle of the server to which the 
1719    *                      partitions belong
1720    * @see #getBosServerHandle
1721    * @return an iteration ID
1722    * @exception AFSException  If an error occurs in the native code
1723    */
1724   protected static native long getBosAdminsBegin( long serverHandle )
1725     throws AFSException;
1726
1727   /**
1728    * Returns the next bos admin of the server.  Returns <code>null</code> 
1729    * if there are no more admins.
1730    *
1731    * @param iterationId   the iteration ID of this iteration
1732    * @see #getBosAdminsBegin
1733    * @return the name of the next admin of the server
1734    * @exception AFSException  If an error occurs in the native code
1735    */
1736   protected static native String getBosAdminsNextString( long iterationId )
1737     throws AFSException;
1738
1739   /**
1740    * Returns the next bos admin of the server.  Returns 0 if there
1741    * are no more admins, != 0 otherwise.
1742    *
1743    * @param cellHandle    the handle of the cell to which these admins belong
1744    * @see #getCellHandle
1745    * @param iterationId   the iteration ID of this iteration
1746    * @see #getBosAdminsBegin
1747    * @param theUser   the user object in which to fill the values of this admin
1748    * @return 0 if no more admins, != 0 otherwise
1749    * @exception AFSException  If an error occurs in the native code
1750    */
1751   protected static native int getBosAdminsNext( long cellHandle, 
1752                                                 long iterationId, User theUser )
1753     throws AFSException;
1754
1755   /**
1756    * Signals that the iteration is complete and will not be accessed anymore.
1757    *
1758    * @param iterationId   the iteration ID of this iteration
1759    * @see #getBosAdminsBegin
1760    * @exception AFSException  If an error occurs in the native code
1761    */
1762   protected static native void getBosAdminsDone( long iterationId )
1763     throws AFSException;
1764
1765   /**
1766    * Adds the given to name to the list of bos administrators on that server.
1767    *
1768    * @param serverHandle  the bos handle of the server to which the 
1769    *                      partitions belong
1770    * @see #getBosServerHandle
1771    * @param adminName   the name of the admin to add to the list
1772    * @exception AFSException  If an error occurs in the native code
1773    */
1774   protected static native void addBosAdmin( long serverHandle, 
1775                                             String adminName )
1776     throws AFSException;
1777
1778   /**
1779    * Removes the given to name from the list of bos administrators on 
1780    * that server.
1781    *
1782    * @param serverHandle  the bos handle of the server to which the 
1783    *                      partitions belong
1784    * @see #getBosServerHandle
1785    * @param adminName   the name of the admin to remove from the list
1786    * @exception AFSException  If an error occurs in the native code
1787    */
1788   protected static native void removeBosAdmin( long serverHandle, 
1789                                                String adminName )
1790     throws AFSException;
1791
1792   /**
1793    * Salvages (restores consistency to) a volume, partition, or server
1794    *
1795    * @param cellHandle    the handle of the cell to which the volume belongs
1796    * @see #getCellHandle
1797    * @param serverHandle  the bos handle of the server on which the 
1798    *                      volume resides
1799    * @see #getBosServerHandle
1800    * @param partitionName  the name of the partition to salvage, 
1801    *                       can be <code>null</code> only if volName is 
1802    *                       <code>null</code>
1803    * @param volName  the name of the volume to salvage, 
1804    *                 can be <code>null</code>
1805    * @param numSalvagers   the number of salvager processes to run in parallel
1806    * @param tempDir   directory to place temporary files, can be 
1807    *                  <code>null</code>
1808    * @param logFile    where salvager log will be written, can be 
1809    *                   <code>null</code>
1810    * @param inspectAllVolumes   whether or not to inspect all volumes, 
1811    *                            not just those marked as active at crash
1812    * @param removeBadlyDamaged   whether or not to remove a volume if it's 
1813    *                             badly damaged
1814    * @param writeInodes   whether or not to record a list of inodes modified
1815    * @param writeRootInodes   whether or not to record a list of AFS 
1816    *                          inodes owned by root
1817    * @param forceDirectory   whether or not to salvage an entire directory 
1818    *                         structure
1819    * @param forceBlockReads   whether or not to force the salvager to read 
1820    *                          the partition
1821    *                          one block at a time and skip badly damaged 
1822    *                          blocks.  Use if partition has disk errors
1823    */
1824   protected static native void salvage( long cellHandle, long serverHandle, 
1825                                         String partitionName, String volName,
1826                                         int numSalvagers, String tempDir, 
1827                                         String logFile, 
1828                                         boolean inspectAllVolumes,
1829                                         boolean removeBadlyDamaged, 
1830                                         boolean writeInodes, 
1831                                         boolean writeRootInodes, 
1832                                         boolean forceDirectory, 
1833                                         boolean forceBlockReads)
1834         throws AFSException;
1835
1836   /**
1837    *  Synchronizes a particular server with the volume location database.
1838    *
1839    * @param cellHandle    the handle of the cell to which the server belongs
1840    * @see #getCellHandle
1841    * @param serverHandle  the vos handle of the server     
1842    * @see #getVosServerHandle
1843    * @param partition   the id of the partition to sync, can be -1 to ignore
1844    * @exception AFSException  If an error occurs in the native code
1845    */
1846   protected static native void syncServerWithVLDB( long cellHandle, 
1847                                                    long serverHandle, 
1848                                                    int partition )
1849     throws AFSException;
1850
1851   /**
1852    *  Synchronizes the volume location database with a particular server.
1853    *
1854    * @param cellHandle    the handle of the cell to which the server belongs
1855    * @see #getCellHandle
1856    * @param serverHandle  the vos handle of the server     
1857    * @see #getVosServerHandle
1858    * @param partition   the id of the partition to sync, can be -1 to ignore
1859    * @param forceDeletion   whether or not to force the deletion of bad volumes
1860    * @exception AFSException  If an error occurs in the native code
1861    */
1862   protected static native void syncVLDBWithServer( long cellHandle, 
1863                                                    long serverHandle, 
1864                                                    int partition, 
1865                                                    boolean forceDeletion )
1866     throws AFSException;
1867
1868   /**
1869    * Retrieves a specified bos log from a server.  Right now this 
1870    * method will simply return a huge String containing the log, but 
1871    * hopefully we can devise a better way to make this work more efficiently.
1872    *
1873    * @param serverHandle  the bos handle of the server to which the key belongs
1874    * @see #getBosServerHandle
1875    * @param logLocation   the full path and name of the desired bos log
1876    * @exception AFSException  If an error occurs in the native code
1877    */
1878   protected static native String getLog( long serverHandle, String logLocation )
1879     throws AFSException;
1880
1881   /**
1882    *  Fills in the restart time fields of the given {@link Server Server} 
1883    *  object. 
1884    *
1885    * @param serverHandle  the bos handle of the server to which the key belongs
1886    * @see #getBosServerHandle
1887    * @param restartType  whether to get the general or binary restart. 
1888    *                     Acceptable values are:<ul>
1889    *                     <li>{@link RESTART_BINARY}</li>
1890    *                     <li>{@link RESTART_GENERAL}</li></ul>     
1891    * @param theServer   the <code>Server</code> object, in which to fill 
1892    *                    the restart time fields
1893    * @exception AFSException  If an error occurs in the native code
1894    */
1895   private static native void getRestartTime( long serverHandle, 
1896                                                int restartType, 
1897                                                ExecutableTime executableTime )
1898     throws AFSException;
1899
1900   /**
1901    *  Sets the restart time of the bos server.
1902    *
1903    * @param serverHandle  the bos handle of the server to which the key belongs
1904    * @see #getBosServerHandle
1905    * @param restartType  whether this is to be a general or binary restart. 
1906    *                     Acceptable values are:<ul>
1907    *                     <li>{@link RESTART_BINARY}</li>
1908    *                     <li>{@link RESTART_GENERAL}</li></ul>
1909    * @param theServer   the server object containing the desired information
1910    * @exception AFSException  If an error occurs in the native code
1911    */
1912   private static native void setRestartTime( long serverHandle, 
1913                                                int restartType, 
1914                                                ExecutableTime executableTime )
1915     throws AFSException;
1916
1917   /**
1918    * Start all server processes.
1919    *
1920    * @param serverHandle  the bos handle of the server to which the 
1921    *                      processes belong
1922    * @see #getBosServerHandle
1923    * @exception AFSException  If an error occurs in the native code
1924    */
1925   protected static native void startAllProcesses( long serverHandle )
1926     throws AFSException;
1927
1928   /**
1929    * Restart all server processes.
1930    *
1931    * @param serverHandle  the bos handle of the server to which the 
1932    *                      processes belong
1933    * @see #getBosServerHandle
1934    * @param restartBosServer   whether or not to restart the bos server as well
1935    * @exception AFSException  If an error occurs in the native code
1936    */
1937   protected static native void restartAllProcesses( long serverHandle, 
1938                                                     boolean restartBosServer )
1939     throws AFSException;
1940
1941   /**
1942    * Stop all server processes.
1943    *
1944    * @param serverHandle  the bos handle of the server to which the 
1945    *                      processes belong
1946    * @see #getBosServerHandle
1947    * @exception AFSException  If an error occurs in the native code
1948    */
1949   protected static native void stopAllProcesses( long serverHandle )
1950     throws AFSException;
1951
1952   /**
1953    * Reclaims all memory being saved by the server portion of the native 
1954    * library. This method should be called when no more <code>Server</code> 
1955    * objects are expected to be used.
1956    */
1957   protected static native void reclaimServerMemory();
1958
1959   /*====================================================================*/
1960   /* INNER CLASSES  */
1961   /*====================================================================*/
1962   public static final class ExecutableTime implements Serializable
1963   {
1964     public static final short NEVER = 0;
1965     public static final short NOW = 1;
1966
1967     public static final short EVERYDAY  = -1;
1968     public static final short SUNDAY    = 0;
1969     public static final short MONDAY    = 1;
1970     public static final short TUESDAY   = 2;
1971     public static final short WEDNESDAY = 3;
1972     public static final short THURSDAY  = 4;
1973     public static final short FRIDAY    = 5;
1974     public static final short SATURDAY  = 6;
1975
1976     static final DecimalFormat formatter = 
1977         (DecimalFormat)DecimalFormat.getInstance();
1978
1979     private short second;
1980     private short minute;
1981     private short hour;
1982     private short day;
1983     private boolean now;
1984     private boolean never;
1985
1986     static
1987     {
1988       formatter.applyPattern("00");
1989     }
1990
1991     /**
1992      * Internal constructor used to construct an empty object that will 
1993      * be passed to JNI for member synchronization of the BOS Server 
1994      * executable time this object represents.
1995      */
1996     ExecutableTime()
1997     {
1998       this.second = (short) 0;
1999       this.minute = (short) 0;
2000       this.hour = (short) 0;
2001       this.day = (short) -1;
2002       this.now = false;
2003       this.never = false;
2004     }
2005
2006     /**
2007      * Constructs an <code>ExecutableTime</code> object that represents either 
2008      * a "<CODE>now</CODE>" <B>or</B> "<CODE>never</CODE>" BOS Executable 
2009      * Restart Time. 
2010      *
2011      * <P>Valid values for the <CODE>type</CODE> parameter are ExecutableTime.NOW
2012      * or ExecutableTime.NEVER.  If a value other than these two is used an
2013      * IllegalArgumentException will be thrown.
2014      *
2015      * @param type   either ExecutableTime.NOW or ExecutableTime.NEVER
2016      * @exception    IllegalArgumentException
2017      *               If a value other than ExecutableTime.NOW or 
2018      *               ExecutableTime.NEVER is used for the <CODE>type</CODE> 
2019      *               parameter.
2020      * @see #isNow()
2021      * @see #isNever()
2022      * @see #Server.ExecutableTime(short, short, short)
2023      */
2024     public ExecutableTime(short type) throws IllegalArgumentException
2025     {
2026       if (type == NOW) {
2027         this.now = true;
2028         this.never = false;
2029       } else if (type == NEVER) {
2030         this.now = false;
2031         this.never = true;
2032       } else {
2033         throw new IllegalArgumentException("You must specify either " + 
2034                                            "ExecutableTime.NOW or " + 
2035                                            "ExecutableTime.NEVER when " +
2036                                            "using this constructor.");
2037       }
2038       this.second = (short) 0;
2039       this.minute = (short) 0;
2040       this.hour = (short) 0;
2041       this.day = (short) -1;
2042     }
2043
2044     /**
2045      * Constructs an <code>ExecutableTime</code> object that may be used to 
2046      * represent a <U>daily</U> BOS Executable Restart Time of a process. 
2047      *
2048      * @param second   the second field for this representation of a 
2049      *                 BOS Server restart time value (range: 0-59)
2050      * @param minute   the minute field for this representation of a 
2051      *                 BOS Server restart time value (range: 0-59)
2052      * @param hour     the hour field for this representation of a BOS 
2053      *                 Server restart time value (range: 0-23)
2054      * @exception      IllegalArgumentException
2055      *                 If any of the parameters values are out of range 
2056      *                 of their respective fields.
2057      * @see #Server.ExecutableTime(short, short, short, short)
2058      * @see #getSecond()
2059      * @see #getMinute()
2060      * @see #getHour()
2061      */
2062     public ExecutableTime(short second, short minute, short hour)
2063       throws IllegalArgumentException
2064     {
2065       this(second, minute, hour, ExecutableTime.EVERYDAY);
2066     }
2067
2068     /**
2069      * Constructs an <code>ExecutableTime</code> object that may be used to 
2070      * represent the BOS Executable Restart Time of a process. 
2071      *
2072      * @param second   the second field for this representation of a 
2073      *                 BOS Server restart time value (range: 0-59)
2074      * @param minute   the minute field for this representation of a 
2075      *                 BOS Server restart time value (range: 0-59)
2076      * @param hour     the hour field for this representation of a BOS 
2077      *                 Server restart time value (range: 0-23)
2078      * @param day      the day field for this representation of a BOS 
2079      *                 Server restart time value.<BR><UL>Valid values include:
2080      *                 <CODE>ExecutableTime.EVERYDAY</CODE> (see also {@link 
2081      *                 #Server.ExecutableTime(short, short, short)})<BR>
2082      *                 <CODE>
2083      *                 ExecutableTime.SUNDAY<BR>
2084      *                 ExecutableTime.MONDAY<BR>
2085      *                 ExecutableTime.TUESDAY<BR>
2086      *                 ExecutableTime.WEDNESDAY<BR>
2087      *                 ExecutableTime.THURSDAY<BR>
2088      *                 ExecutableTime.FRIDAY<BR>
2089      *                 ExecutableTime.SATURDAY<BR>
2090      *                 </CODE></UL>
2091      * @exception      IllegalArgumentException
2092      *                 If any of the parameters values are out of range 
2093      *                 of their respective fields.
2094      * @see #Server.ExecutableTime(short, short, short)
2095      * @see #getSecond()
2096      * @see #getMinute()
2097      * @see #getHour()
2098      * @see #getDay()
2099      */
2100     public ExecutableTime(short second, short minute, short hour, short day) 
2101     {
2102       if ( (0 > second || second > 59) ||
2103            (0 > minute || minute > 59) ||
2104            (0 > hour || hour > 24) ||
2105            (-1 > day || day > 6) ) {
2106         throw new IllegalArgumentException("One of the specified values " + 
2107                                         "are invalid.");
2108       }
2109       this.second = second;
2110       this.minute = minute;
2111       this.hour = hour;
2112       this.day = day;
2113       this.now = false;
2114       this.never = false;
2115     }
2116
2117     /**
2118      * Returns the second of this ExecutableTime object.
2119      *
2120      * @return the second of this ExecutableTime object.
2121      * @exception IllegalStateException 
2122      *            If the executable time this object represents has a value of
2123      *            "<CODE>now</CODE>" or "<CODE>never</CODE>".
2124      */
2125     public short getSecond() throws IllegalStateException 
2126     {
2127       if (now || never) {
2128         throw new IllegalStateException("Executable time is set to 'now' or" +
2129                                                         " 'never'.");
2130       }
2131       return second;
2132     }
2133
2134     /**
2135      * Returns the minute of this ExecutableTime object.
2136      *
2137      * @return the minute of this ExecutableTime object.
2138      * @exception IllegalStateException 
2139      *            If the executable time this object represents has a value of
2140      *            "<CODE>now</CODE>" or "<CODE>never</CODE>".
2141      */
2142     public short getMinute() throws IllegalStateException 
2143     {
2144       if (now || never) {
2145         throw new IllegalStateException("Executable time is set to 'now' or" + 
2146                                         " 'never'.");
2147       }
2148       return minute;
2149     }
2150
2151     /**
2152      * Returns the hour of this ExecutableTime object, in 24 hour time.
2153      *
2154      * @return the hour of this ExecutableTime object.
2155      * @exception IllegalStateException
2156      *            If the executable time this object represents has a value of
2157      *            "<CODE>now</CODE>" or "<CODE>never</CODE>".
2158      */
2159     public short getHour() throws IllegalStateException
2160     {
2161       if (now || never) {
2162         throw new IllegalStateException("Executable time is set to 'now' or" + 
2163                                                         " 'never'.");
2164       }
2165       return hour;
2166     }
2167
2168     /**
2169      * Returns a numeric representation of the day of this ExecutableTime 
2170      * object. If it is daily, the value of ExecutableTime.EVERYDAY is returned.
2171      * 
2172      * <P>Possible return values are:<BR>
2173      * <CODE>
2174      * ExecutableTime.EVERYDAY<BR>
2175      * <BR>
2176      * ExecutableTime.SUNDAY<BR>
2177      * ExecutableTime.MONDAY<BR>
2178      * ExecutableTime.TUESDAY<BR>
2179      * ExecutableTime.WEDNESDAY<BR>
2180      * ExecutableTime.THURSDAY<BR>
2181      * ExecutableTime.FRIDAY<BR>
2182      * ExecutableTime.SATURDAY<BR>
2183      * </CODE>
2184      *
2185      * @return    a numeric representation of the day of this ExecutableTime 
2186      *            object.
2187      * @exception IllegalStateException
2188      *            If the executable time this object represents has a value of
2189      *            "<CODE>now</CODE>" or "<CODE>never</CODE>".
2190      */
2191     public short getDay() throws IllegalStateException
2192     {
2193       if (now || never) {
2194         throw new IllegalStateException("Executable time is set to 'now' or" + 
2195                                                         " 'never'.");
2196       }
2197       return day;
2198     }
2199
2200     /**
2201      * Returns a String representation, name for the day of the week or 
2202      * "Everyday", of this object's day property.
2203      * 
2204      * <P>Possible return values are:
2205      * <PRE>
2206      * Sunday
2207      * Monday
2208      * Tuesday
2209      * Wednesday
2210      * Thursday
2211      * Friday
2212      * Saturday
2213      * 
2214      * Everyday
2215      * </PRE>
2216      *
2217      * @return the day of this ExecutableTime object.
2218      * @exception IllegalStateException
2219      *            If the executable time this object represents has a value of
2220      *            "<CODE>now</CODE>" or "<CODE>never</CODE>".
2221      * @see #getDay()
2222      */
2223     public String getDayString() throws IllegalStateException
2224     {
2225       switch (getDay())
2226       {
2227         case 0:
2228             return "Sunday";
2229         case 1:
2230             return "Monday";
2231         case 2:
2232             return "Tuesday";
2233         case 3:
2234             return "Wednesday";
2235         case 4:
2236             return "Thursday";
2237         case 5:
2238             return "Friday";
2239         case 6:
2240             return "Saturday";
2241         default:
2242             return "Everyday";
2243       }
2244     }
2245
2246     /**
2247      * Returns whether or not the BOS restart time, represented by this 
2248      * ExecutableTime object, is set to "<CODE>now</CODE>" or not.  
2249      * This means that at some point in the past, when someone set it to 
2250      * "<CODE>now</CODE>", the bosserver restarted all its processes,
2251      * and never again.
2252      *
2253      * @return whether or not the restart time is "<CODE>now</CODE>"
2254      */
2255     public boolean isNow()
2256     {
2257       return now;
2258     }
2259
2260     /**
2261      * Returns the second of this ExecutableTime object.
2262      *
2263      * @return the second of this ExecutableTime object.
2264      */
2265     /**
2266      * Returns whether or not the BOS restart time, represented by this 
2267      * ExecutableTime object, is set to "<CODE>never</CODE>" or not.  
2268      * This means that the bosserver will never restart its processes.
2269      *
2270      * @return whether or not the restart time is "<CODE>never</CODE>"
2271      */
2272     public boolean isNever()
2273     {
2274       return never;
2275     }
2276
2277     /**
2278      * Tests whether two <code>ExecutableTime</code> objects are equal, 
2279      * based on a
2280      * comparison of each of their respective properties. If 
2281      * "<CODE>now</CODE>" or "<CODE>never</CODE>" is set in either object, 
2282      * only those properties are analyzed.
2283      *
2284      * @param time   the ExecutableTime to test against
2285      * @return whether the specifed ExecutableTime is the same as this 
2286      * ExecutableTime as defined above
2287      */
2288     public boolean equals( ExecutableTime time )
2289     {
2290       boolean same = false;
2291       try {
2292         same = ( (second == time.getSecond()) &&
2293                  (minute == time.getMinute()) &&
2294                  (hour   == time.getHour()  ) &&
2295                  (day    == time.getDay()   ) );
2296       } catch (Exception e) {
2297         same = ( (now    == time.isNow()    ) &&
2298                  (never  == time.isNever()  ) );
2299
2300       }
2301       return same;
2302     }
2303
2304     /**
2305      * Returns the String representation of time value of this 
2306      * <CODE>ExecutableTime</CODE> object.
2307      *
2308      * <P> Possible return values:<BR>
2309      * <LI> "Now"<BR>
2310      * <LI> "Never"<BR>
2311      * <LI> Day and time string in the form:<BR>&nbsp;&nbsp;&nbsp;&nbsp; 
2312      * <CODE>&#60;day&#62; at &#60;hh&#62;:&#60;MM&#62;[:&#60;ss&#62;]</CODE>
2313      * <BR><BR>
2314      *
2315      * <B>Example Return Values:</B><PRE>
2316      * Sunday at 04:00
2317      * Sunday at 05:10:30
2318      * Everyday at 20:00</PRE>
2319      *
2320      * @return the String representation of this <CODE>ExecutableTime</CODE> 
2321      * object
2322      */
2323     public String toString()
2324     {
2325       if (now) {
2326         return "Now";
2327       } else if (never) {
2328         return "Never";
2329       } else {
2330         try {
2331           if (second != 0) {
2332             return getDayString() + " at " + 
2333                 ExecutableTime.formatter.format(hour) + ":" + 
2334                 ExecutableTime.formatter.format(minute) + ":" + 
2335                 ExecutableTime.formatter.format(second);
2336           } else {
2337             return getDayString() + " at " + 
2338                 ExecutableTime.formatter.format(hour) + ":" + 
2339                 ExecutableTime.formatter.format(minute);
2340           }
2341         } catch (Exception e) {
2342           return "(unknown)";
2343         }
2344       }
2345     }
2346
2347   }
2348   /*====================================================================*/
2349
2350 }
2351
2352
2353
2354
2355
2356
2357