dest_only_libafs: only_libafs dest_dirs
$(MAKE) build TARGET=libafs COMPILE_PART2B=dest
-${TOP_INCDIR} ${TOP_INCDIR}/afs ${TOP_LIBDIR}:
+${TOP_INCDIR} ${TOP_INCDIR}/afs ${TOP_LIBDIR} ${TOP_JLIBDIR}:
mkdir -p $@
install_dirs: force
echo Not building MT libadmin for ${SYS_NAME} ;; \
esac
+libjafs: libadmin
+ case ${SYS_NAME} in \
+ alpha_dux*|sgi_*|sun4x_*|rs_aix*|*linux*|hp_ux110) \
+ ${COMPILE_PART1} JAVA/libjafs ${COMPILE_PART2} ;; \
+ *) \
+ echo Not building MT libjafs for ${SYS_NAME} ;; \
+ esac
+
+libjafsadm: libjafs
+
+jafs: libjafs
+
+jafsadm: libjafsadm
+
finale: project cmd comerr afsd allrcmds butc tbutc @ENABLE_KERNEL_MODULE@ libuafs audit kauth log package \
ptserver scout bu_utils ubik uss bozo vfsck volser \
venus update xstat afsmonitor dauth rxdebug libafsrpc \
-${COMPILE_PART1} libadmin/cfg ${COMPILE_CLEAN}
-${COMPILE_PART1} libadmin/test ${COMPILE_CLEAN}
-${COMPILE_PART1} libadmin/samples ${COMPILE_CLEAN}
+ -${COMPILE_PART1} JAVA/libjafs ${COMPILE_CLEAN}
-${COMPILE_PART1} finale ${COMPILE_CLEAN}
-${COMPILE_PART1} mpp ${COMPILE_CLEAN}
-${COMPILE_PART1} package ${COMPILE_CLEAN}
-${COMPILE_PART1} libuafs ${COMPILE_CLEAN}
-(cd src/libafs; /bin/rm -rf afs afsint config rx)
-(cd src/libuafs; /bin/rm -rf afs afsint config rx des)
- -/bin/rm -rf ${TOP_INCDIR} ${TOP_LIBDIR}
+ -/bin/rm -rf ${TOP_INCDIR} ${TOP_LIBDIR} ${TOP_JLIBDIR}
-/bin/rm -rf libafs_tree ${SYS_NAME}
src/libadmin/samples/Makefile \
src/libadmin/test/Makefile \
src/libadmin/vos/Makefile \
+ src/JAVA/libjafs/Makefile \
src/libafs/Makefile \
src/libafs/Makefile.common \
src/libafs/MakefileProto.${MKAFS_OSTYPE} \
allrcmds: project rcp rlogind
+
+
src/ftpd43+/Makefile \
src/gtx/Makefile \
src/inetd/Makefile \
+src/JAVA/libjafs/Makefile \
src/kauth/test/Makefile \
src/kauth/Makefile \
src/libacl/test/Makefile \
--- /dev/null
+#-----------------------------------------------------------
+# Custom UFiler Error Codes
+#-----------------------------------------------------------
+UNKNOWN = Unknown error.
+SPECIAL_CASE = Special case error.
+GENERAL_FAILURE = Operation returned unsuccessful.
+
+E1000 = Data requested does not exist or is null.
+E1001 = User session is invalid
+E1002 = Session has expired, please login again
+E1003 = Operation aborted
+E1004 = Operation was forced to abort
+
+#-----------------------------------------------------------
+# Standard UNIX Error Codes
+#-----------------------------------------------------------
+E1 = Operation not permitted
+E2 = No such file or directory
+E3 = No such process
+E4 = Interrupted system call
+E5 = I/O error
+E6 = No such device or address
+E7 = Arg list too long
+E8 = Exec format error
+E9 = Bad file number
+E10 = No child processes
+E11 = Try again
+E12 = Out of memory
+E13 = Permission denied
+E14 = Bad address
+E15 = Block device required
+E16 = Device or resource busy
+E17 = File exists
+E18 = Cross-device link
+E19 = No such device
+E20 = Not a directory
+E21 = Is a directory
+E22 = Invalid argument
+E23 = File table overflow
+E24 = Too many open files
+E25 = Not a typewriter
+E26 = Text file busy
+E27 = File too large
+E28 = No space left on device
+E29 = Illegal seek
+E30 = Read-only file system
+E31 = Too many links
+E32 = Broken pipe
+E33 = Math argument out of domain of func
+E34 = Math result not representable
+E35 = Resource deadlock would occur
+E36 = File name too long
+E37 = No record locks available
+E38 = Function not implemented
+E39 = Directory not empty
+E40 = Too many symbolic links encountered
+E41 = Operation would block
+E42 = No message of desired type
+E43 = Identifier removed
+E44 = Channel number out of range
+E45 = Level 2 not synchronized
+E46 = Level 3 halted
+E47 = Level 3 reset
+E48 = Link number out of range
+E49 = Protocol driver not attached
+E50 = No CSI structure available
+E51 = Level 2 halted
+E52 = Invalid exchange
+E53 = Invalid request descriptor
+E54 = Exchange full
+E55 = No anode
+E56 = Invalid request code
+E57 = Invalid slot
+E58 = Dead lock
+E59 = Bad font file format
+E60 = Device not a stream
+E61 = No data available
+E62 = Timer expired
+E63 = Out of streams resources
+E64 = Machine is not on the network
+E65 = Package not installed
+E66 = Object is remote
+E67 = Link has been severed
+E68 = Advertise error
+E69 = Srmount error
+E70 = Communication error on send
+E71 = Protocol error
+E72 = Multihop attempted
+E73 = RFS specific error
+E74 = Not a data message
+E75 = Value too large for defined data type
+E76 = Name not unique on network
+E77 = File descriptor in bad state
+E78 = Remote address changed
+E79 = Can not access a needed shared library
+E80 = Accessing a corrupted shared library
+E81 = .lib section in a.out corrupted
+E82 = Attempting to link in too many shared libraries
+E83 = Cannot exec a shared library directly
+E84 = Illegal byte sequence
+E85 = Interrupted system call should be restarted
+E86 = Streams pipe error
+E87 = Too many users
+E88 = Socket operation on non-socket
+E89 = Destination address required
+E90 = Message too long
+E91 = Protocol wrong type for socket
+E92 = Protocol not available
+E93 = Protocol not supported
+E94 = Socket type not supported
+E95 = Operation not supported on transport endpoint
+E96 = Protocol family not supported
+E97 = Address family not supported by protocol
+E98 = Address already in use
+E99 = Cannot assign requested address
+E100 = Network is down
+E101 = Network is unreachable
+E102 = Network dropped connection because of reset
+E103 = Software caused connection abort
+E104 = Connection reset by peer
+E105 = No buffer space available
+E106 = Transport endpoint is already connected
+E107 = Transport endpoint is not connected
+E108 = Cannot send after transport endpoint shutdown
+E109 = Too many references: cannot splice
+E110 = Connection timed out
+E111 = Connection refused
+E112 = Host is down
+E113 = No route to host
+E114 = Operation already in progress
+E115 = Operation now in progress
+E116 = Stale NFS file handle
+E117 = Structure needs cleaning
+E118 = Not a XENIX named type file
+E119 = No XENIX semaphores available
+E120 = Is a named type file
+E121 = Remote I/O error
+E122 = Quota exceeded
+E123 = No medium found
+E124 = Wrong medium type
+#-----------------------------------------------------------
+# Error Codes for acfg_errors
+#-----------------------------------------------------------
+E70354688 = mysterious failure
+E70354689 = could not find entry
+E70354690 = do not know that information
+E70354691 = line appears before a cell has been defined
+E70354692 = syntax error
+E70354693 = a database file is missing
+E70354694 = no more entries
+#-----------------------------------------------------------
+# Error Codes for ktc_errors
+#-----------------------------------------------------------
+E11862784 = an unexpected error was encountered
+E11862785 = a buffer was too small for the response
+E11862786 = an invalid argument was passed in
+E11862787 = no such entry
+E11862788 = a pioctl failed
+E11862789 = AFS kernel pioctl doesn't exist
+E11862790 = unknown cell was passed to SetToken
+E11862791 = Cache Manager is not initialized / afsd is not running
+E11862792 = failed to send or receive session key via remote procedure call
+E11862793 = Cache Manager RPC server is not responding
+#-----------------------------------------------------------
+# Error Codes for boserr
+#-----------------------------------------------------------
+E39424 = process not active
+E39425 = no such entity
+E39426 = can't do operation now
+E39427 = entity already exists
+E39428 = failed to create entity
+E39429 = index out of range
+E39430 = you are not authorized for this operation
+E39431 = syntax error in create parameter
+E39432 = I/O error
+E39433 = network problem
+E39434 = unrecognized bnode type
+E39435 = kvno already used - have to remove existing kvno's before reuse
+E39436 = this function requires encrypted input, use a newer client program
+#-----------------------------------------------------------
+# Error Codes for butc_errs
+#-----------------------------------------------------------
+E156566272 = error in dump/restore process
+E156566273 = ungraceful abort
+E156566274 = the process has already been aborted
+E156566275 = unable to end dump/restore since work in progress
+E156566276 = some of the dump/restores were unsuccessful
+E156566277 = could not abort the process
+E156566278 = the process was aborted by request
+E156566279 = scan tape resulted in failure
+E156566280 = No dump task with specified ID
+E156566281 = No tasks active
+E156566282 = the volume was not found on tape
+E156566283 = unexpected EOF encountered on tape
+E156566284 = missing file trailer on tape
+E156566285 = unexpected tape label
+E156566286 = tape was unusable
+E156566287 = corrupted volume header on tape
+E156566288 = internal error
+E156566289 = corruption in internal queue data structures
+E156566290 = memory allocation failure
+E156566291 = access denied
+E156566292 = tape requested to be skipped
+E156566293 = invalid task
+#-----------------------------------------------------------
+# Error Codes for butm_errs
+#-----------------------------------------------------------
+E156568832 = interface incompatible
+E156568833 = there is not an opened tape
+E156568834 = multiple simultaneous opens not permitted
+E156568835 = can't open tape
+E156568836 = error during tape close
+E156568837 = tape I/O error
+E156568838 = write operation on read-only tape
+E156568839 = operation inappropriate in this context
+E156568840 = read file ended before all data read
+E156568841 = write a zero length file
+E156568842 = end of tape
+E156568843 = problem reading configuration
+E156568844 = argument too long or out of range
+E156568845 = unexpected end of volume data
+E156568846 = appended tape label
+E156568847 = end of dump
+E156568848 = tape device error
+E156568849 = end-of-file marker
+E156568850 = unexpected tape datablock
+E156568851 = no label on tape
+E156568852 = cannot position within the file
+#-----------------------------------------------------------
+# Error Codes for butx_errs
+#-----------------------------------------------------------
+E156571648 = Version 1
+E156571649 = XBSA couldn't mount shared library
+E156571650 = XBSA handle already initialized
+E156571651 = XBSA invalid serverType specified
+E156571652 = XBSA invalid serverName specified
+E156571653 = XBSA invalid bsaObjectOwner specified
+E156571654 = XBSA invalid appObjectOwner specified
+E156571655 = XBSA invalid secToken specified
+E156571656 = XBSA invalid objectSpaceName specified
+E156571657 = XBSA invalid pathName specified
+E156571658 = XBSA invalid bufferSize specified
+E156571659 = XBSA invalid dataBuffer specified
+E156571660 = XBSA invalid lGName specified
+E156571661 = XBSA invalid objectDescription specified
+E156571662 = XBSA invalid objectInfo specified
+E156571663 = XBSA version mismatch
+E156571664 = XBSA unable to mount the XBSA library
+E156571665 = XBSA initialization of the XBSA interface failed
+E156571666 = XBSA begin transaction failed
+E156571667 = XBSA has not been initialized, no handle
+E156571668 = XBSA end transaction failed
+E156571669 = XBSA terminate session failed
+E156571670 = XBSA query object failed
+E156571671 = XBSA get object failed
+E156571672 = XBSA end data failed
+E156571673 = XBSA create object failed
+E156571674 = XBSA delete object failed
+E156571675 = XBSA send data failed
+E156571676 = XBSA get data failed
+E156571677 = XBSA get environment failed
+E156571678 = XBSA volume to delete not found
+#-----------------------------------------------------------
+# Error Codes for bucoord_errs
+#-----------------------------------------------------------
+E156288000 = Unacceptable user supplied argument
+E156288001 = Object has been updated
+E156288002 = Search matched more than one item
+E156288003 = Can't allocate working memory
+E156288004 = Can't get cell configuration information
+E156288005 = Specified item already exists
+E156288006 = Error in configuration parameters
+E156288007 = No such volume set
+E156288008 = No such volume entry
+E156288009 = Volume set already exists
+E156288010 = No such server
+E156288011 = No such partition
+E156288012 = Version number mismatch
+E156288013 = Lock has not been acquired
+E156288014 = Internal error
+E156288015 = No such host/port entry
+#-----------------------------------------------------------
+# Error Codes for budb_errs
+#-----------------------------------------------------------
+E156303872 = dump with specified id already exists
+E156303873 = no dump matching the id was found
+E156303874 = no dump matching the name was found
+E156303875 = no tape matching the name was found
+E156303876 = no volume matching the name was found
+E156303877 = entry doesn't exist
+E156303878 = reference to a tape not being used
+E156303879 = dump of database failed
+E156303880 = access to database denied
+E156303881 = incompatible version numbers
+E156303882 = argument too long or out of range
+E156303883 = sequence of operations incorrect
+E156303884 = inconsistent or unsupported flags bit combination
+E156303885 = requested list too large
+E156303886 = index to iterator function is out of range
+E156303887 = bad database block type
+E156303888 = lock is not set
+E156303889 = lock is held by another user
+E156303890 = attempt to lock a lock already held
+E156303891 = interface incompatible
+E156303892 = Ubik I/O error
+E156303893 = bad database address
+E156303894 = backup database is inconsistent
+E156303895 = internal error encountered in backup database server
+E156303896 = error reading cell database
+E156303897 = cell name not found
+E156303898 = database empty or corrupted
+E156303899 = Ubik ClientInit failed
+E156303900 = couldn't allocate entry
+E156303901 = can't allocate memory
+E156303902 = dump is not an initial dump
+E156303903 = reference to a dump not being used
+#-----------------------------------------------------------
+# Error Codes for cmd_errors
+#-----------------------------------------------------------
+E3359744 = More than the maximum number of parameters defined
+E3359745 = Internal parsing error
+E3359746 = Too many values specified after a CMD_SINGLE switch
+E3359747 = Too many parameters specified
+E3359748 = Impossibly few aguments specified
+E3359749 = unrecognized or ambiguous command name
+E3359750 = unrecognized or ambiguous switch name
+E3359751 = <unused>
+E3359752 = Insufficient required parameters provided
+E3359753 = Token too large
+#-----------------------------------------------------------
+# Error Codes for test1
+#-----------------------------------------------------------
+E11829760 = Can't read ticket file
+E11829761 = Can't find ticket or TGT
+E11829762 = TGT expired
+E11829763 = Can't decode authenticator
+E11829764 = Ticket expired
+E11829765 = Repeated request
+E11829766 = The ticket isn't for us
+E11829767 = Request is inconsistent
+E11829768 = Delta-T too big
+E11829769 = Incorrect net address
+E11829770 = Protocol version mismatch
+E11829771 = Invalid message type
+E11829772 = Message stream modified
+E11829773 = Message out of order
+E11829774 = Unauthorized request
+E11829775 = Current password is null
+E11829776 = Incorrect current password
+E11829777 = Protocol error
+E11829778 = Error returned by KDC
+E11829779 = Null ticket returned by KDC
+E11829780 = Retry count exceeded
+E11829781 = Can't send request
+#-----------------------------------------------------------
+# Error Codes for test2
+#-----------------------------------------------------------
+E1163220992 = foo
+E1163220993 = bar
+E1163220994 = meow
+#-----------------------------------------------------------
+# Error Codes for kaerrors
+#-----------------------------------------------------------
+E180480 = AuthServer database is inconsistent
+E180481 = user already exists
+E180482 = Ubik I/O error
+E180483 = couldn't allocate entry
+E180484 = user doesn't exist
+E180485 = database empty or corrupted
+E180486 = name or instance is too long or contains illegal characters
+E180487 = bad index used internally
+E180488 = caller not authorized
+E180489 = answer packet too short for result
+E180490 = password is incorrect
+E180491 = interface incompatible
+E180492 = argument out of range
+E180493 = administrative command called incorrectly
+E180494 = can't create session key
+E180495 = can't read password from terminal
+E180496 = illegal key: bad parity or weak
+E180497 = Ubik ClientInit failed
+E180498 = Ubik Call failed
+E180499 = AuthServer returned incorrect response
+E180500 = error reading cell database
+E180501 = cell name not found
+E180502 = too many Ubik security objects outstanding
+E180503 = too many keys were passed to the server's security object
+E180504 = authentication server was passed a bad ticket
+E180505 = unknown key version number
+E180506 = key cache invalidated by some key change
+E180507 = may not issue ticket for server
+E180508 = may not authenticate as this user
+E180509 = may not change your key
+E180510 = not allowed to create associate
+E180511 = can't find suitable ticket
+E180512 = operation not allowed for associate user
+E180513 = not a special AuthServer principal
+E180514 = server and client clocks are badly skewed
+E180515 = not allowed to recursively call set_password from get_time
+E180516 = Rx failed for some reason
+E180517 = zero length password is illegal
+E180518 = internal error encountered in kaserver
+E180519 = password has expired (KAPWEXPIRED)
+E180520 = it seems like a reused password (KAREUSED)
+E180521 = you changed it too recently; see your systems administrator (KATOOSOON)
+E180522 = ID is locked - see your system admin (KALOCKED)
+#-----------------------------------------------------------
+# Error Codes for afs_AdminBosErrors
+#-----------------------------------------------------------
+E16896 = the bos server name cannot be NULL
+E16897 = the bos server handle cannot be NULL
+E16898 = the bos server handle cannot be NULL
+E16899 = the bos server handle failed to pass the magic number test. Most likely the server handle is invalid, or has been overwritten by mistake.
+E16900 = the bos server handle is invalid
+E16901 = the bos server handle does not reference a valid server
+E16902 = unable to establish a connection with the specified bos server machine
+E16903 = the process name cannot be NULL
+E16904 = the process cannot be NULL
+E16905 = the cron time cannot be NULL when creating a process of type cron
+E16906 = the cron time must be NULL when creating a process of type fs or simple
+E16907 = the process status cannot be NULL
+E16908 = the process type cannot be NULL
+E16909 = the process information cannot be NULL
+E16910 = the parameter cannot be NULL
+E16911 = the notifier cannot be NULL
+E16912 = the administrator name cannot be NULL
+E16913 = the key cannot be NULL
+E16914 = the key cannot be NULL
+E16915 = the host name cannot be NULL
+E16916 = the source file cannot be NULL
+E16917 = the destination file cannot be NULL
+E16918 = the new time cannot be NULL
+E16919 = the old time cannot be NULL
+E16920 = the backup time cannot be NULL
+E16921 = the restart time cannot be NULL
+E16922 = the log name cannot be NULL
+E16923 = the log buffer size cannot be NULL
+E16924 = the log data buffer cannot be NULL
+E16925 = the command cannot be NULL
+E16926 = the auxiliary process status cannot be NULL
+E16927 = the process status is invalid. You can only set a process state to BOS_PROCESS_STOPPED or BOS_PROCESS_RUNNING
+E16928 = the process type retrieved from the bos server was invalid.
+E16929 = the executable source file could not be opened for reading.
+E16930 = unable to determine the size of the executable source file
+E16931 = the executable source file could not be read.
+E16932 = an error occurred transmitting the contents of the executable source file to the bos server.
+E16933 = the executable source file cannot be NULL.
+E16934 = the hour member of the time parameter must be between 0 and 23.
+E16935 = the minute member of the time parameter must be between 0 and 60.
+E16936 = the second member of the time parameter must be between 0 and 60.
+E16937 = the day member of the time parameter must be between 0 and 6.
+E16938 = unable to successfully read log file.
+E16939 = the cell handle does not contain a valid token.
+E16940 = the cell handle is not valid for vos requests.
+E16941 = a parition must be specified when salvaging a volume .
+E16942 = the log file could not be opened for writing.
+E16943 = the resulting salvage command is too long to pass to the bos server.
+E16944 = bos_ProcessCreate can't create fs processes, use bos_FSProcessCreate instead.
+E16945 = the file server executable path cannot be NULL.
+E16946 = the volume server executable path cannot be NULL.
+E16947 = the salvager executable path cannot be NULL.
+#-----------------------------------------------------------
+# Error Codes for afs_AdminCfgErrors
+#-----------------------------------------------------------
+E17920 = the specified configuration option is not yet supported
+E17921 = the host name parameter cannot be NULL
+E17922 = the host name parameter exceeds the maximum allowed length
+E17923 = the host handle reference parameter cannot be NULL
+E17924 = the host handle parameter cannot be NULL
+E17925 = the host handle parameter failed the magic number test; the handle is invalid or corrupted
+E17926 = the host handle parameter is marked as invalid
+E17927 = the host handle parameter contains a NULL host name reference
+E17928 = the host handle parameter contains a NULL cell handle
+E17929 = the host handle parameter contains a NULL cell name reference
+E17930 = the administrator principal parameter cannot be NULL
+E17931 = the administrator principal parameter exceeds the maximum allowed length
+E17932 = the password parameter cannot be an empty string
+E17933 = the configuration status reference parameter cannot be NULL
+E17934 = the cell name reference parameter cannot be NULL
+E17935 = the minimally required server configuration information is missing, unreadable, or invalid
+E17936 = the server is not configured in any cell
+E17937 = the server does not have any keys
+E17938 = the server's cell is not listed in the server's cell database
+E17939 = the server's cell database contains no database server entries for the server's cell
+E17940 = the cell name parameter cannot be NULL
+E17941 = the cell name parameter exceeds the maximum allowed length
+E17942 = the cell name parameter conflicts with the cell name contained in the host handle parameter
+E17943 = the database hosts parameter cannot be NULL
+E17944 = the database hosts parameter contains too many host names
+E17945 = unable to set the server cell information; most likely cause is an unknown database host name
+E17946 = the bosserver process is currently running on the server host
+E17947 = the vice partition table reference parameter cannot be NULL
+E17948 = the vice partition table entry count reference parameter cannot be NULL
+E17949 = unable to read the vice partition table
+E17950 = the partition name parameter cannot be NULL
+E17951 = the partition name parameter syntax is invalid
+E17952 = the device name parameter cannot be NULL
+E17953 = the device name parameter syntax is invalid
+E17954 = the vice partition table entry is invalid
+E17955 = unable to write to the vice partition table
+E17956 = the valid flag reference parameter cannot be NULL
+E17957 = the installed flag reference parameter cannot be NULL
+E17958 = the version number reference parameter cannot be NULL
+E17959 = the started flag reference parameter cannot be NULL
+E17960 = the minimally required client configuration information is missing, unreadable, or invalid
+E17961 = the client is not configured in any cell
+E17962 = the client's cell is not listed in the client's cell database
+E17963 = the client's cell database contains no database server entries for the client's cell
+E17964 = unable to determine which version of the AFS client is installed
+E17965 = unable to read the client's cell database
+E17966 = unable to update the client's cell database
+E17967 = the client's cell database contains the maximum number of entries for the specified cell; a new database host can not be added
+E17968 = failed to edit client's cell database
+E17969 = unable to set the client's current cell
+E17970 = the AFS bosserver control service is not configured or is improperly configured
+E17971 = the AFS bosserver control service is not prepared to accept a control request or is not responding
+E17972 = timed out waiting for the AFS bosserver control service to start or stop
+E17973 = cannot determine the status of the AFS bosserver control service
+E17974 = failed to set or clear the AFS server authentication flag
+E17975 = the bosserver-processes flag reference parameter cannot be NULL
+E17976 = the database-servers-configured flag reference parameter cannot be NULL
+E17977 = the fileserver-configured flag reference parameter cannot be NULL
+E17978 = the upserver-configured flag reference parameter cannot be NULL
+E17979 = the update client instance suffix cannot be NULL
+E17980 = the update client instance suffix exceeds the maximum allowed length
+E17981 = the update client's target server name cannot be NULL
+E17982 = the update client's import directory list cannot be NULL
+E17983 = the upclient-configured flag reference parameter cannot be NULL
+E17984 = unable to establish a connection with the specified Ubik voting service on the specified host
+E17985 = timed out waiting for one or more database servers to achieve quorum; common causes are time skew between database server machines and network connectivity problems
+E17986 = the server's cell database contains too many database server entries
+E17987 = the callback parameter cannot be NULL
+E17988 = the update count reference parameter cannot be NULL
+E17989 = the AFS server principal (afs) key can not be obtained from pre 3.5 database servers
+E17990 = the specified AFS server principal (afs) password is invalid; the password generates a key that fails a checksum comparison with the current AFS server principal (afs) key
+E17991 = the resolver is unable to retrieve host information from the default host database
+E17992 = the specfied host name resolves to a fully qualified name that exceeds the maximum allowed length
+E17993 = the AFS client service is not configured or is improperly configured
+E17994 = the AFS client service is not prepared to accept a control request or is not responding
+E17995 = timed out waiting for the AFS client service to start or stop
+E17996 = cannot determine the status of the AFS client service
+#-----------------------------------------------------------
+# Error Codes for afs_AdminClientErrors
+#-----------------------------------------------------------
+E19456 = the cell handle parameter cannot be NULL
+E19457 = the cell handle reference parameter cannot be NULL
+E19458 = the server handle parameter failed to pass the magic number test. Most likely the server handle is invalid, or has been overwritten by mistake.
+E19459 = the cell handle is not valid.
+E19460 = the cell handle is not valid for authentication server requests
+E19461 = the cell handle authentication server pointer is NULL
+E19462 = the cell handle is not valid for protection server requests
+E19463 = the cell handle protection server pointer is NULL
+E19464 = the cell handle is not valid for volume server requests
+E19465 = the cell handle volume server pointer is NULL
+E19466 = the cell name parameter cannot be NULL
+E19467 = the token handle parameter cannot be NULL
+E19468 = the token handle is invalid
+E19469 = the token handle parameter failed to pass the magic number test. Most likely the token handle is invalid, or has been overwritten by mistake
+E19470 = failed to create a new client security object for the token handle
+E19471 = unable to locate the location of AFS install
+E19472 = unable to initialize the AFS rpc component
+E19473 = unable to initialize the windows socket component
+E19474 = afsclient_Init must be called before calling any other afsclient function
+E19475 = an error occurred while trying to access the local client configuration information
+E19476 = the token handle was marked as containing valid tokens, but the actual tokens were invalid
+E19477 = the token handle must contain valid afs tokens for the cell
+E19478 = the directory parameter cannot be NULL
+E19479 = the volume name parameter cannot be NULL
+E19480 = unable to determine the parent of the given directory
+E19481 = the directory is not in AFS
+E19482 = the server did not match any known AFS servers
+E19483 = the rpc stat handle cannot be NULL
+E19484 = the cell handle does not contain kas tokens
+E19485 = there is no connection to the server
+E19486 = the client stat handle cannot be NULL
+E19487 = there is no connection to the client
+E19488 = the cell name pointer cannot be NULL
+E19489 = the client configuration pointer cannot be NULL
+E19490 = the rxdebug handle cannot be NULL
+E19491 = the rxdebug request timed out
+E19492 = the rxdebug request is not supported
+#-----------------------------------------------------------
+# Error Codes for afs_AdminCommonErrors
+#-----------------------------------------------------------
+E17152 = couldn't allocate memory necessary to fulfill request
+E17153 = insufficient privilege to complete operation
+E17154 = failed to initialize a mutex
+E17155 = failed to lock a mutex
+E17156 = failed to unlock a mutex
+E17157 = failed to destroy a mutex
+E17158 = failed to initialize a condition variable
+E17159 = failed to wait on a condition variable
+E17160 = failed to destroy a condition variable
+E17161 = failed to signal a condition variable
+E17162 = failed to initialize a thread attribute
+E17163 = failed to set thread detach state
+E17164 = failed to create a thread
+E17165 = failed to join a thread
+E17166 = the iterator has been marked terminated (most likely by calling done). Next cannot be called after calling done.
+E17167 = the iterator has been marked completed.
+E17168 = the iterator parameter cannot be NULL.
+E17169 = the rpc specific data parameter cannot be NULL.
+E17170 = the iterator parameter failed to pass the magic number test. Most likely the iterator is invalid, or has been overwritten by mistake.
+E17171 = the iterator parameter is marked invalid
+E17172 = the iterator parameter cannot be NULL nor can it point to NULL
+E17173 = the server name parameter cannot be NULL
+E17174 = the server address parameter cannot be NULL
+E17175 = the server name parameter cannot translated to an address
+E17176 = unable to determine the name of the local host
+E17177 = more data is available
+E17178 = failed to create a socket
+E17179 = the server type is invalid
+#-----------------------------------------------------------
+# Error Codes for afs_AdminKasErrors
+#-----------------------------------------------------------
+E19200 = the server handle parameter cannot be NULL
+E19201 = the server handle parameter failed to pass the magic number test. Most likely the server handle is invalid, or has been overwritten by mistake.
+E19202 = the server handle parameter is marked invalid
+E19203 = the server handle parameter contains no servers
+E19204 = the cell handle and the server handle parameter cannot both be NULL
+E19205 = the cell handle and the server handle parameter cannot both be non-NULL
+E19206 = the authentication server handle parameter cannot be NULL
+E19207 = the from parameter cannot be NULL
+E19208 = the to parameter cannot be NULL
+E19209 = the server list parameter cannot be NULL
+E19210 = the server list parameter contains too many servers
+E19211 = the server handle parameter cannot be NULL nor can it point to NULL
+E19212 = the who parameter cannot be NULL
+E19213 = the password parameter cannot be NULL
+E19214 = the authentication server parameter cannot be NULL
+E19215 = the locked until parameter cannot be NULL
+E19216 = the principal parameter cannot be NULL
+E19217 = the key parameter cannot be NULL
+E19218 = the lock end time parameter cannot be NULL
+E19219 = the password expires parameter cannot be greater than 255
+E19220 = the failed password attempts parameter cannot be greater than 255
+E19221 = the failed password lock time parameter cannot be greater than 129600
+E19222 = the stats parameter cannot be NULL
+E19223 = the debug parameter cannot be NULL
+E19224 = the server list parameter didn't contain any servers
+E19225 = at least one principal field to set must be specified
+#-----------------------------------------------------------
+# Error Codes for afs_AdminMiscErrors
+#-----------------------------------------------------------
+E19712 = the directory parameter cannot be NULL.
+E19713 = the user parameter cannot be NULL.
+E19714 = the acl parameter cannot be NULL.
+E19715 = this interface does not support changing DFS acls.
+#-----------------------------------------------------------
+# Error Codes for afs_AdminPtsErrors
+#-----------------------------------------------------------
+E20480 = the protection server parameter cannot be NULL
+E20481 = the user name parameter cannot be NULL
+E20482 = the user name parameter is too long
+E20483 = the group name parameter cannot be NULL
+E20484 = the group name parameter is too long
+E20485 = failed to translate a name to an identifier
+E20486 = the new owner parameter cannot be NULL
+E20487 = the new owner parameter is too long
+E20488 = the new group parameter cannot be NULL
+E20489 = the new group id parameter cannot be positive
+E20490 = the target group parameter cannot be NULL
+E20491 = the target group parameter is too long
+E20492 = the group parameter cannot be NULL
+E20493 = the group membership list is longer than the maximum retrievable
+E20494 = the member name parameter cannot be NULL
+E20495 = the old name parameter cannot be NULL
+E20496 = the old name is too long
+E20497 = the new name parameter cannot be NULL
+E20498 = the new name is too long
+E20499 = PTS_GROUP_ANYUSER_ACCESS is an invalid value for the list delete parameter
+E20500 = PTS_GROUP_OWNER_ACCESS is an invalid value for the list groups owned parameter
+E20501 = PTS_USER_ANYUSER_ACCESS is an invalid value for the list groups owned parameter
+E20502 = the new entry parameter cannot be NULL
+E20503 = the user parameter cannot be NULL
+E20504 = the new group id parameter cannot be NULL
+E20505 = the maximum group id parameter cannot be NULL
+E20506 = the new user id parameter cannot be NULL
+E20507 = the maximum user id parameter cannot be NULL
+#-----------------------------------------------------------
+# Error Codes for afs_AdminUtilErrors
+#-----------------------------------------------------------
+E21760 = the server entry parameter cannot be NULL
+E21761 = the server name parameter cannot be NULL
+E21762 = the server address parameter cannot be NULL
+E21763 = the server address parameter cannot be NULL
+E21764 = the server name parameter cannot translated to an address
+E21765 = failed to open the client CellServDB file
+E21766 = the error text parameter cannot be NULL
+E21767 = the cell name parameter cannot be NULL
+E21768 = the rx connection parameter cannot be NULL
+E21769 = the rpc function parameter cannot be NULL
+E21770 = the rpc stats parameter cannot be NULL
+E21771 = the state parameter cannot be NULL
+E21772 = the rpc version parameter cannot be NULL
+E21773 = the rxdebug handle parameter cannot be null
+E21774 = the rxdebug version parameter cannot be null
+E21775 = the rxdebug stats parameter cannot be null
+#-----------------------------------------------------------
+# Error Codes for afs_AdminVosErrors
+#-----------------------------------------------------------
+E22016 = the volume server parameter cannot be NULL
+E22017 = the cell handle parameter cannot be NULL
+E22018 = the cell handle parameter failed to pass the magic number test. Most likely the cell handle is invalid, or has been overwritten by mistake.
+E22019 = the cell handle parameter is marked as invalid.
+E22020 = the cell handle parameter is marked as invalid for volume server requests.
+E22021 = the cell handle does not contain valid AFS tokens.
+E22022 = the volume identifier parameter must be a read write volume in order to make a backup volume.
+E22023 = a backup volume already exists for volume identifier, but it exists on a server different from the one that holds volumeidentifier.
+E22024 = the server handle parameter cannot be NULL
+E22025 = the server handle parameter is marked as invalid
+E22026 = the server handle parameter failed the magic number test. Most likely the server handle is invalid, or has been overwritten by mistake.
+E22027 = a connection with the server could not be established.
+E22028 = the partition parameter cannot be NULL
+E22029 = the partition parameter is too large
+E22030 = the volume name parameter is too long
+E22031 = the volume name parameter cannot be NULL
+E22032 = the volume name parameter cannot end with .readonly or .backup
+E22033 = the volume identifier parameter cannot be NULL
+E22034 = the volume identifier parameter cannot exceed VOLMAXPARTS
+E22035 = the volume identifier does not exist on the specified server and partition
+E22036 = the volume name is already in use.
+E22037 = the partition name parameter cannot be NULL
+E22038 = the partition name parameter must start with /vicep
+E22039 = the partition name parameter is too long.
+E22040 = the partition name parameter is too short.
+E22041 = the partition name parameter must be all lower case letters.
+E22042 = the partition identifier parameter cannot be NULL
+E22043 = the resulting partition identifier exceeds VOLMAXPARTS
+E22044 = the volume prefix parameter cannot be NULL when the exclude prefix is VOS_EXCLUDE
+E22045 = the server address parameter cannot be NULL
+E22046 = the server entry parameter cannot be NULL
+E22047 = the server transaction status parameter cannot be NULL
+E22048 = the vldb entry parameter cannot be NULL
+E22049 = at least one of the arguments must not be null - server handle, partition, volume identifier.
+E22050 = the new volume name parameter cannot be NULL
+E22051 = both the server handle and the paritiion parameters must be specified.
+E22052 = the dump file parameter cannot be NULL
+E22053 = an error occurred while trying to write more data to the dump file
+E22054 = an error occurred while trying to open dump file
+E22055 = the volume to be restored exists on a server different from the one specified and you specified an incremental restore. If you wish to restore this volume, specify a full restore.
+E22056 = an error occurred while trying open restore file
+E22057 = an error occurred while trying close restore file
+E22058 = an error occurred while trying read the restore file
+E22059 = an error occurred while trying send the contents of the restore file
+E22060 = the volume name is too big
+E22061 = either the volume name or the volume identifier parameter must not be NULL
+E22062 = the volume parameter cannot be NULL
+E22063 = only read write volumes can be moved
+E22064 = only read write volumes can be released
+E22065 = only replicated volumes can be released
+E22066 = unable to create a backup volume because no read write volume exists
+E22067 = unable to create a backup volume because the vldb entry is invalid
+E22068 = unable to get server's address from vldb
+E22069 = skipping volume since read write is in a different location
+E22070 = there were no entries in the vldb retrieved.
+#-----------------------------------------------------------
+# Error Codes for pterror
+#-----------------------------------------------------------
+E267264 = Entry for name already exists
+E267265 = Entry for id already exists
+E267266 = Couldn't allocate an id for this entry
+E267267 = Couldn't read/write the database
+E267268 = User or group doesn't exist
+E267269 = Permission denied
+E267270 = No group specified
+E267271 = No user specified
+E267272 = Badly formed name (group prefix doesn't match owner?)
+E267273 = argument illegal or out of range
+E267274 = may not create more groups
+E267275 = database needs rebuilding
+E267276 = can't make owner an empty group
+E267277 = database is inconsistent
+E267278 = bad database address
+E267279 = too many elements in group
+E267280 = malloc failed to alloc enough memory
+#-----------------------------------------------------------
+# Error Codes for stress_errs
+#-----------------------------------------------------------
+E19059456 = process created, not yet started
+E19059457 = process running, no error
+E19059458 = arguments illegal or inconsistent
+E19059459 = incorrect input checksum
+E19059460 = incorrect output checksum
+E19059461 = unexpected number of bytes returned by rx_Read
+E19059462 = unexpected number of bytes sent by rx_Write
+E19059463 = connection unauthenticated
+E19059464 = unknown key version number
+E19059465 = incorrect client name/instance/cell
+E19059466 = increment operation produced wrong value
+E19059467 = clock on client and server too far apart
+E19059468 = couldn't make a new connection
+E19059469 = connection has unexpected call numbers
+E19059470 = failed to detect duplicate call
+E19059471 = failed to detect bad cksum
+E19059472 = whole connection is not in error
+E19059473 = idle connection is acting as a challenge oracle
+#-----------------------------------------------------------
+# Error Codes for rxkad_errs
+#-----------------------------------------------------------
+E19270400 = Security module structure inconsistent
+E19270401 = Packet too short for security challenge
+E19270402 = Security level negotiation failed
+E19270403 = Ticket length too long or too short
+E19270404 = packet had bad sequence number
+E19270405 = caller not authorized
+E19270406 = illegal key: bad parity or weak
+E19270407 = security object was passed a bad ticket
+E19270408 = ticket contained unknown key version number
+E19270409 = authentication expired
+E19270410 = sealed data inconsistent
+E19270411 = user data too long
+E19270412 = caller not authorized to use encrypted connections
+#-----------------------------------------------------------
+# Error Codes for uerrors
+#-----------------------------------------------------------
+E5376 = no quorum elected
+E5377 = not synchronization site (should work on sync site)
+E5378 = too many hosts
+E5379 = I/O error writing dbase or log
+E5380 = mysterious internal error
+E5381 = major synchronization error
+E5382 = file not found when processing dbase
+E5383 = bad lock range size (must be 1)
+E5384 = read error reprocessing log
+E5385 = problems with host name
+E5386 = bad operation for this transaction type
+E5387 = two commits or aborts done to transaction
+E5388 = operation done after abort (or commmit)
+E5389 = no servers appear to be up
+E5390 = premature EOF
+E5391 = error writing log file
+E5392 = unsupported address family -- bogus error
+E5393 = inconsistent cell name -- bogus error
+E5394 = security group bad or missing -- bogus error
+E5395 = server group name bad or missing -- bogus error
+E5396 = server uuid bad or missing -- bogus error
+E5397 = memory allocation failure -- bogus error
+E5398 = host not a member of server group -- bogus error
+E5399 = too many bindings per server -- bogus error
+E5400 = inconsistent principal name from binding -- bogus error
+E5401 = I/O error in ubik pipe -- bogus error
+E5402 = operation aborted to prevent dead lock (two sync sites?)
+E5403 = rpc runtime exception caught -- bogus error
+E5404 = vote thread pool queue operation failed -- bogus error
+E5405 = clock skew among servers too high -- bogus error
+E5406 = repeatedly failed to obtain ubik lock -- bogus error
+E5407 = permission denied for attempted operation -- bogus error
+E5408 = no space left on database device -- bogus error
+E5409 = invalid DB pathname -- bogus error
+E5410 = bad file descriptor -- bogus error
+E5411 = Reinitialize called before initialize
+E5412 = failed to initialize per client mutex
+E5413 = failed to destroy per client mutex
+#-----------------------------------------------------------
+# Error Codes for vl_errors
+#-----------------------------------------------------------
+E363520 = Volume Id entry exists in vl database
+E363521 = I/O related error
+E363522 = Volume name entry exists in vl database
+E363523 = Internal creation failure
+E363524 = No such entry
+E363525 = Vl database is empty
+E363526 = Entry is deleted (soft delete)
+E363527 = Volume name is illegal
+E363528 = Index is out of range
+E363529 = Bad volume type
+E363530 = Illegal server number (out of range)
+E363531 = Bad partition number
+E363532 = Run out of space for Replication sites
+E363533 = No such Replication server site exists
+E363534 = Replication site already exists
+E363535 = Parent R/W entry not found
+E363536 = Illegal Reference Count number
+E363537 = Vl size for attributes exceeded
+E363538 = Bad incoming vl entry
+E363539 = Illegal max volid increment
+E363540 = RO/BACK id already hashed
+E363541 = Vl entry is already locked
+E363542 = Bad volume operation code
+E363543 = Bad release lock type
+E363544 = Status report: last release was aborted
+E363545 = Invalid replication site server flag
+E363546 = No permission access
+E363547 = malloc(realloc) failed to alloc enough memory
+E363548 = Wrong vldb version
+E363549 = Index out of range
+E363550 = Servers have the same ip address
+E363551 = Illegal attribute mask value
+#-----------------------------------------------------------
+# Error Codes for volerr
+#-----------------------------------------------------------
+E1492325120 = internal error releasing transaction
+E1492325121 = unknown internal error
+E1492325122 = badly formatted dump
+E1492325123 = badly formatted dump(2)
+E1492325124 = could not attach volume
+E1492325125 = illegal partition
+E1492325126 = could not detach volume
+E1492325127 = insufficient privilege for volume operation
+E1492325128 = error from volume location database
+E1492325129 = bad volume name
+E1492325130 = volume moved
+E1492325131 = illegal volume operation
+E1492325132 = volume release failed
+E1492325133 = volume still in use by volserver
+E1492325134 = out of virtual memory in volserver
+E1492325135 = no such volume
+E1492325136 = more than one read/write volume
+E1492325137 = failed volume server operation
--- /dev/null
+/*
+ * @(#)ACL.java 2.0 04/18/2001
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+/**
+ * An abstract representation of AFS file and directory pathnames.
+ *
+ * This class is an extension of the standard Java File class with file-based
+ * manipulation methods overridden by integrated AFS native methods.
+ *
+ * @version 2.0, 04/18/2001 - Completely revised class for efficiency.
+ */
+
+public class ACL implements Serializable, Comparable
+{
+ private ACL.Entry[] positiveEntries;
+ private ACL.Entry[] negativeEntries;
+
+ private String path;
+
+ public ACL(String path) throws AFSException
+ {
+ int numberPositiveEntries = 0;
+ int numberNegativeEntries = 0;
+ ACL.Entry aclEntry;
+ String buffer;
+
+ this.path = path;
+
+ StringTokenizer st = new StringTokenizer(getACLString(path), "\n\t");
+
+ buffer = st.nextToken();
+ numberPositiveEntries = new Integer(buffer).intValue();
+ positiveEntries = new ACL.Entry[numberPositiveEntries];
+
+ buffer = st.nextToken();
+ numberNegativeEntries = new Integer(buffer).intValue();
+ negativeEntries = new ACL.Entry[numberNegativeEntries];
+
+ for(int i = 0; i < numberPositiveEntries; i++)
+ {
+ aclEntry = new ACL.Entry();
+ aclEntry.setUser(st.nextToken());
+ aclEntry.setPermissions(new Integer(st.nextToken()).intValue());
+ positiveEntries[i] = aclEntry;
+ }
+
+ for(int i = 0; i < numberNegativeEntries; i++)
+ {
+ aclEntry = new ACL.Entry();
+ aclEntry.setUser(st.nextToken());
+ aclEntry.setPermissions(new Integer(st.nextToken()).intValue());
+ negativeEntries[i] = aclEntry;
+ }
+ }
+ public int getEntryCount()
+ {
+ return positiveEntries.length + positiveEntries.length;
+ }
+ public String getPath()
+ {
+ return path;
+ }
+ public ACL.Entry[] getPositiveEntries()
+ {
+ return positiveEntries;
+ }
+ public void addPositiveEntry(ACL.Entry entry) throws AFSException
+ {
+ int n = positiveEntries.length;
+ ACL.Entry[] e = new ACL.Entry[n + 1];
+ System.arraycopy(positiveEntries, 0, e, 0, n);
+ e[n] = entry;
+ positiveEntries = e;
+ setACLString(path, getFormattedString());
+ }
+ public void setPositiveEntries(ACL.Entry[] entries) throws AFSException
+ {
+ this.positiveEntries = entries;
+ setACLString(path, getFormattedString());
+ }
+ public ACL.Entry[] getNegativeEntries()
+ {
+ return negativeEntries;
+ }
+ public void addNegativeEntry(ACL.Entry entry) throws AFSException
+ {
+ int n = negativeEntries.length;
+ ACL.Entry[] e = new ACL.Entry[n + 1];
+ System.arraycopy(negativeEntries, 0, e, 0, n);
+ e[n] = entry;
+ negativeEntries = e;
+ setACLString(path, getFormattedString());
+ }
+ public void setNegativeEntries(ACL.Entry[] entries) throws AFSException
+ {
+ this.negativeEntries = entries;
+ setACLString(path, getFormattedString());
+ }
+
+ public void flush() throws AFSException
+ {
+ setACLString(path, getFormattedString());
+ }
+
+ private ACL.Entry[] getNonEmptyEntries(ACL.Entry[] entries)
+ {
+ ArrayList response = new ArrayList(entries.length);
+ for (int i = 0; i < entries.length; i++)
+ {
+ boolean isNonEmpty = entries[i].canRead() ||
+ entries[i].canLookup() ||
+ entries[i].canWrite() ||
+ entries[i].canInsert() ||
+ entries[i].canDelete() ||
+ entries[i].canLock() ||
+ entries[i].canAdmin();
+ if (isNonEmpty) response.add(entries[i]);
+ }
+ if (response.size() == entries.length) return entries;
+ return (ACL.Entry[])response.toArray(new ACL.Entry[response.size()]);
+ }
+
+ private void entriesToString(ACL.Entry[] entries, StringBuffer response)
+ {
+ for (int i = 0; i < entries.length; i++)
+ {
+ this.entryToString((ACL.Entry)entries[i], response);
+ }
+ }
+
+ private void entryToString(ACL.Entry entry, StringBuffer response)
+ {
+ response.append(entry.getUser() + '\t' + entry.getPermissionsMask() + '\n');
+ }
+
+ /**
+ * Returns a ViceIoctl formatted String representation of this
+ * <CODE>ACL</CODE>.
+ *
+ * @return a ViceIoctl formatted String representation of this
+ * <CODE>ACL</CODE>.
+ */
+ private String getFormattedString()
+ {
+ StringBuffer out = null;
+ ACL.Entry[] nonEmptyPos = this.getNonEmptyEntries(this.getPositiveEntries());
+ ACL.Entry[] nonEmptyNeg = this.getNonEmptyEntries(this.getNegativeEntries());
+
+ out = new StringBuffer(nonEmptyPos.length + "\n" + nonEmptyNeg.length + "\n");
+ this.entriesToString(nonEmptyPos, out);
+ this.entriesToString(nonEmptyNeg, out);
+
+ return out.toString();
+ }
+
+ /////////////// custom override methods ////////////////////
+
+ /**
+ * Compares two ACL objects respective to their paths and does not
+ * factor any other attribute. Alphabetic case is significant in
+ * comparing names.
+ *
+ * @param acl The ACL object to be compared to this ACL
+ * instance
+ *
+ * @return Zero if the argument is equal to this ACL's path, a
+ * value less than zero if this ACL's path is
+ * lexicographically less than the argument, or a value greater
+ * than zero if this ACL's path is lexicographically
+ * greater than the argument
+ */
+ public int compareTo(ACL acl)
+ {
+ return this.getPath().compareTo(acl.getPath());
+ }
+
+ /**
+ * Comparable interface method.
+ *
+ * @see #compareTo(ACL)
+ */
+ public int compareTo(Object obj)
+ {
+ return compareTo((ACL)obj);
+ }
+
+ /**
+ * Tests whether two <code>ACL</code> objects are equal, based on their
+ * paths and permission bits.
+ *
+ * @param acl the ACL to test
+ * @return whether the specifed ACL is the same as this ACL
+ */
+ public boolean equals( ACL acl )
+ {
+ return ( (this.getPath().equals(acl.getPath())) &&
+ (positiveEntries.equals(acl.getPositiveEntries())) &&
+ (negativeEntries.equals(acl.getNegativeEntries())) );
+ }
+
+ /**
+ * Returns a String representation of this <CODE>ACL</CODE>
+ *
+ * @return a String representation of this <CODE>ACL</CODE>
+ */
+ public String toString()
+ {
+ ACL.Entry[] nonEmptyPos = this.getNonEmptyEntries(this.getPositiveEntries());
+ ACL.Entry[] nonEmptyNeg = this.getNonEmptyEntries(this.getNegativeEntries());
+
+ StringBuffer out = new StringBuffer("ACL for ");
+ out.append(path);
+ out.append("\n");
+ out.append("Positive Entries:\n");
+ for (int i = 0; i < nonEmptyPos.length; i++) {
+ out.append(" ");
+ out.append(nonEmptyPos[i].toString());
+ }
+ if (nonEmptyNeg.length > 0) {
+ out.append("Negative Entries:\n");
+ for (int i = 0; i < nonEmptyNeg.length; i++) {
+ out.append(" ");
+ out.append(nonEmptyNeg[i].toString());
+ }
+ }
+
+ return out.toString();
+ }
+
+ /////////////// native methods ////////////////////
+
+ /**
+ * Returns a formatted String representing the ACL for the specified path.
+ *
+ * The string format is in the form of a ViceIoctl and is as follows:
+ * printf("%d\n%d\n", positiveEntriesCount, negativeEntriesCount);
+ * printf("%s\t%d\n", userOrGroupName, rightsMask);
+ *
+ * @param path the directory path
+ * @returns a formatted String representing the ACL for the specified path.
+ * @throws an AFSException if an AFS or JNI exception is encountered.
+ */
+ private native String getACLString(String path) throws AFSException;
+
+ /**
+ * Sets the ACL in the file system according to this abstract representation.
+ *
+ * @param path the directory path
+ * @param aclString string representation of ACL to be set
+ * @throws an AFSException if an AFS or JNI exception is encountered.
+ */
+ private native void setACLString(String path, String aclString) throws AFSException;
+
+ /*====================================================================*/
+ /* INNER CLASSES */
+ /*====================================================================*/
+
+ /**
+ * AFS ACL Entry Class.
+ *
+ * <p> Documentation reference:
+ * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ772">Managing Access Control Lists</A>
+ *
+ * @version 2.0, 04/18/2001 - Completely revised class for efficiency.
+ * @version 3.0, 05/01/2002 - Converted class to an inner class.
+ */
+ public static final class Entry implements Serializable
+ {
+ /** ACL Mask read constant */
+ public static final int READ = 1;
+ /** ACL Mask write constant */
+ public static final int WRITE = 2;
+ /** ACL Mask insert constant */
+ public static final int INSERT = 4;
+ /** ACL Mask lookup constant */
+ public static final int LOOKUP = 8;
+ /** ACL Mask delete constant */
+ public static final int DELETE = 16;
+ /** ACL Mask lock constant */
+ public static final int LOCK = 32;
+ /** ACL Mask administer constant */
+ public static final int ADMIN = 64;
+
+ private String username;
+
+ private boolean r = false;
+ private boolean l = false;
+ private boolean i = false;
+ private boolean d = false;
+ private boolean w = false;
+ private boolean k = false;
+ private boolean a = false;
+
+ /**
+ * Constructs a new ACL entry with all permission bits set to <code>false</code>.
+ */
+ public Entry()
+ {
+ }
+ /**
+ * Constructs a new ACL entry with all permission bits set to <code>false</code>
+ * and sets the associated user or group name.
+ *
+ * @param user The user or group name associated with this entry
+ */
+ public Entry(String user)
+ {
+ this.setUser(user);
+ }
+ /**
+ * Constructs a new ACL entry setting each permission bit to its appropriate
+ * value according to the <code>permissionsMask</code> specified.
+ *
+ * @see #canRead
+ * @see #canWrite
+ * @see #canInsert
+ * @see #canLookup
+ * @see #canDelete
+ * @see #canLock
+ * @see #canAdmin
+ * @param permissionsMask An integer representation of the permissoin
+ * rights of this entry
+ */
+ public Entry(int permissionsMask)
+ {
+ this.setPermissions(permissionsMask);
+ }
+ /**
+ * Constructs a new ACL entry setting each permission bit to its appropriate
+ * value according to the <code>permissionsMask</code> specified
+ * and sets the associated user or group name.
+ *
+ * @see #canRead
+ * @see #canWrite
+ * @see #canInsert
+ * @see #canLookup
+ * @see #canDelete
+ * @see #canLock
+ * @see #canAdmin
+ * @see #setUser
+ * @param permissionsMask An integer representation of the permissoin
+ * rights of this entry
+ * @param user The username or group associated with this entry
+ */
+ public Entry(String user, int permissionsMask)
+ {
+ this.setUser(user);
+ this.setPermissions(permissionsMask);
+ }
+ /*-------------------------------------------------------------------------*/
+ /**
+ * Set this entry's permission bits according to the value of the
+ * <code>permissionsMask</code> specified.
+ *
+ * @see #getPermissionsMask
+ * @param permissionsMask An integer representation of the permissoin
+ * rights of this entry
+ */
+ public void setPermissions(int permissionsMask)
+ {
+ if ((permissionsMask & READ) != 0) {
+ this.setRead(true);
+ }
+ if ((permissionsMask & LOOKUP) != 0) {
+ this.setLookup(true);
+ }
+ if ((permissionsMask & INSERT) != 0) {
+ this.setInsert(true);
+ }
+ if ((permissionsMask & DELETE) != 0) {
+ this.setDelete(true);
+ }
+ if ((permissionsMask & WRITE) != 0) {
+ this.setWrite(true);
+ }
+ if ((permissionsMask & LOCK) != 0) {
+ this.setLock(true);
+ }
+ if ((permissionsMask & ADMIN) != 0) {
+ this.setAdmin(true);
+ }
+ }
+ /**
+ * Returns this entry's permission mask.
+ *
+ * <p> <B>Permission Mask</B><BR>
+ * 01 - READ <BR>
+ * 02 - WRITE <BR>
+ * 04 - INSERT<BR>
+ * 08 - LOOKUP<BR>
+ * 16 - DELETE<BR>
+ * 32 - LOCK <BR>
+ * 64 - ADMIN <BR>
+ *
+ * <p> Any combination of the above mask values would equate to a valid combination of
+ * permission settings. For example, if the permission mask was <B>11</B>, the ACL permissions
+ * would be as follows: <code>read</code> (1), <code>write</code> (2), and <code>lookup</code> (8).<BR>
+ * [1 + 2 + 8 = 11]
+ *
+ * @return An integer representation (mask) of the permissoin rights of this entry
+ */
+ public int getPermissionsMask()
+ {
+ int permissionsMask = 0;
+ if (canRead()) permissionsMask |= READ;
+ if (canWrite()) permissionsMask |= WRITE;
+ if (canInsert()) permissionsMask |= INSERT;
+ if (canLookup()) permissionsMask |= LOOKUP;
+ if (canDelete()) permissionsMask |= DELETE;
+ if (canLock()) permissionsMask |= LOCK;
+ if (canAdmin()) permissionsMask |= ADMIN;
+ return permissionsMask;
+ }
+ /**
+ * Returns the user <B>or</B> group name associated with this ACL entry.
+ *
+ * @return String representation of the user or group name associated with this entry.
+ */
+ public String getUser()
+ {
+ return username;
+ }
+ /**
+ * Sets the user <B>or</B> group name associated with this ACL entry.
+ *
+ * @param user representation of the user or group name associated with this entry.
+ */
+ public void setUser(String user)
+ {
+ username = user;
+ }
+ /**
+ * <IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits <code>read</code> access.
+ *
+ * <p> This permission enables a user to read the contents of files in the directory
+ * and to obtain complete status information for the files (read/retrieve the file
+ * attributes).
+ *
+ * <p><FONT COLOR="666699"><IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>File Permission</B></U></FONT><BR>
+ * This permission is meaningful with respect to files in
+ * a directory, rather than the directory itself or its subdirectories.
+ *
+ * <p> Documentation reference:
+ * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
+ *
+ * @return <code>true</code> if and only if the ACL permits <code>read</code> access of
+ * files; <code>false</code> otherwise
+ */
+ public boolean canRead()
+ {
+ return r;
+ }
+ /**
+ * Sets the ACL permission to accomodate <code>read</code> access for files.
+ *
+ * @see #canRead
+ * @param flag boolean flag that denotes the permission bit for <code>read</code> access.
+ */
+ public void setRead(boolean flag)
+ {
+ r = flag;
+ }
+ /**
+ * <IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits lookup access.
+ *
+ * <p> This permission functions as something of a gate keeper for access to the directory
+ * and its files, because a user must have it in order to exercise any other permissions.
+ * In particular, a user must have this permission to access anything in the directory's
+ * subdirectories, even if the ACL on a subdirectory grants extensive permissions.
+ *
+ * <p> This permission enables a user to list the names of the files and subdirectories in
+ * the directory (this does not permit read access to its respective entries), obtain
+ * complete status information for the directory element itself, and examine the directory's
+ * ACL.
+ *
+ * <p> This permission does not enable a user to read the contents of a file in the
+ * directory.
+ *
+ * <p> Similarly, this permission does not enable a user to lookup the contents of,
+ * obtain complete status information for, or examine the ACL of the subdirectory of
+ * the directory. Those operations require the <code>lookup</code> permission on the ACL
+ * of the subdirectory itself.
+ *
+ * <p><FONT COLOR="666699"><IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>Directory Permission</B></U></FONT><BR>
+ * This permission is meaningful with respect to the
+ * directory itself. For example, the <code>insert</code> permission (see: {@link #canInsert})
+ * does not control addition of data to a file, but rather creation of a new file or
+ * subdirectory.
+ *
+ * <p> Documentation reference:
+ * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
+ *
+ * @return <code>true</code> if and only if the ACL permits <code>lookup</code> access for
+ * directories; <code>false</code> otherwise
+ */
+ public boolean canLookup()
+ {
+ return l;
+ }
+ /**
+ * Sets the ACL permission to accomodate <code>lookup</code> access for directories.
+ *
+ * @see #canLookup
+ * @param flag boolean flag that denotes the permission bit for <code>lookup</code> access.
+ */
+ public void setLookup(boolean flag)
+ {
+ l = flag;
+ }
+ /**
+ * <IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits <code>insert</code> access.
+ *
+ * <p> This permission enables a user to add new files to the directory, either by creating
+ * or copying, and to create new subdirectories. It does not extend into any subdirectories,
+ * which are protected by their own ACLs.
+ *
+ * <p><FONT COLOR="666699"><IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>Directory Permission</B></U></FONT><BR>
+ * This permission is meaningful with respect to the
+ * directory itself. For example, the <code>insert</code> permission (see: {@link #canInsert})
+ * does not control addition of data to a file, but rather creation of a new file or
+ * subdirectory.
+ *
+ * <p> Documentation reference:
+ * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
+ *
+ * @return <code>true</code> if and only if the ACL permits <code>insert</code> access for
+ * directories; <code>false</code> otherwise
+ */
+ public boolean canInsert()
+ {
+ return i;
+ }
+ /**
+ * Sets the ACL permission to accomodate <code>insert</code> access for directories.
+ *
+ * @see #canInsert
+ * @param flag boolean flag that denotes the permission bit for <code>insert</code> access.
+ */
+ public void setInsert(boolean flag)
+ {
+ i = flag;
+ }
+ /**
+ * <IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits <code>delete</code> access.
+ *
+ * <p> This permission enables a user to remove files and subdirectories from the directory
+ * or move them into other directories (assuming that the user has the <code>insert</code>
+ * (see: {@link #canInsert}) permission on the ACL of the other directories).
+ *
+ * <p><FONT COLOR="666699"><IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>Directory Permission</B></U></FONT><BR>
+ * This permission is meaningful with respect to the
+ * directory itself. For example, the <code>insert</code> permission (see: {@link #canInsert})
+ * does not control addition of data to a file, but rather creation of a new file or
+ * subdirectory.
+ *
+ * <p> Documentation reference:
+ * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
+ *
+ * @return <code>true</code> if and only if the ACL permits <code>delete</code> access for
+ * directories; <code>false</code> otherwise
+ */
+ public boolean canDelete()
+ {
+ return d;
+ }
+ /**
+ * Sets the ACL permission to accomodate <code>delete</code> access for directories.
+ *
+ * @see #canDelete
+ * @param flag boolean flag that denotes the permission bit for <code>delete</code> rights.
+ */
+ public void setDelete(boolean flag)
+ {
+ d = flag;
+ }
+ /**
+ * <IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits <code>write</code> access.
+ *
+ * <p> This permission enables a user to modify the contents of files in the directory
+ * and to change their operating system specific mode bits.
+ *
+ * <p><FONT COLOR="666699"><IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>File Permission</B></U></FONT><BR>
+ * This permission is meaningful with respect to files in
+ * a directory, rather than the directory itself or its subdirectories.
+ *
+ * <p> Documentation reference:
+ * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
+ *
+ * @return <code>true</code> if and only if the ACL permits <code>write</code> access for
+ * files; <code>false</code> otherwise
+ */
+ public boolean canWrite()
+ {
+ return w;
+ }
+ /**
+ * Sets the ACL permission to accomodate <code>write</code> access for files.
+ *
+ * @see #canWrite
+ * @param flag boolean flag that denotes the permission bit for <code>write</code> access.
+ */
+ public void setWrite(boolean flag)
+ {
+ w = flag;
+ }
+ /**
+ * <IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits the <code>lock</code> authority.
+ *
+ * <p> This permission enables the user to run programs that issue system calls to
+ * lock files in the directory.
+ *
+ * <p><FONT COLOR="666699"><IMG SRC="file.gif" ALT="File Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>File Permission</B></U></FONT><BR>
+ * This permission is meaningful with respect to files in
+ * a directory, rather than the directory itself or its subdirectories.
+ *
+ * <p> Documentation reference:
+ * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
+ *
+ * @return <code>true</code> if and only if the ACL permits <code>lock</code> authority for
+ * files; <code>false</code> otherwise
+ */
+ public boolean canLock()
+ {
+ return k;
+ }
+ /**
+ * Sets the ACL permission to accomodate <code>lock</code> access for files.
+ *
+ * @see #canLock
+ * @param flag boolean flag that denotes the permission bit for <code>lock</code> rights.
+ */
+ public void setLock(boolean flag)
+ {
+ k = flag;
+ }
+ /**
+ * <IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> Tests whether the ACL permits <code>administer</code> access.
+ *
+ * <p> This permission enables a user to change the directory's ACL. Members of the
+ * <code>system:administrators</code> group implicitly have this permission on every
+ * directory (that is, even if that group does not appear on the ACL). Similarly, the
+ * owner of a directory implicitly has this permission on its ACL and those of all
+ * directories below it that he or she owns.
+ *
+ * <p><FONT COLOR="666699"><IMG SRC="folder.gif" ALT="Directory Permission" WIDTH="15" HEIGHT="15" BORDER="0"> <U><B>Directory Permission</B></U></FONT><BR>
+ * This permission is meaningful with respect to the
+ * directory itself. For example, the <code>insert</code> permission (see: {@link #canInsert})
+ * does not control addition of data to a file, but rather creation of a new file or
+ * subdirectory.
+ *
+ * <p> Documentation reference:
+ * <A HREF="http://www.transarc.com/Library/documentation/afs/3.6/unix/en_US/HTML/AdminGd/auagd020.htm#HDRWQ782">The AFS ACL Permissions</A>
+ *
+ * @return <code>true</code> if and only if the ACL permits <code>administer</code> access for
+ * directories; <code>false</code> otherwise
+ */
+ public boolean canAdmin()
+ {
+ return a;
+ }
+ /**
+ * Sets the ACL permission to accomodate <code>administer</code> rights for directories.
+ *
+ * @see #canAdmin
+ * @param flag boolean flag that denotes the permission bit for <code>administer</code> rights.
+ */
+ public void setAdmin(boolean flag)
+ {
+ a = flag;
+ }
+
+ /////////////// custom override methods ////////////////////
+
+ /**
+ * Tests whether two <code>ACL.Entry</code> objects are equal, based on associated
+ * username and permission bits.
+ *
+ * @param entry the ACL.Entry to test
+ * @return whether the specifed ACL.Entry is the same as this ACL.Entry
+ */
+ public boolean equals( ACL.Entry entry )
+ {
+ return ( (this.getUser().equals( entry.getUser() )) &&
+ (this.getPermissionsMask() == entry.getPermissionsMask()) );
+ }
+
+ /**
+ * Returns a String representation of this <CODE>ACL.Entry</CODE>
+ *
+ * @return a String representation of this <CODE>ACL.Entry</CODE>
+ */
+ public String toString()
+ {
+ StringBuffer out = new StringBuffer(username);
+ out.append("\t");
+ if (r) out.append("r");
+ if (l) out.append("l");
+ if (i) out.append("i");
+ if (d) out.append("d");
+ if (w) out.append("w");
+ if (k) out.append("k");
+ if (a) out.append("a");
+ out.append("\n");
+ return out.toString();
+ }
+
+ }
+}
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * @(#)AFSException.java 2.0 01/04/16
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.util.Locale;
+
+/**
+ * An exception indicating that an error has occurred in the Java AFS
+ * API, in the Java AFS JNI, or in the AFS file system.
+ *
+ * @version 1.0, 04/16/2001
+ * @see java.lang.Exception
+ */
+public class AFSException extends Exception
+{
+ /**
+ * The AFS specific error number (code).
+ * @see #getErrorCode()
+ */
+ protected int errno;
+
+ /**
+ * Constructs an <code>AFSException</code> with the specified detail
+ * message.
+ *
+ * @param reason the detail message.
+ */
+ public AFSException(String reason)
+ {
+ super(reason);
+ }
+ /**
+ * Constructs an <code>AFSException</code> with the specified error code.
+ * This constructor will also generate the appropriate error message
+ * respective to the specified error code.
+ *
+ * @param errno the AFS error number (error code).
+ */
+ public AFSException(int errno)
+ {
+ super(ErrorTable.getMessage( (errno == 0) ? ErrorTable.UNKNOWN : errno ));
+ this.errno = (errno == 0) ? ErrorTable.UNKNOWN : errno;
+ }
+ /**
+ * Constructs an <code>AFSException</code> with the specified detail message
+ * and specified error code. In this constructor the specified detail message
+ * overrides the default AFS error message defined by the
+ * <code>ErrorTable</code> class. Therefore, to retrieve the AFS specific
+ * error message, you must use the <code>{@link #getAFSMessage}</code> method.
+ * The <code>{@link #getMessage}</code> method will return the message specified
+ * in this constructor.
+ *
+ * @param reason the detail message.
+ * @param errno the AFS error number (error code).
+ */
+ public AFSException(String reason, int errno)
+ {
+ super(reason);
+ this.errno = errno;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the AFS specific error number (code). This code can be interpreted
+ * by use of the <code>{@link ErrorTable}</code> class method
+ * <code>{@link ErrorTable#getMessage(int)}</code>.
+ *
+ * @return the AFS error code of this <code>AFSException</code>
+ * object.
+ * @see ErrorTable#getMessage(int)
+ */
+ public int getErrorCode()
+ {
+ return errno;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the error message string of this exception.
+ *
+ * @return the error message string of this exception object.
+ *
+ * @see #getAFSMessage()
+ */
+ public String getMessage()
+ {
+ String msg = super.getMessage();
+ return (msg == null) ? ErrorTable.getMessage(errno) : msg;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the locale specific error message string of this exception.
+ *
+ * @return the error message string of this exception object.
+ * @param locale the locale for which this message will be displayed
+ *
+ * @see #getAFSMessage()
+ */
+ public String getMessage(Locale locale)
+ {
+ String msg = super.getMessage();
+ return (msg == null) ? ErrorTable.getMessage(errno, locale) : msg;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the AFS error message string defined by the <code>ErrorTable
+ * </code> class. The message will be formatted according to the default
+ * Locale.
+ *
+ * <P> This message is also available from this object's super class
+ * method <code>getMessage</code>. However, this method will always return
+ * the string message associated with the actual AFS error code/number
+ * specified, whereas the {@link #getMessage()} method will return the
+ * string message intended for this Exception object, which may be
+ * an overridden message defined in the constructor of this Exception.
+ *
+ * @return the AFS error message string of this exception object.
+ *
+ * @see #getAFSMessage(Locale)
+ * @see AFSException#AFSException(String, int)
+ * @see ErrorTable#getMessage(int)
+ * @see java.lang.Exception#getMessage()
+ */
+ public String getAFSMessage()
+ {
+ return ErrorTable.getMessage(errno);
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the AFS error message defined by the <code>ErrorTable</code>
+ * class. The message will be formatted according to the specified Locale.
+ *
+ * <P> This message is also available from this object's super class
+ * method <code>getMessage</code>. However, this method will always return
+ * the string message associated with the actual AFS error code/number
+ * specified, whereas the {@link #getMessage()} method will return the
+ * string message intended for this Exception object, which may be
+ * an overridden message defined in the constructor of this Exception.
+ *
+ * @return the AFS error message string of this exception object.
+ * @param locale the locale for which this message will be displayed
+ *
+ * @see #getAFSMessage()
+ * @see AFSException#AFSException(String, int)
+ * @see ErrorTable#getMessage(int, Locale)
+ * @see java.lang.Exception#getMessage()
+ */
+ public String getAFSMessage(Locale locale)
+ {
+ return ErrorTable.getMessage(errno, locale);
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns a string representation of this AFS Exception.
+ *
+ * <P> The message will be formatted according to the specified Locale.
+ *
+ * @return the AFS error message string of this exception object.
+ *
+ * @see #getAFSMessage()
+ * @see ErrorTable#getMessage(int)
+ * @see java.lang.Exception#getMessage()
+ */
+ public String toString()
+ {
+ return "AFSException: Error Code: " + errno + "; Message: " +
+ getMessage();
+ }
+ /*-----------------------------------------------------------------------*/
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * @(#)AFSFileException.java 2.0 01/04/16
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.util.Locale;
+
+/**
+ * An exception indicating that a file related error has occured in the
+ * Java AFS API, in the Java AFS JNI, or in the AFS file system.
+ *
+ * <P> This exception extends Java's <code>java.io.IOException</code>
+ * and is therefore often used as a substitution for
+ * {@link java.io.IOException}.
+ *
+ * @version 2.0, 04/16/2001
+ * @version 1.0, 05/25/2000
+ * @see AFSException
+ * @see java.io.IOException
+ */
+public class AFSFileException extends java.io.IOException
+{
+ /**
+ * The AFS specific error number (code).
+ * @see #getErrorCode()
+ */
+ protected int errno;
+
+ /**
+ * Constructs an <code>AFSFileException</code> with the specified detail
+ * message.
+ *
+ * @param reason the detail message.
+ */
+ public AFSFileException (String reason)
+ {
+ super(reason);
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the AFS specific error number (code). This code can be interpreted
+ * by use of the <code>{@link ErrorTable}</code> class method
+ * <code>{@link ErrorTable#getMessage(int)}</code>.
+ *
+ * @return the AFS error code of this <code>AFSException</code>
+ * object.
+ * @see ErrorTable#getMessage(int)
+ */
+ public int getErrorCode()
+ {
+ return errno;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the error message string of this exception.
+ *
+ * @return the error message string of this exception object.
+ *
+ * @see #getAFSMessage()
+ */
+ public String getMessage()
+ {
+ String msg = super.getMessage();
+ return (msg == null) ? ErrorTable.getMessage(errno) : msg;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the locale specific error message string of this exception.
+ *
+ * @return the error message string of this exception object.
+ * @param locale the locale for which this message will be displayed
+ *
+ * @see #getAFSMessage()
+ */
+ public String getMessage(Locale locale)
+ {
+ String msg = super.getMessage();
+ return (msg == null) ? ErrorTable.getMessage(errno, locale) : msg;
+ }
+ /**
+ * Constructs an <code>AFSFileException</code> with the specified error
+ * code. This constructor will also generate the appropriate error message
+ * respective to the specified error code.
+ *
+ * @param errno the AFS error number (error code).
+ */
+ public AFSFileException (int errno)
+ {
+ super(ErrorTable.getMessage( (errno == 0) ? ErrorTable.UNKNOWN : errno ));
+ this.errno = (errno == 0) ? ErrorTable.UNKNOWN : errno;
+ }
+ /**
+ * Constructs an <code>AFSFileException</code> with the specified detail
+ * message and specified error code. In this constructor the specified
+ * detail message overrides the default AFS error message defined by the
+ * <code>ErrorTable</code> class. Therefore, to retrieve the AFS specific
+ * error message, you must use the <code>{@link #getAFSMessage}
+ * </code> method. The <code>{@link #getMessage}</code> method will return
+ * the message specified in this constructor.
+ *
+ * @param reason the detail message.
+ * @param errno the AFS error number (error code).
+ * @see #getAFSMessage()
+ */
+ public AFSFileException (String reason, int errno)
+ {
+ super( (reason == null) ? ErrorTable.getMessage( errno ) : reason );
+ this.errno = errno;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the AFS error message string defined by the <code>ErrorTable
+ * </code> class. The message will be formatted according to the default
+ * Locale.
+ *
+ * <P> This message is also available from this object's super class
+ * method <code>getMessage</code>. However, this method will always return
+ * the string message associated with the actual AFS error code/number
+ * specified, whereas the {@link #getMessage()} method will return the
+ * string message intended for this Exception object, which may be
+ * an overridden message defined in the constructor of this Exception.
+ *
+ * @return the AFS error message string of this exception object.
+ *
+ * @see #getAFSMessage(Locale)
+ * @see AFSFileException#AFSFileException(String, int)
+ * @see ErrorTable#getMessage(int)
+ * @see java.lang.Exception#getMessage()
+ */
+ public String getAFSMessage()
+ {
+ return ErrorTable.getMessage(errno);
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the AFS error message defined by the <code>ErrorTable</code>
+ * class. The message will be formatted according to the specified Locale.
+ *
+ * <P> This message is also available from this object's super class
+ * method <code>getMessage</code>. However, this method will always return
+ * the string message associated with the actual AFS error code/number
+ * specified, whereas the {@link #getMessage()} method will return the
+ * string message intended for this Exception object, which may be
+ * an overridden message defined in the constructor of this Exception.
+ *
+ * @return the AFS error message string of this exception object.
+ * @param locale the locale for which this message will be displayed
+ *
+ * @see #getAFSMessage()
+ * @see AFSFileException#AFSFileException(String, int)
+ * @see ErrorTable#getMessage(int, Locale)
+ * @see java.lang.Exception#getMessage()
+ */
+ public String getAFSMessage(Locale locale)
+ {
+ return ErrorTable.getMessage(errno, locale);
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns a string representation of this AFS Exception.
+ *
+ * @return the AFS error message string of this
+ * <code>AFSFileException</code> object.
+ *
+ * @see #getMessage()
+ */
+ public String toString()
+ {
+ return "AFSFileException: Error Code: " + errno + "; Message: " +
+ getMessage();
+ }
+ /*-----------------------------------------------------------------------*/
+}
+
+
--- /dev/null
+/*
+ * @(#)AFSSecurityException.java 2.0 01/04/16
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.util.Locale;
+
+/**
+ * An exception indicating that a security related error has occured in the
+ * Java AFS API, in the Java AFS JNI, or in the AFS file system.
+ *
+ * @version 1.0, 04/16/2001
+ * @see AFSException
+ */
+public class AFSSecurityException extends SecurityException
+{
+ /**
+ * The AFS specific error number (code).
+ * @see #getErrorCode()
+ */
+ protected int errno;
+
+ /**
+ * Constructs an <code>AFSSecurityException</code> with the specified detail
+ * message.
+ *
+ * @param reason the detail message.
+ */
+ public AFSSecurityException (String reason)
+ {
+ super(reason);
+ }
+ /**
+ * Constructs an <code>AFSSecurityException</code> with the specified error
+ * code. This constructor will also generate the appropriate error message
+ * respective to the specified error code.
+ *
+ * @param errno the AFS error number (error code).
+ */
+ public AFSSecurityException (int errno)
+ {
+ super(ErrorTable.getMessage( (errno == 0) ? ErrorTable.UNKNOWN : errno ));
+ this.errno = (errno == 0) ? ErrorTable.UNKNOWN : errno;
+ }
+ /**
+ * Constructs an <code>AFSFileException</code> with the specified detail
+ * message and specified error code. In this constructor the specified
+ * detail message overrides the default AFS error message defined by the
+ * <code>ErrorTable</code> class. Therefore, to retrieve the AFS specific
+ * error message, you must use the <code>{@link #getAFSMessage}
+ * </code> method. The <code>{@link #getMessage}</code> method will return
+ * the message specified in this constructor.
+ *
+ * @param reason the detail message.
+ * @param errno the AFS error number (error code).
+ * @see #getAFSMessage()
+ */
+ public AFSSecurityException (String reason, int errno)
+ {
+ super( (reason == null) ? ErrorTable.getMessage( errno ) : reason );
+ this.errno = errno;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the AFS specific error number (code). This code can be interpreted
+ * by use of the <code>{@link ErrorTable}</code> class method
+ * <code>{@link ErrorTable#getMessage(int)}</code>.
+ *
+ * @return the AFS error code of this <code>AFSException</code>
+ * object.
+ * @see ErrorTable#getMessage(int)
+ */
+ public int getErrorCode()
+ {
+ return errno;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the error message string of this exception.
+ *
+ * @return the error message string of this exception object.
+ *
+ * @see #getAFSMessage()
+ */
+ public String getMessage()
+ {
+ String msg = super.getMessage();
+ return (msg == null) ? ErrorTable.getMessage(errno) : msg;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the locale specific error message string of this exception.
+ *
+ * @return the error message string of this exception object.
+ * @param locale the locale for which this message will be displayed
+ *
+ * @see #getAFSMessage()
+ */
+ public String getMessage(Locale locale)
+ {
+ String msg = super.getMessage();
+ return (msg == null) ? ErrorTable.getMessage(errno, locale) : msg;
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the AFS error message string defined by the <code>ErrorTable
+ * </code> class. The message will be formatted according to the default
+ * Locale.
+ *
+ * <P> This message is also available from this object's super class
+ * method <code>getMessage</code>. However, this method will always return
+ * the string message associated with the actual AFS error code/number
+ * specified, whereas the {@link #getMessage()} method will return the
+ * string message intended for this Exception object, which may be
+ * an overridden message defined in the constructor of this Exception.
+ *
+ * @return the AFS error message string of this exception object.
+ *
+ * @see #getAFSMessage(Locale)
+ * @see AFSSecurityException#AFSSecurityException(String, int)
+ * @see ErrorTable#getMessage(int)
+ * @see java.lang.Exception#getMessage()
+ */
+ public String getAFSMessage()
+ {
+ return ErrorTable.getMessage(errno);
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns the AFS error message defined by the <code>ErrorTable</code>
+ * class. The message will be formatted according to the specified Locale.
+ *
+ * <P> This message is also available from this object's super class
+ * method <code>getMessage</code>. However, this method will always return
+ * the string message associated with the actual AFS error code/number
+ * specified, whereas the {@link #getMessage()} method will return the
+ * string message intended for this Exception object, which may be
+ * an overridden message defined in the constructor of this Exception.
+ *
+ * @return the AFS error message string of this exception object.
+ * @param locale the locale for which this message will be displayed
+ *
+ * @see #getAFSMessage()
+ * @see AFSSecurityException#AFSSecurityException(String, int)
+ * @see ErrorTable#getMessage(int, Locale)
+ * @see java.lang.Exception#getMessage()
+ */
+ public String getAFSMessage(Locale locale)
+ {
+ return ErrorTable.getMessage(errno, locale);
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns a string representation of this AFS Exception.
+ *
+ * @return the AFS error message string of this
+ * <code>AFSSecurityException</code> object.
+ *
+ * @see #getMessage()
+ */
+ public String toString()
+ {
+ return "AFSSecurityException: Error Code: " + errno + "; Message: " +
+ getMessage();
+ }
+ /*-----------------------------------------------------------------------*/
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * @(#)Cell.java 1.0 6/29/2001
+ *
+ * Copyright (c) 2001-2002 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.Date;
+
+/**
+ * An abstract representation of an AFS cell. It holds information about
+ * the cell, such as what users, groups, and servers exist in the cell.
+ * <BR><BR>
+ *
+ * Constructing a <code>Cell</code> object does not mean a new cell is
+ * created in the AFS file system -- on the contrary, a <code>Cell</code>
+ * object must be a representation of an already existing AFS cell. There
+ * is no way to create a new AFS cell through this API. See
+ * <a href="http://www.openafs.org">OpenAFS.org</a> for information on how
+ * to create a new cell.<BR><BR>
+ *
+ * The construction of a <code>Cell</code> object acts as an entry point
+ * for authentication into the AFS system. Thus, when you construct a
+ * <code>Cell</code>, you must pass in an authenticated <code>Token</code>
+ * of a user in the AFS cell that the <code>Cell</code> represents. You
+ * will be authenticated as the user represented by <code>token</code> and
+ * you will only be allowed to perform actions that the user is
+ * authorized to perform. You must construct a <code>Cell</code> before
+ * attempting to construct any other object in this package, since the
+ * other objects all require a <code>Cell</code> object on construction,
+ * either directly or indirectly.<BR><BR>
+ *
+ * Note that to successfully construct a <code>Cell</code> object, the
+ * code must be running on a machine with a running AFS client, and the
+ * cell this object is to represent must have an entry in the client's
+ * CellServDB file.<BR><BR>
+ *
+ * Each <code>Cell</code> object has its own individual set of
+ * <code>Server</code>s, <code>User</code>s, and <code>Group</code>s.
+ * This represents the properties and attributes of an actual AFS cell.
+ *
+ * If an error occurs during a method call, an
+ * <code>AFSException</code> will be thrown. This class is the Java
+ * equivalent of errors thrown by AFS; see {@link AFSException}
+ * for a complete description.<BR><BR>
+ *
+ * <!--Example of how to use class-->
+ * The following is a simple example of how to construct and use a
+ * <code>Cell</code> object. It shows how a <code>Cell</code> can be used to
+ * get an abstract representation of an AFS server, and how it can obtain an
+ * array of <code>User</code> objects, each of which is an abstract
+ * representation of an AFS user.<BR><BR>
+ *
+ * <PRE>
+ * import org.openafs.jafs.AFSException;
+ * import org.openafs.jafs.Cell;
+ * import org.openafs.jafs.Partition;
+ * import org.openafs.jafs.Server;
+ * import org.openafs.jafs.Token;
+ * import org.openafs.jafs.User;
+ * ...
+ * public class ...
+ * {
+ * ...
+ * private Cell cell;
+ * private Server server;
+ * private Token token;
+ * ...
+ * public static void main(String[] args) throws Exception
+ * {
+ * String username = arg[0];
+ * String password = arg[1];
+ * String cellName = arg[2];
+ * String serverName = arg[3];
+ *
+ * token = new Token(username, password, cellName);
+ * cell = new Cell(token);
+ * server = cell.getServer(serverName);
+ *
+ * User[] users = cell.getUsers();
+ * ...
+ * }
+ * ...
+ * }
+ * </PRE>
+ *
+ */
+public class Cell implements java.io.Serializable
+{
+ protected ArrayList users;
+ protected ArrayList userNames;
+ protected ArrayList groups;
+ protected ArrayList groupNames;
+ protected ArrayList servers;
+ protected ArrayList serverNames;
+
+ protected String name;
+ protected int cellHandle;
+ protected Token token;
+
+ protected int maxGroupID;
+ protected int maxUserID;
+
+ protected GregorianCalendar tokenExpiration;
+
+ protected boolean cachedInfo;
+
+ /**
+ * Constructs a new <CODE>Cell</CODE> object instance given
+ * the <code>Token</code> that should represents an authenticated user
+ * with administrative access. In order to get full access to the cell,
+ * it is best that the <code>Token</code> provided have administrative
+ * privileges.
+ *
+ * @param token the user's authenticated token
+ * @exception AFSException If an error occurs in the native code
+ */
+ public Cell( Token token )
+ throws AFSException
+ {
+ this.token = token;
+ this.name = token.getCellName();
+
+ cellHandle = getCellHandle( name, token.getHandle() );
+
+ users = null;
+ userNames = null;
+ groups = null;
+ groupNames = null;
+ servers = null;
+ serverNames = null;
+ cachedInfo = false;
+ tokenExpiration = null;
+ }
+
+ /**
+ * Constructs a new <CODE>Cell</CODE> object instance given
+ * the <code>Token</code> that should represents an authenticated user
+ * with administrative access. In order to get full access to the cell,
+ * it is best that the <code>Token</code> provided have administrative
+ * privileges.
+ *
+ * <P> This constructor is ideal for point-in-time representation and
+ * transient applications. It ensures all data member values are set
+ * and available without calling back to the filesystem at the first
+ * request for them. Use the {@link #refresh()} method to address any
+ * coherency concerns.
+ *
+ * @param token the user's authenticated token
+ * @param preloadAllMembers true will ensure all object members are
+ * set upon construction; otherwise members
+ * will be set upon access, which is the default
+ * behavior.
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh
+ */
+ public Cell( Token token, boolean preloadAllMembers )
+ throws AFSException
+ {
+ this(token);
+ if (preloadAllMembers) refresh(true);
+ }
+
+ /**
+ * Refreshes the properties of this Cell object instance with values
+ * from the AFS cell it represents. All properties that have been
+ * initialized and/or accessed will be renewed according to the values
+ * of the AFS cell this Cell object instance represents.
+ *
+ * <P>Since in most environments administrative changes can be administered
+ * from an AFS command-line program or an alternate GUI application, this
+ * method provides a means to refresh the Java object representation and
+ * thereby ascertain any possible modifications that may have been made
+ * from such alternate administrative programs. Using this method before
+ * an associated instance accessor will ensure the highest level of
+ * representative accuracy, accommodating changes made external to the
+ * Java application space. If administrative changes to the underlying AFS
+ * system are only allowed via this API, then the use of this method is
+ * unnecessary.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void refresh() throws AFSException
+ {
+ this.refresh(false);
+ }
+
+ /**
+ * Refreshes the properties of this Cell object instance with values
+ * from the AFS cell it represents. If <CODE>all</CODE> is <CODE>true</CODE>
+ * then <U>all</U> of the properties of this Cell object instance will be
+ * set, or renewed, according to the values of the AFS cell it represents,
+ * disregarding any previously set properties.
+ *
+ * <P> Thus, if <CODE>all</CODE> is <CODE>false</CODE> then properties that
+ * are currently set will be refreshed and properties that are not set will
+ * remain uninitialized. See {@link #refresh()} for more information.
+ *
+ * @param all if true set or renew all object properties; otherwise
+ * renew all set properties
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh()
+ */
+ protected void refresh(boolean all) throws AFSException
+ {
+ if( all || (users != null) ) {
+ refreshUsers();
+ }
+ if( all || (userNames != null) ) {
+ refreshUserNames();
+ }
+ if( all || (groups != null) ) {
+ refreshGroups();
+ }
+ if( all || (groupNames != null) ) {
+ refreshGroupNames();
+ }
+ if( all || (servers != null) ) {
+ refreshServers();
+ }
+ if( all || (serverNames != null) ) {
+ refreshServerNames();
+ }
+ if( all || cachedInfo ) {
+ refreshInfo();
+ }
+ }
+
+ /**
+ * Obtains the expiration time of the token being used by this
+ * <code>Cell</code> object. Does not actually refresh the token; that is,
+ * once a token is obtained, its expiration time will not change. This
+ * method is mostly for consistency with the other methods. It is mainly
+ * used for getting the token information once; after that, it need not
+ * be called again.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ private void refreshTokenExpiration() throws AFSException
+ {
+ long expTime;
+
+ expTime = token.getExpiration();
+
+ tokenExpiration = new GregorianCalendar();
+ long longTime = expTime*1000;
+ Date d = new Date( longTime );
+ tokenExpiration.setTime( d );
+ }
+
+ /**
+ * Sets all the information fields of this <code>Cell</code> object,
+ * such as max group and user ids, to trheir most current values.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshInfo() throws AFSException
+ {
+ maxGroupID = getMaxGroupID( cellHandle );
+ maxUserID = getMaxUserID( cellHandle );
+ cachedInfo = true;
+ }
+
+ /**
+ * Obtains the most current list of <code>User</code> objects of this cell.
+ * Finds all users that currently have a kas and/or pts entry for this cell.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshUsers() throws AFSException
+ {
+ User currUser;
+ users = new ArrayList();
+
+ // get kas entries
+ int iterationId = getKasUsersBegin( cellHandle );
+
+ currUser = new User( this );
+ boolean authorized = false;
+ int r = 1;
+ while( r != 0 ) {
+ try {
+ if (authorized) {
+ users.add( currUser );
+ currUser = new User( this );
+ }
+ r = getKasUsersNext( cellHandle, iterationId, currUser );
+ authorized = true;
+ } catch (AFSException e) {
+ System.err.println("ERROR Cell::refreshUsers():kas (User: "
+ + currUser.getName() + ") -> " + e.getMessage());
+ authorized = false;
+ //if (org.openafs.jafs.ErrorCodes.isPermissionDenied(e.getErrorCode()))
+ //r = 0;
+ }
+ }
+ getKasUsersDone( iterationId );
+
+ //take the union with the pts entries
+ iterationId = getPtsUsersBegin( cellHandle );
+ authorized = false;
+ r = 1;
+ while( r != 0 ) {
+ try {
+ if (authorized) {
+ if( !users.contains( currUser ) ) {
+ users.add( currUser );
+ }
+ currUser = new User( this );
+ }
+ r = getPtsOnlyUsersNext( cellHandle, iterationId, currUser );
+ authorized = true;
+ } catch (AFSException e) {
+ System.err.println("ERROR Cell::refreshUsers():pts (User: "
+ + currUser.getName() + ") -> " + e.getMessage());
+ authorized = false;
+ //if (org.openafs.jafs.ErrorCodes.isPermissionDenied(e.getErrorCode()))
+ // r = 0;
+ }
+ }
+ getPtsUsersDone( iterationId );
+
+ }
+
+ /**
+ * Obtains the most current list of user names of this cell. Finds
+ * all users that currently have a kas and/or pts entry for this cell.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshUserNames() throws AFSException
+ {
+ String currName;
+ userNames = new ArrayList();
+
+ // get kas entries
+ int iterationId = getKasUsersBegin( cellHandle );
+ while( ( currName = getKasUsersNextString( iterationId )) != null ) {
+ userNames.add( currName );
+ }
+ getKasUsersDone( iterationId );
+
+ //take the union with the pts entries
+ iterationId = Cell.getPtsUsersBegin( cellHandle );
+ while( ( currName = getPtsOnlyUsersNextString( iterationId, cellHandle ) )
+ != null ) {
+ if( !userNames.contains( currName ) ) {
+ userNames.add( currName );
+ }
+ }
+ getPtsUsersDone( iterationId );
+ }
+
+
+ /**
+ * Obtains the most current list of <code>Group</code> objects of this cell.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshGroups() throws AFSException
+ {
+ Group currGroup;
+
+ int iterationId = getGroupsBegin( cellHandle );
+
+ groups = new ArrayList();
+
+ currGroup = new Group( this );
+ boolean authorized = false;
+ int r = 1;
+ while( r != 0 ) {
+ try {
+ if (authorized) {
+ groups.add( currGroup );
+ currGroup = new Group( this );
+ }
+ r = getGroupsNext( cellHandle, iterationId, currGroup );
+ authorized = true;
+ } catch (AFSException e) {
+ System.err.println("ERROR Cell::refreshGroups() (Group: "
+ + currGroup.getName() + ") -> " + e.getMessage());
+ authorized = false;
+ //if (org.openafs.jafs.ErrorCodes.isPermissionDenied(e.getErrorCode()))
+ // r = 0;
+ }
+ }
+ Cell.getGroupsDone( iterationId );
+ }
+
+ /**
+ * Obtains the most current list of group names of this cell.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshGroupNames() throws AFSException
+ {
+ String currName;
+
+ int iterationId = getGroupsBegin( cellHandle );
+
+ groupNames = new ArrayList();
+ while( ( currName = getGroupsNextString( iterationId ) ) != null ) {
+ groupNames.add( currName );
+ }
+ getGroupsDone( iterationId );
+ }
+
+ /**
+ * Obtains the most current list of <code>Server</code> objects of this cell.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshServers() throws AFSException
+ {
+ Server currServer;
+
+ int iterationId = getServersBegin( cellHandle );
+
+ servers = new ArrayList();
+
+ currServer = new Server( this );
+ boolean authorized = false;
+ int r = 1;
+ while( r != 0 ) {
+ try {
+ if (authorized) {
+ System.out.println("[Java] Cell::refreshServers() -> adding server: "
+ + currServer.getName());
+ servers.add( currServer );
+ currServer = new Server( this );
+ }
+ r = getServersNext( cellHandle, iterationId, currServer );
+System.out.println("[Java] Cell::refreshServers() -> r: " + r);
+ authorized = true;
+ } catch (AFSException e) {
+ System.err.println("ERROR Cell::refreshServers() (Server: "
+ + currServer.getName() + ") -> " + e.getMessage());
+ authorized = false;
+ //if (e.getErrorCode() == org.openafs.jafs.ErrorCodes.PERMISSION_DENIED)
+ // r = 0;
+ }
+ }
+ getServersDone( iterationId );
+ }
+
+ /**
+ * Obtains the most current list of server names of this cell.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshServerNames()
+ throws AFSException
+ {
+ String currName;
+
+ int iterationId = getServersBegin( cellHandle );
+
+ serverNames = new ArrayList();
+ while( ( currName = getServersNextString( iterationId ) ) != null ) {
+ serverNames.add( currName );
+ }
+ getServersDone( iterationId );
+ }
+
+ /**
+ * Unauthenticates this </code>Token</code> object associated with this
+ * <code>Cell</code> and deletes all of its stored information. This
+ * method should only be called when this <code>Cell</code> or any of the
+ * objects constructed using this <code>Cell</code> will not be used
+ * anymore. Note that this does not delete the actual AFS cell that this
+ * <code>Cell</code> object represents; it merely closes the
+ * representation.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void close() throws AFSException
+ {
+ Cell.closeCell( cellHandle );
+ token.close();
+ users = null;
+ userNames = null;
+ groups = null;
+ groupNames = null;
+ servers = null;
+ serverNames = null;
+ cachedInfo = false;
+ tokenExpiration = null;
+ }
+
+ //////////////// ACCESSORS ////////////////////////
+
+ /**
+ * Retrieves the <CODE>User</CODE> object (which is an abstract
+ * representation of an actual AFS user) designated by <code>name</code>.
+ * If a user by that name does not actually exist in AFS in the cell
+ * represented by this object, an {@link AFSException} will be
+ * thrown.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @exception NullPointerException If <CODE>name</CODE> is
+ * <CODE>null</CODE>.
+ * @param name the name of the user to retrieve
+ * @return <CODE>User</CODE> designated by <code>name</code>.
+ */
+ public User getUser(String name) throws AFSException
+ {
+ if (name == null) throw new NullPointerException();
+ User user = new User(name, this);
+ return user;
+ }
+
+ /**
+ * Returns the total number of users who are registered with KAS and PTS,
+ * without duplicates. If a user has a KAS entry and not a PTS entry,
+ * it will still be counted. Conversely, if a user has a PTS entry and
+ * not KAS, it too will be counted. Effectively it is a non-duplicate
+ * union of KAS and PTS user entries.
+ *
+ * <P>If the total list of users or user names have already been
+ * collected (see {@link #getUsers()}), then the returning value will be
+ * calculated based upon the current list. Otherwise, KAS and PTS will be
+ * explicitly queried for the information.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return a <code>User</code> array of the users of the cell.
+ * @see #getUsers()
+ * @see #getUserNames()
+ */
+ public int getUserCount() throws AFSException
+ {
+ if( users != null ) {
+ return users.size();
+ } else if( userNames != null ) {
+ return userNames.size();
+ } else {
+ int k = getKasUserCount(cellHandle);
+ int p = getPtsOnlyUserCount(cellHandle);
+ return k + p;
+ }
+ }
+
+ /**
+ * Retrieves an array containing all of the <code>User</code> objects
+ * associated with this <code>Cell</code>, each of which are an abstract
+ * representation of an actual user of the AFS cell. After this method
+ * is called once, it saves the array of <code>User</code>s and returns
+ * that saved array on subsequent calls, until the {@link #refresh()} method
+ * is called and a more current list is obtained.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return a <code>User</code> array of the users of the cell.
+ */
+ public User[] getUsers() throws AFSException
+ {
+ if( users == null ) refreshUsers();
+ return (User[]) users.toArray( new User[users.size()] );
+ }
+
+ /**
+ * Returns an array containing a subset of the <code>User</code> objects
+ * associated with this <code>Cell</code>, each of which is an abstract
+ * representation of an actual AFS user of the AFS cell. The subset
+ * is a point-in-time list of users (<code>User</code> objects
+ * representing AFS users) starting at the complete array's index of
+ * <code>startIndex</code> and containing up to <code>length</code>
+ * elements.
+ *
+ * If <code>length</code> is larger than the number of remaining elements,
+ * respective to <code>startIndex</code>, then this method will
+ * ignore the remaining positions requested by <code>length</code> and
+ * return an array that contains the remaining number of elements found in
+ * this cell's complete array of users.
+ *
+ * <P>This method is especially useful when managing iterations of very
+ * large lists. {@link #getUserCount()} can be used to determine if
+ * iteration management is practical.
+ *
+ * <P>This method does not save the resulting data and therefore
+ * queries AFS for each call.
+ *
+ * <P><B>Note:</B> PTS-only users are collected before KAS users
+ * and therefore will always, if PTS-only users exist, be within the
+ * lowest range of this cell's complete list of users. PTS and KAS
+ * users are joined in a non-duplicating union and are consequently
+ * treated as a single list of users, thus <code>startIndex</code>
+ * does not necessarily indicate the first KAS user.
+ *
+ * <P><B>Example:</B> If there are more than 50,000 users within this cell
+ * then only render them in increments of 10,000.
+ * <PRE>
+ * ...
+ * User[] users;
+ * if (cell.getUserCount() > 50000) {
+ * int index = 0;
+ * int length = 10000;
+ * while (index < cell.getUserCount()) {
+ * users = cell.<B>getUsers</B>(index, length);
+ * for (int i = 0; i < users.length; i++) {
+ * ...
+ * }
+ * index += length;
+ * ...
+ * }
+ * } else {
+ * users = cell.getUsers();
+ * for (int i = 0; i < users.length; i++) {
+ * ...
+ * }
+ * }
+ * ...
+ * </PRE>
+ *
+ * @param startIndex the base zero index position at which the subset array
+ * should start from, relative to the complete list of
+ * elements present in AFS.
+ * @param length the number of elements that the subset should contain
+ * @return a subset array of users in this cell
+ * @exception AFSException If an error occurs in the native code
+ * @see #getUserCount()
+ * @see #getUserNames(int, int)
+ * @see #getUsers()
+ */
+ public User[] getUsers(int startIndex, int length) throws AFSException
+ {
+ User[] users = new User[length];
+ User currUser = new User( this );
+ int ptsOnlyCount = getPtsOnlyUserCount(cellHandle);
+ int iterationID = 0;
+ int indexPTS = 0;
+ int indexKAS = 0;
+
+ if (startIndex < ptsOnlyCount) {
+ int i = 0;
+ iterationID = getPtsUsersBegin(cellHandle);
+ while( getPtsOnlyUsersNext( cellHandle, iterationID, currUser ) != 0 &&
+ indexPTS < length )
+ {
+ if (i >= startIndex) {
+ users[indexPTS] = currUser;
+ currUser = new User( this );
+ indexPTS++;
+ }
+ }
+ getPtsUsersDone( iterationID );
+
+ if (indexPTS < length) {
+ startIndex = 0;
+ length -= indexPTS;
+ } else {
+ return users;
+ }
+ } else {
+ startIndex -= (ptsOnlyCount - 1);
+ }
+
+ iterationID = getKasUsersBeginAt( cellHandle, startIndex );
+ while( getKasUsersNext(cellHandle, iterationID, currUser ) != 0 &&
+ indexKAS < length )
+ {
+ users[indexKAS] = currUser;
+ currUser = new User( this );
+ indexKAS++;
+ }
+ getKasUsersDone( iterationID );
+
+ if (indexKAS < length) {
+ User[] u = new User[indexKAS + indexPTS];
+ System.arraycopy(users, 0, u, 0, u.length);
+ return u;
+ } else {
+ return users;
+ }
+ }
+
+ /**
+ * Retrieves an array containing all of the names of users
+ * associated with this <code>Cell</code>. After this method
+ * is called once, it saves the array of <code>String</code>s and returns
+ * that saved array on subsequent calls, until the {@link #refresh()} method
+ * is called and a more current list is obtained.
+ *
+ * <P>This method is especially useful when managing iterations of
+ * large lists. {@link #getUserCount()} can be used to determine if
+ * iteration management is practical. In comparison to {@link #getUsers()},
+ * this method has yielded an average performance advantage of approximately
+ * 82% at 10K users; this statistic, however, strictly compares the response
+ * time of each method and understands that the {@link #getUsers()} method
+ * will return an array of populated <code>User</code> objects, whereas this
+ * method will return an array of <code>String</code> names.
+ * <BR><BR>
+ *
+ * @return an <code>String</code> array of the user names of the cell.
+ * @exception AFSException If an error occurs in the native code
+ */
+ public String[] getUserNames() throws AFSException
+ {
+ if( userNames == null ) refreshUserNames();
+ return (String[]) userNames.toArray( new String[userNames.size()] );
+ }
+
+ /**
+ * Returns an array containing a subset of the names of users
+ * associated with this <code>Cell</code>. The subset
+ * is a point-in-time list of users (<code>String</code> names
+ * of AFS users) starting at the complete array's index of
+ * <code>startIndex</code> and containing up to <code>length</code>
+ * elements.
+ *
+ * If <code>length</code> is larger than the number of remaining elements,
+ * respective to <code>startIndex</code>, then this method will
+ * ignore the remaining positions requested by <code>length</code> and
+ * return an array that contains the remaining number of elements found in
+ * this cell's complete array of users.
+ *
+ * <P>This method is especially useful when managing iterations of very
+ * large lists. {@link #getUserCount()} can be used to determine if
+ * iteration management is practical.
+ *
+ * <P>This method does not save the resulting data and therefore
+ * queries AFS for each call.
+ *
+ * <P><B>Note:</B> PTS-only users are collected before KAS users
+ * and therefore will always, if PTS-only users exist, be within the
+ * lowest range of this cell's complete list of users. PTS and KAS
+ * users are joined in a non-duplicating union and are consequently
+ * treated as a single list of users, thus <code>startIndex</code>
+ * does not necessarily indicate the first KAS user.
+ *
+ * <P><B>Example:</B> If there are more than 50,000 users within this cell
+ * then only render them in increments of 10,000.
+ * <PRE>
+ * ...
+ * String[] users;
+ * if (cell.getUserCount() > 50000) {
+ * int index = 0;
+ * int length = 10000;
+ * while (index < cell.getUserCount()) {
+ * users = cell.<B>getUserNames</B>(index, length);
+ * for (int i = 0; i < users.length; i++) {
+ * ...
+ * }
+ * index += length;
+ * ...
+ * }
+ * } else {
+ * users = cell.getUserNames();
+ * for (int i = 0; i < users.length; i++) {
+ * ...
+ * }
+ * }
+ * ...
+ * </PRE>
+ *
+ * @param startIndex the base zero index position at which the subset array
+ * should start from, relative to the complete list of
+ * elements present in AFS.
+ * @param length the number of elements that the subset should contain
+ * @return a subset array of user names in this cell
+ * @exception AFSException If an error occurs in the native code
+ * @see #getUserCount()
+ * @see #getUserNames()
+ * @see #getUsers(int, int)
+ */
+ public String[] getUserNames(int startIndex, int length)
+ throws AFSException
+ {
+ String[] users = new String[length];
+ String currUser;
+ int ptsOnlyCount = getPtsOnlyUserCount(cellHandle);
+ int iterationID = 0;
+ int indexPTS = 0;
+ int indexKAS = 0;
+
+ if (startIndex < ptsOnlyCount) {
+ int i = 0;
+ iterationID = getPtsUsersBegin(cellHandle);
+ while( (currUser = getPtsOnlyUsersNextString( iterationID, cellHandle ))
+ != null && indexPTS < length ) {
+ if (i >= startIndex) {
+ users[indexPTS] = currUser;
+ indexPTS++;
+ }
+ }
+ getPtsUsersDone( iterationID );
+
+ if (indexPTS < length) {
+ startIndex = 0;
+ length -= indexPTS;
+ } else {
+ return users;
+ }
+ } else {
+ startIndex -= (ptsOnlyCount - 1);
+ }
+
+ iterationID = getKasUsersBeginAt( cellHandle, startIndex );
+ while( (currUser = getKasUsersNextString( iterationID )) != null &&
+ indexKAS < length ) {
+ users[indexKAS] = currUser;
+ indexKAS++;
+ }
+ getKasUsersDone( iterationID );
+
+ if (indexKAS < length) {
+ String[] u = new String[indexKAS + indexPTS];
+ System.arraycopy(users, 0, u, 0, u.length);
+ return u;
+ } else {
+ return users;
+ }
+ }
+
+ /**
+ * Retrieves the <CODE>Group</CODE> object (which is an abstract
+ * representation of an actual AFS group) designated by <code>name</code>.
+ * If a group by that name does not actually exist in AFS in the cell
+ * represented by this object, an {@link AFSException} will be
+ * thrown.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @exception NullPointerException If <CODE>name</CODE> is
+ * <CODE>null</CODE>.
+ * @param name the name of the group to retrieve
+ * @return <CODE>Group</CODE> designated by <code>name</code>.
+ */
+ public Group getGroup(String name) throws AFSException
+ {
+ if (name == null) throw new NullPointerException();
+ Group group = new Group(name, this);
+ group.refresh(true);
+ return group;
+ }
+
+ /**
+ * Returns the total number of groups associated with this Cell.
+ *
+ * <P>If the total list of groups or group names have already been
+ * collected (see {@link #getGroups()}), then the returning value will be
+ * calculated based upon the current list. Otherwise, PTS will be
+ * explicitly queried for the information.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return a <code>User</code> array of the users of the cell.
+ * @see #getGroups()
+ * @see #getGroupNames()
+ */
+ public int getGroupCount() throws AFSException
+ {
+ if( groups != null ) {
+ return groups.size();
+ } else if( groupNames != null ) {
+ return groupNames.size();
+ } else {
+ return getGroupCount(cellHandle);
+ }
+ }
+
+ /**
+ * Retrieves an array containing all of the <code>Group</code> objects
+ * associated with this <code>Cell</code>, each of which are an abstract
+ * representation of an actual group of the AFS cell. After this method
+ * is called once, it saves the array of <code>Group</code>s and returns
+ * that saved array on subsequent calls, until the {@link #refresh()} method
+ * is called and a more current list is obtained.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return a <code>Group</code> array of the groups of the cell.
+ */
+ public Group[] getGroups() throws AFSException
+ {
+ if( groups == null ) refreshGroups();
+ return (Group[]) groups.toArray( new Group[groups.size()] );
+ }
+
+ /**
+ * Returns an array containing a subset of the <code>Group</code> objects
+ * associated with this <code>Cell</code>, each of which is an abstract
+ * representation of an actual AFS group of the AFS cell. The subset
+ * is a point-in-time list of groups (<code>Group</code> objects
+ * representing AFS groups) starting at the complete array's index of
+ * <code>startIndex</code> and containing up to <code>length</code>
+ * elements.
+ *
+ * If <code>length</code> is larger than the number of remaining elements,
+ * respective to <code>startIndex</code>, then this method will
+ * ignore the remaining positions requested by <code>length</code> and
+ * return an array that contains the remaining number of elements found in
+ * this cell's complete array of groups.
+ *
+ * <P>This method is especially useful when managing iterations of very
+ * large lists. {@link #getGroupCount()} can be used to determine if
+ * iteration management is practical.
+ *
+ * <P>This method does not save the resulting data and therefore
+ * queries AFS for each call.
+ *
+ * <P><B>Example:</B> If there are more than 50,000 groups within this cell
+ * then only render them in increments of 10,000.
+ * <PRE>
+ * ...
+ * Group[] groups;
+ * if (cell.getGroupCount() > 50000) {
+ * int index = 0;
+ * int length = 10000;
+ * while (index < cell.getGroupCount()) {
+ * groups = cell.<B>getGroups</B>(index, length);
+ * for (int i = 0; i < groups.length; i++) {
+ * ...
+ * }
+ * index += length;
+ * ...
+ * }
+ * } else {
+ * groups = cell.getGroups();
+ * for (int i = 0; i < groups.length; i++) {
+ * ...
+ * }
+ * }
+ * ...
+ * </PRE>
+ *
+ * @param startIndex the base zero index position at which the subset array
+ * should start from, relative to the complete list of
+ * elements present in AFS.
+ * @param length the number of elements that the subset should contain
+ * @return a subset array of groups in this cell
+ * @exception AFSException If an error occurs in the native code
+ * @see #getGroupCount()
+ * @see #getGroupNames(int, int)
+ * @see #getGroups()
+ */
+ public Group[] getGroups(int startIndex, int length) throws AFSException
+ {
+ Group[] groups = new Group[length];
+ Group currGroup = new Group( this );
+ int i = 0;
+
+ int iterationID = getGroupsBeginAt( cellHandle, startIndex );
+
+ while( getGroupsNext( cellHandle, iterationID, currGroup ) != 0
+ && i < length ) {
+ groups[i] = currGroup;
+ currGroup = new Group( this );
+ i++;
+ }
+ getGroupsDone( iterationID );
+ if (i < length) {
+ Group[] v = new Group[i];
+ System.arraycopy(groups, 0, v, 0, i);
+ return v;
+ } else {
+ return groups;
+ }
+ }
+
+ /**
+ * Retrieves an array containing all of the names of groups
+ * associated with this <code>Cell</code>. After this method
+ * is called once, it saves the array of <code>String</code>s and returns
+ * that saved array on subsequent calls, until the {@link #refresh()} method
+ * is called and a more current list is obtained.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return a <code>String</code> array of the group names of the cell.
+ */
+ public String[] getGroupNames() throws AFSException
+ {
+ if( groupNames == null ) refreshGroupNames();
+ return (String[]) groupNames.toArray( new String[groupNames.size()] );
+ }
+
+ /**
+ * Returns an array containing a subset of the names of groups
+ * associated with this <code>Cell</code>. The subset
+ * is a point-in-time list of groups (<code>String</code> names
+ * of AFS groups) starting at the complete array's index of
+ * <code>startIndex</code> and containing up to <code>length</code>
+ * elements.
+ *
+ * If <code>length</code> is larger than the number of remaining elements,
+ * respective to <code>startIndex</code>, then this method will
+ * ignore the remaining positions requested by <code>length</code> and
+ * return an array that contains the remaining number of elements found in
+ * this cell's complete array of groups.
+ *
+ * <P>This method is especially useful when managing iterations of very
+ * large lists. {@link #getGroupCount()} can be used to determine if
+ * iteration management is practical.
+ *
+ * <P>This method does not save the resulting data and therefore
+ * queries AFS for each call.
+ *
+ * <P><B>Example:</B> If there are more than 50,000 groups within this cell
+ * then only render them in increments of 10,000.
+ * <PRE>
+ * ...
+ * String[] groups;
+ * if (cell.getGroupCount() > 50000) {
+ * int index = 0;
+ * int length = 10000;
+ * while (index < cell.getGroupCount()) {
+ * groups = cell.<B>getGroupNames</B>(index, length);
+ * for (int i = 0; i < groups.length; i++) {
+ * ...
+ * }
+ * index += length;
+ * ...
+ * }
+ * } else {
+ * groups = cell.getGroupNames();
+ * for (int i = 0; i < groups.length; i++) {
+ * ...
+ * }
+ * }
+ * ...
+ * </PRE>
+ *
+ * @param startIndex the base zero index position at which the subset array
+ * should start from, relative to the complete list of
+ * elements present in AFS.
+ * @param length the number of elements that the subset should contain
+ * @return a subset array of group names in this cell
+ * @exception AFSException If an error occurs in the native code
+ * @see #getGroupCount()
+ * @see #getGroups(int, int)
+ * @see #getGroupNames()
+ */
+ public String[] getGroupNames(int startIndex, int length)
+ throws AFSException
+ {
+ String[] groups = new String[length];
+ String currGroup;
+ int i = 0;
+
+ int iterationID = getGroupsBeginAt( cellHandle, startIndex );
+
+ while( (currGroup = getGroupsNextString( iterationID )) != null &&
+ i < length )
+ {
+ groups[i] = currGroup;
+ i++;
+ }
+ getGroupsDone( iterationID );
+ if (i < length) {
+ String[] v = new String[i];
+ System.arraycopy(groups, 0, v, 0, i);
+ return v;
+ } else {
+ return groups;
+ }
+ }
+
+ /**
+ * Retrieves the <CODE>Server</CODE> object (which is an abstract
+ * representation of an actual AFS server) designated by <code>name</code>.
+ * If a group by that name does not actually exist in AFS in the cell
+ * represented by this object, an {@link AFSException} will be
+ * thrown.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @exception NullPointerException If <CODE>name</CODE> is
+ * <CODE>null</CODE>.
+ * @param name the name of the server to retrieve
+ * @return <CODE>Server</CODE> designated by <code>name</code>.
+ */
+ public Server getServer(String name)
+ throws AFSException
+ {
+ if (name == null) throw new NullPointerException();
+ Server server = new Server(name, this);
+ server.refresh(true);
+ return server;
+ }
+
+ /**
+ * Returns the total number of servers associated with this Cell.
+ *
+ * <P>If the total list of servers or server names have already been
+ * collected (see {@link #getServers()}), then the returning value will be
+ * calculated based upon the current list. Otherwise, AFS will be
+ * explicitly queried for the information.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return a <code>User</code> array of the users of the cell.
+ * @see #getServers()
+ * @see #getServerNames()
+ */
+ public int getServerCount() throws AFSException
+ {
+ if( servers != null ) {
+ return servers.size();
+ } else if( serverNames != null ) {
+ return serverNames.size();
+ } else {
+ return getServerCount(cellHandle);
+ }
+ }
+
+ /**
+ * Retrieves an array containing all of the <code>Server</code> objects
+ * associated with this <code>Cell</code>, each of which are an abstract
+ * representation of an actual server of the AFS cell. After this method
+ * is called once, it saves the array of <code>Server</code>s and returns
+ * that saved array on subsequent calls, until the {@link #refresh()} method
+ * is called and a more current list is obtained.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return an <code>Server</code> array of the servers of the cell.
+ */
+ public Server[] getServers() throws AFSException
+ {
+ if ( servers == null ) refreshServers();
+ return (Server[]) servers.toArray( new Server[servers.size()] );
+ }
+
+ /**
+ * Retrieves an array containing all of the names of servers
+ * associated with this <code>Cell</code>. After this method
+ * is called once, it saves the array of <code>String</code>s and returns
+ * that saved array on subsequent calls, until the {@link #refresh()} method
+ * is called and a more current list is obtained.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return a <code>String</code> array of the servers of the cell.
+ */
+ public String[] getServerNames() throws AFSException
+ {
+ if ( serverNames == null ) refreshServerNames();
+ return (String[]) serverNames.toArray( new String[serverNames.size()] );
+ }
+
+ /**
+ * Returns the maximum group ID that's been used within the cell.
+ * The next auto-assigned group ID will be one less (more negative)
+ * than this amount. After this method is called once, it saves the
+ * max group id and returns that id on subsequent calls, until the
+ * {@link #refresh()} method is called and a more current id is obtained.
+ *
+ * @return an integer representing the maximum group ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getMaxGroupID() throws AFSException
+ {
+ if( !cachedInfo ) refreshInfo();
+ return maxGroupID;
+
+ }
+
+ /**
+ * Returns the maximum user ID that's been used within the cell.
+ * The next auto-assigned user ID will be one greater (more positive)
+ * than this amount. After this method is called once, it saves the
+ * max user id and returns that id on subsequent calls, until the
+ * {@link #refresh()} method is called and a more current id is obtained.
+ *
+ * @return an integer representing the maximum user ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getMaxUserID() throws AFSException
+ {
+ if( !cachedInfo ) refreshInfo();
+ return maxUserID;
+ }
+
+ /**
+ * Returns the expiration time of the authentication token being used
+ * by this <code>Cell</code> object. After this time, this
+ * <code>Cell</code> object will no longer be authorized to perform
+ * actions requiring administrative authority.
+ *
+ * @return expiration time of the token
+ * @exception AFSException If an error occurs in the native code
+ */
+ public GregorianCalendar getTokenExpiration() throws AFSException
+ {
+ if( tokenExpiration == null ) refreshTokenExpiration();
+ return tokenExpiration;
+ }
+
+ /**
+ * Returns the cell handle of this cell.
+ *
+ * @return the cell handle
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getCellHandle() throws AFSException
+ {
+ return cellHandle;
+ }
+
+ /**
+ * Returns the name of this cell.
+ *
+ * @return the cell name
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Sets the maximum group ID that's been used within the cell. The next
+ * auto-assigned group ID will be one less (more negative) than this amount.
+ *
+ * @param maxID an integer representing the maximum group ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void setMaxGroupID( int maxID ) throws AFSException
+ {
+ setMaxGroupID( cellHandle, maxID );
+ maxGroupID = maxID;
+ }
+
+ /**
+ * Sets the maximum user ID that's been used within the cell. The next
+ * auto-assigned user ID will be one greater (more positive) than this
+ * amount.
+ *
+ * @param maxID an integer representing the maximum user ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void setMaxUserID( int maxID ) throws AFSException
+ {
+ setMaxUserID( cellHandle, maxID );
+ maxUserID = maxID;
+ }
+
+ /////////////// information methods ////////////////////
+
+ /**
+ * Returns a <code>String</code> representation of this <code>Cell</code>.
+ * Contains the cell name followed by the names of its users and groups.
+ *
+ * @return a <code>String</code> representation of this <code>Cell</code>
+ */
+ protected String getInfo()
+ {
+ String r = "Cell: " + name + "\n\n";
+ try {
+ r += "\tMax group ID: " + getMaxGroupID() + "\n";
+ r += "\tMax user ID: " + getMaxUserID() + "\n";
+ r += "\tToken expiration: " + getTokenExpiration().getTime() + "\n";
+ } catch( AFSException e ) {
+ return e.toString();
+ }
+
+ String[] servs;
+ String[] usrs;
+ String[] grps;
+ try {
+ usrs = getUserNames();
+ grps = getGroupNames();
+ servs = getServerNames();
+
+ } catch( Exception e ) {
+ return e.toString();
+ }
+
+ r += "--Users--\n";
+
+ for( int i = 0; i < usrs.length; i++ ) {
+
+ r += usrs[i] + "\n";
+ }
+
+ r += "\n--Groups--\n";
+
+ for( int i = 0; i < grps.length; i++ ) {
+
+ r += grps[i] + "\n";
+ }
+
+ r += "\n--Servers--\n";
+
+ for( int i = 0; i < servs.length; i++ ) {
+
+ r += servs[i] + "\n";
+ }
+
+ return r;
+ }
+
+ /**
+ * Returns a <code>String</code> containing the <code>String</code>
+ * representations of all the users of this <code>Cell</code>.
+ *
+ * @return a <code>String</code> representation of the users
+ * @see User#getInfo
+ */
+ protected String getInfoUsers() throws AFSException
+ {
+ String r;
+
+ r = "Cell: " + name + "\n\n";
+ r += "--Users--\n";
+
+ User usrs[] = getUsers();
+ for( int i = 0; i < usrs.length; i++ ) {
+ r += usrs[i].getInfo() + "\n";
+ }
+
+ return r;
+ }
+
+ /**
+ * Returns a <code>String</code> containing the <code>String</code>
+ * representations of all the groups of this <code>Cell</code>.
+ *
+ * @return a <code>String</code> representation of the groups
+ * @see Group#getInfo
+ */
+ protected String getInfoGroups() throws AFSException
+ {
+ String r;
+
+ r = "Cell: " + name + "\n\n";
+ r += "--Groups--\n";
+
+ Group grps[] = getGroups();
+ for( int i = 0; i < grps.length; i++ ) {
+ r += grps[i].getInfo() + "\n";
+ }
+ return r;
+ }
+
+ /**
+ * Returns a <code>String</code> containing the <code>String</code>
+ * representations of all the servers of this <code>Cell</code>.
+ *
+ * @return a <code>String</code> representation of the servers
+ * @see Server#getInfo
+ */
+ protected String getInfoServers()
+ throws AFSException
+ {
+ String r;
+ r = "Cell: " + name + "\n\n";
+ r += "--Servers--\n";
+ Server[] servs = getServers();
+ for( int i = 0; i < servs.length; i++ ) {
+ r += servs[i].getInfo() + "\n";
+ }
+ return r;
+ }
+
+ /////////////// override methods ////////////////////
+
+ /**
+ * Tests whether two <code>Cell</code> objects are equal, based on their
+ * names. Does not test whether the objects are actually the same
+ * representational instance of the AFS cell.
+ *
+ * @param otherCell the <code>Cell</code> to test
+ * @return whether the specifed user is the same as this user
+ */
+ public boolean equals( Cell otherCell )
+ {
+ return name.equals( otherCell.getName() );
+ }
+
+ /**
+ * Returns the name of this <CODE>Cell</CODE>
+ *
+ * @return the name of this <CODE>Cell</CODE>
+ */
+ public String toString()
+ {
+ return name;
+ }
+
+ /////////////// native methods Cell ////////////////////
+
+ /**
+ * Returns the total number of KAS users belonging to the cell denoted
+ * by <CODE>cellHandle</CODE>.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @return total count of KAS users
+ * @exception AFSException If an error occurs in the native code
+ * @see Cell#getCellHandle
+ */
+ protected static native int getKasUserCount( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Begin the process of getting the kas users that belong to the cell.
+ * Returns an iteration ID to be used by subsequent calls to
+ * <code>getKasUsersNextString</code> (or <code>getKasUsersNext</code>)
+ * and <code>getKasUsersDone</code>.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @see Cell#getCellHandle
+ * @return an iteration ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getKasUsersBegin( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Begin the process of getting the KAS users, starting at
+ * <code>startIndex</code>, that belong to the cell.
+ * Returns an iteration ID to be used by subsequent calls to
+ * <code>getKasUsersNextString</code> (or <code>getKasUsersNext</code>)
+ * and <code>getKasUsersDone</code>.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @param startIndex the starting base-zero index
+ * @return an iteration ID
+ * @exception AFSException If an error occurs in the native code
+ * @see Cell#getCellHandle
+ */
+ protected static native int getKasUsersBeginAt( int cellHandle,
+ int startIndex )
+ throws AFSException;
+
+ /**
+ * Returns the next kas user of the cell. Returns <code>null</code> if there
+ * are no more users. Appends instance names to principal names as follows:
+ * <i>principal</i>.<i>instance</i>
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getKasUsersBegin
+ * @return the name of the next user of the cell
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native String getKasUsersNextString( int iterationId )
+ throws AFSException;
+
+ /**
+ * Fills the next kas user object of the cell. Returns 0 if there
+ * are no more users, != 0 otherwise.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @see Cell#getCellHandle
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getKasUsersBegin
+ * @param theUser a User object to be populated with the values of
+ * the next kas user
+ * @return 0 if there are no more users, != 0 otherwise
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getKasUsersNext( int cellHandle,
+ int iterationId,
+ User theUser )
+ throws AFSException;
+
+ /**
+ * Signals that the iteration is complete and will not be accessed anymore.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getKasUsersBegin
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void getKasUsersDone( int iterationId )
+ throws AFSException;
+
+ /**
+ * Returns the total number of PTS users belonging to the cell denoted
+ * by <CODE>cellHandle</CODE>.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @return total number of PTS users
+ * @exception AFSException If an error occurs in the native code
+ * @see Cell#getCellHandle
+ */
+ protected static native int getPtsUserCount( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Returns the total number of PTS users, belonging to the cell denoted
+ * by <CODE>cellHandle</CODE>, that are not in KAS.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @return total number of users that are in PTS and not KAS
+ * @exception AFSException If an error occurs in the native code
+ * @see Cell#getCellHandle
+ */
+ protected static native int getPtsOnlyUserCount( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Begin the process of getting the pts users that belong to the cell.
+ * Returns an iteration ID to be used by subsequent calls to
+ * <code>getPtsUsersNextString</code> (or <code>getPtsUsersNext</code>)
+ * and <code>getPtsUsersDone</code>.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @see Cell#getCellHandle
+ * @return an iteration ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getPtsUsersBegin( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Returns the next pts user of the cell. Returns <code>null</code> if
+ * there are no more users.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getPtsUsersBegin
+ * @return the name of the next user of the cell
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native String getPtsUsersNextString( int iterationId )
+ throws AFSException;
+
+ /**
+ * Returns the next pts user (who is not a kas user) of the cell.
+ * Returns <code>null</code> if there are no more users.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @param cellHandle the cell handle to which these users will belong
+ * @see Cell#getPtsUsersBegin
+ * @return the name of the next pts user (not kas user) of the cell
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native String getPtsOnlyUsersNextString( int iterationId,
+ int cellHandle )
+ throws AFSException;
+
+ /**
+ * Fills the next pts user object of the cell. Returns 0 if there
+ * are no more users, != 0 otherwise.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @see Cell#getCellHandle
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getPtsUsersBegin
+ * @param theUser a User object to be populated with the values of
+ * the next pts user
+ * @return 0 if there are no more users, != 0 otherwise
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getPtsUsersNext( int cellHandle, int iterationId,
+ User theUser )
+ throws AFSException;
+
+ /**
+ * Fills the next pts user (who does not have a kas entry) object of
+ * the cell. Returns 0 if there are no more users, != 0 otherwise.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @see Cell#getCellHandle
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getPtsUsersBegin
+ * @param theUser a User object to be populated with the values of
+ * the next pts (with no kas) user
+ * @return 0 if there are no more users, != 0 otherwise
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getPtsOnlyUsersNext( int cellHandle,
+ int iterationId,
+ User theUser )
+ throws AFSException;
+
+ /**
+ * Signals that the iteration is complete and will not be accessed anymore.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getPtsUsersBegin
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void getPtsUsersDone( int iterationId )
+ throws AFSException;
+
+ /**
+ * Returns the total number of groups belonging to the cell denoted
+ * by <CODE>cellHandle</CODE>.
+ *
+ * @param cellHandle the handle of the cell to which the groups belong
+ * @return total number of groups
+ * @exception AFSException If an error occurs in the native code
+ * @see Cell#getCellHandle
+ */
+ protected static native int getGroupCount( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Begin the process of getting the groups that belong to the cell. Returns
+ * an iteration ID to be used by subsequent calls to
+ * <code>getGroupsNextString</code> (or <code>getGroupsNext</code>) and
+ * <code>getGroupsDone</code>.
+ *
+ * @param cellHandle the handle of the cell to which the groups belong
+ * @see Cell#getCellHandle
+ * @return an iteration ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getGroupsBegin( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Begin the process of getting the groups that belong to the cell, starting
+ * with element index <code>startIndex</code>. Returns an iteration ID to
+ * be used by subsequent calls to <code>getGroupsNextString</code>
+ * (or <code>getGroupsNext</code>) and <code>getGroupsDone</code>.
+ *
+ * @param cellHandle the handle of the cell to which the groups belong
+ * @param startIndex the starting base-zero index
+ * @return an iteration ID
+ * @exception AFSException If an error occurs in the native code
+ * @see Cell#getCellHandle
+ */
+ protected static native int getGroupsBeginAt( int cellHandle,
+ int startIndex )
+ throws AFSException;
+
+ /**
+ * Returns the next group of the cell. Returns <code>null</code> if there
+ * are no more groups.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getGroupsBegin
+ * @return the name of the next user of the cell
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native String getGroupsNextString( int iterationId )
+ throws AFSException;
+
+ /**
+ * Fills the next group object of the cell. Returns 0 if there
+ * are no more groups, != 0 otherwise.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @see Cell#getCellHandle
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getGroupsBegin
+ * @param theGroup a Group object to be populated with the values of
+ * the next group
+ * @return 0 if there are no more users, != 0 otherwise
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getGroupsNext( int cellHandle, int iterationId,
+ Group theGroup )
+ throws AFSException;
+
+ /**
+ * Signals that the iteration is complete and will not be accessed anymore.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getGroupsBegin
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void getGroupsDone( int iterationId )
+ throws AFSException;
+
+ /**
+ * Returns the total number of servers belonging to the cell denoted
+ * by <CODE>cellHandle</CODE>.
+ *
+ * @param cellHandle the handle of the cell to which the servers belong
+ * @return total number of servers
+ * @exception AFSException If an error occurs in the native code
+ * @see Cell#getCellHandle
+ */
+ protected static native int getServerCount( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Begin the process of getting the servers in the cell. Returns
+ * an iteration ID to be used by subsequent calls to
+ * <code>getServersNextString</code> and <code>getServersDone</code>.
+ *
+ * @param cellHandle the handle of the cell to which the servers belong
+ * @see Cell#getCellHandle
+ * @return an iteration ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getServersBegin( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Returns the next server of the cell. Returns <code>null</code> if there
+ * are no more servers.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getServersBegin
+ * @return the name of the next server of the cell
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native String getServersNextString( int iterationId )
+ throws AFSException;
+
+ /**
+ * Fills the next server object of the cell. Returns 0 if there are no
+ * more servers, != 0 otherwise.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @see Cell#getCellHandle
+ * @param iterationId the iteration ID of this iteration
+ * @param theServer a Server object to be populated with the values
+ * of the next server
+ * @see Cell#getServersBegin
+ * @return 0 if there are no more servers, != 0 otherwise
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getServersNext( int cellHandle, int iterationId,
+ Server theServer )
+ throws AFSException;
+
+ /**
+ * Signals that the iteration is complete and will not be accessed anymore.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see Cell#getServersBegin
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void getServersDone( int iterationId )
+ throws AFSException;
+
+ /**
+ * Returns the name of the cell.
+ *
+ * @param cellHandle the handle of the cell to which the user belongs
+ * @see Cell#getCellHandle
+ * @return the name of the cell
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native String getCellName( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Creates a mount point for a volume within the file system.
+ *
+ * @param cellHandle the handle of the cell to which the user belongs
+ * @see Cell#getCellHandle
+ * @param directory the full path of the place in the AFS file system
+ * at which to mount the volume
+ * @param volumeName the name of the volume to mount
+ * @param readWrite whether or not this is to be a readwrite mount point
+ * @param forceCheck whether or not to check if this volume name exists
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void createMountPoint( int cellHandle,
+ String directory,
+ String volumeName,
+ boolean readWrite,
+ boolean forceCheck )
+ throws AFSException;
+
+ /*
+ * Sets an ACL for a given place in the AFS file system.
+ *
+ * @param directory the full path of the place in the AFS file system
+ * for which to add an entry
+ * @param username the name of the user or group for which to add an entry
+ * @param read whether or not to allow read access to this user
+ * @param write whether or not to allow write access to this user
+ * @param lookup whether or not to allow lookup access to this user
+ * @param delete whether or not to allow deletion access to this user
+ * @param insert whether or not to allow insertion access to this user
+ * @param lock whether or not to allow lock access to this user
+ * @param admin whether or not to allow admin access to this user
+ * @exception AFSException If an error occurs in the native code
+ */
+ public static native void setACL( String directory, String username,
+ boolean read, boolean write,
+ boolean lookup, boolean delete,
+ boolean insert, boolean lock,
+ boolean admin )
+ throws AFSException;
+
+ /**
+ * Gets the maximum group pts ID that's been used within a cell.
+ * The next auto-assigned group ID will be one less (more negative)
+ * than this value.
+ *
+ * @param cellHandle the handle of the cell to which the group belongs
+ * @see Cell#getCellHandle
+ * @return an integer reresenting the max group id in a cell
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getMaxGroupID( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Sets the maximum group pts ID that's been used within a cell. The next
+ * auto-assigned group ID will be one less (more negative) than this value.
+ *
+ * @param cellHandle the handle of the cell to which the group belongs
+ * @see Cell#getCellHandle
+ * @param maxID an integer reresenting the new max group id in a cell
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void setMaxGroupID( int cellHandle, int maxID )
+ throws AFSException;
+
+ /**
+ * Gets the maximum user pts ID that's been used within a cell.
+ * The next auto-assigned user ID will be one greater (more positive)
+ * than this value.
+ *
+ * @param cellHandle the handle of the cell to which the user belongs
+ * @see Cell#getCellHandle
+ * @return an integer reresenting the max user id in a cell
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getMaxUserID( int cellHandle )
+ throws AFSException;
+
+ /**
+ * Sets the maximum user pts ID that's been used within a cell. The next
+ * auto-assigned user ID will be one greater (more positive) than this value.
+ *
+ * @param cellHandle the handle of the cell to which the user belongs
+ * @see Cell#getCellHandle
+ * @param maxID an integer reresenting the new max user id in a cell
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void setMaxUserID( int cellHandle, int maxID )
+ throws AFSException;
+
+ /**
+ * Reclaims all memory being saved by the cell portion of the native library.
+ * This method should be called when no more <code>Cell</code> objects
+ * are expected to be used.
+ */
+ protected static native void reclaimCellMemory();
+
+
+ /////////////// native methods jafs_Cell ////////////////////
+
+ /**
+ * Opens a cell for administrative use, based on the token provided.
+ * Returns a cell handle to be used by other methods as a means of
+ * authentication.
+ *
+ * @param cellName the name of the cell for which to get the handle
+ * @param tokenHandle a token handle previously returned by a call to
+ * {@link Token#getHandle}
+ * @return a handle to the open cell
+ * @exception AFSException If an error occurs in the native code
+ * @see Token#getHandle
+ */
+ protected static native int getCellHandle( String cellName, int tokenHandle )
+ throws AFSException;
+
+ /**
+ * Closes the given currently open cell handle.
+ *
+ * @param cellHandle the cell handle to close
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void closeCell( int cellHandle )
+ throws AFSException;
+}
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * @(#)ErrorTable.java 2.0 11/06/2000
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.util.ResourceBundle;
+import java.util.Locale;
+
+/**
+ * Static class for error code message management.
+ *
+ * <P>Simply translates all error codes returned by the AFS native library
+ * to literal string messages according to the defined locale.
+ *
+ * @version 2.0, 11/06/2000
+ */
+public final class ErrorTable
+{
+ /* Undefined Error Constants */
+ public static final int UNKNOWN = -3;
+ public static final int SPECIAL_CASE = -2;
+ public static final int GENERAL_FAILURE = -1;
+
+ /* Java Application Error Constants */
+ public static final int NULL = 1000;
+ public static final int INVALID_SESSION = 1001;
+ public static final int EXPIRED_SESSION = 1002;
+ public static final int OPERATION_ABORTED = 1003;
+ public static final int FORCED_ABORT = 1004;
+
+ /* General UNIX Error Constants */
+ public static final int NOT_PERMITTED = 1;
+ public static final int NOT_FOUND = 2;
+ public static final int IO_ERROR = 5;
+ public static final int NO_DEVICE_ADDRESS = 6;
+ public static final int BAD_FILE = 9;
+ public static final int TRY_AGAIN = 11;
+ public static final int OUT_OF_MEMORY = 12;
+ public static final int PERMISSION_DENIED = 13;
+ public static final int BAD_ADDRESS = 14;
+ public static final int DEVICE_BUSY = 16;
+ public static final int FILE_EXISTS = 17;
+ public static final int NO_DEVICE = 19;
+ public static final int NOT_DIRECTORY = 20;
+ public static final int IS_DIRECTORY = 21;
+ public static final int INVALID_ARG = 22;
+ public static final int FILE_OVERFLOW = 23;
+ public static final int FILE_BUSY = 26;
+ public static final int NAME_TOO_LONG = 36;
+ public static final int DIRECTORY_NOT_EMPTY = 39;
+ public static final int CONNECTION_TIMED_OUT = 110;
+ public static final int QUOTA_EXCEEDED = 122;
+
+ /* AFS Error Constants */
+ public static final int BAD_USERNAME = 180486;
+ public static final int BAD_PASSWORD = 180490;
+ public static final int EXPIRED_PASSWORD = 180519;
+ public static final int SKEWED_CLOCK = 180514;
+ public static final int ID_LOCKED = 180522;
+ public static final int CELL_NOT_FOUND = 180501;
+ public static final int USERNAME_EXISTS = 180481;
+ public static final int USER_DOES_NOT_EXIST = 180484;
+
+ /* AFS Authentication Error Constants */
+ public static final int PRPERM = 267269;
+ public static final int UNOACCESS = 5407;
+ public static final int BZACCESS = 39430;
+ public static final int KANOAUTH = 180488;
+ public static final int RXKADNOAUTH = 19270405;
+
+ private static java.util.Hashtable bundles;
+
+ static
+ {
+ bundles = new java.util.Hashtable(2);
+ try {
+ bundles.put(Locale.US,
+ ResourceBundle.getBundle("ErrorMessages", Locale.US));
+ bundles.put(Locale.SIMPLIFIED_CHINESE,
+ ResourceBundle.getBundle("ErrorMessages", Locale.SIMPLIFIED_CHINESE));
+ } catch (Exception e) {
+ bundles.put(Locale.getDefault(),
+ ResourceBundle.getBundle("ErrorMessages"));
+ }
+ }
+
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Tests to identify if the return code is a "Permission Denied" error.
+ *
+ * <P> This method will qualify <CODE>errno</CODE> against:
+ * <LI><CODE>ErrorTable.PERMISSION_DENIED</CODE>
+ * <LI><CODE>ErrorTable.PRPERM</CODE>
+ * <LI><CODE>ErrorTable.UNOACCESS</CODE>
+ * <LI><CODE>ErrorTable.BZACCESS</CODE>
+ * <LI><CODE>ErrorTable.KANOAUTH</CODE>
+ * <LI><CODE>ErrorTable.RXKADNOAUTH</CODE>
+ *
+ * @param errno Error Code/Number
+ * @return boolean If <CODE>errno</CODE> is a "Permission Denied"
+ * error.
+ */
+ public static boolean isPermissionDenied(int errno)
+ {
+ return (errno == PERMISSION_DENIED || errno == PRPERM ||
+ errno == UNOACCESS || errno == BZACCESS || errno == KANOAUTH
+ || errno == RXKADNOAUTH);
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns a String message representing the error code (number) provided.
+ *
+ * <P> If the error code provided is out of range of the library of defined
+ * error codes, this method will return <CODE>Error number [###] unknown
+ * </CODE>. If an exception is thrown, this method will return either:
+ * <CODE>Unknown error</CODE>, <CODE>Special case error</CODE>, or
+ * <CODE>Invalid error code: ###</CODE>.
+ *
+ * @param errno Error Code/Number
+ * @return String Interpreted error message derived from
+ * <CODE>errno</CODE>.
+ */
+ public static String getMessage(int errno)
+ {
+ return getMessage(errno, Locale.getDefault());
+ }
+ /*-----------------------------------------------------------------------*/
+ /**
+ * Returns a String message, respective to the provided locale, representing
+ * the error code (number) provided.
+ *
+ * <P> If the error code provided is out of range of the library of defined
+ * error codes, this method will return <CODE>Error number [###] unknown
+ * </CODE>. If an exception is thrown, this method will return either:
+ * <CODE>Unknown error</CODE>, <CODE>Special case error</CODE>, or
+ * <CODE>Invalid error code: ###</CODE>.
+ *
+ * @param errno Error Code/Number
+ * @param locale Locale of to be used for translating the message.
+ * @return String Interpreted error message derived from
+ * <CODE>errno</CODE>.
+ */
+ public static String getMessage(int errno, Locale locale)
+ {
+ String msg = "Error number [" + errno + "] unknown.";
+ try {
+ msg = getBundle(locale).getString("E" + errno);
+ } catch (Exception e) {
+ try {
+ if (errno == 0) {
+ msg = "";
+ } else if (errno == GENERAL_FAILURE) {
+ msg = getBundle(locale).getString("GENERAL_FAILURE");
+ } else if (errno == UNKNOWN) {
+ msg = getBundle(locale).getString("UNKNOWN");
+ } else if (errno == SPECIAL_CASE) {
+ msg = getBundle(locale).getString("SPECIAL_CASE");
+ } else {
+ System.err.println("ERROR in ErrorCode getMessage(): " + e);
+ msg = "Invaid error code: " + errno;
+ }
+ } catch (Exception e2) {
+ //INGORE
+ }
+ } finally {
+ return msg;
+ }
+ }
+ /*-----------------------------------------------------------------------*/
+ private static ResourceBundle getBundle(Locale locale) throws Exception
+ {
+ if (locale == null) return getBundle(Locale.getDefault());
+ ResourceBundle rb = (ResourceBundle)bundles.get(locale);
+ if (rb == null) {
+ rb = ResourceBundle.getBundle("ErrorMessages", locale);
+ bundles.put(locale, rb);
+ }
+ return rb;
+ }
+}
+
+
+
--- /dev/null
+/*
+ * @(#)File.java 1.3 10/12/2000
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/*****************************************************************************/
+/**
+ *
+ * An abstract representation of AFS file and directory pathnames.
+ *
+ * This class is an extension of the standard Java File class with file-based
+ * manipulation methods overridden by integrated AFS native methods.
+ *
+ * <p> Extension methods include:
+ *
+ * <ol>
+ * <li> <code>{@link #isMountPoint}</code>
+ * <li> <code>{@link #isLink}</code>
+ * <li> <code>{@link #isValidated}</code>
+ * <li> <code>{@link #validate}</code>
+ * <li> <code>{@link #refresh}</code>
+ * <li> <code>{@link #getErrorCode}</code>
+ * <li> <code>{@link #getErrorMessage}</code>
+ * </ol>
+ *
+ * <p> For performance optimization, all newly constructed <code>File</code>
+ * objects are only validated once. Furthermore, if an abstract pathname
+ * denotes a symbolic-link, then the {@link #isLink} attribute is set
+ * to true and the {@link #getTarget} field member is populated with
+ * this symbolic-link's target resource. (see {@link #getTarget})
+ *
+ * <p> If you are interested in validating the target resource, simply
+ * call {@link #validate} before calling any of the attribute accessors.
+ * This action will <code>stat</code> the target resource, identifying
+ * its associated attributes and populating them in this objects field
+ * members.
+ *
+ * <p> Following is an example of how to construct a new AFS File Object:
+ * <p><blockquote><pre>
+ * try {
+ * File file = new File("/afs/mycell.com/proj/");
+ * if (file.isDirectory()) {
+ * System.out.println("This is a directory.");
+ * } else if (file.isLink()) {
+ * System.out.println("This is a symbolic-link.");
+ * System.out.println(" Its target is: " + file.getTarget());
+ * file.validate();
+ * if (file.isFile()) {
+ * System.out.println(" This object is now a file!");
+ * } else if (file.isDirectory()) {
+ * System.out.println(" This object is now a directory!");
+ * } else if (file.isMountPoint()) {
+ * System.out.println(" This object is now a volume mount point!");
+ * }
+ * } else if (file.isMountPoint()) {
+ * System.out.println("This is a volume mount point.");
+ * } else if (file.isFile()) {
+ * System.out.println("This is file.");
+ * System.out.println(" its size is: " + file.length());
+ * }
+ * } catch (AFSFileException ae) {
+ * System.out.println("AFS Exception: " + ae.getMessage());
+ * System.out.println("AFS Error Code: " + ae.getErrorCode());
+ * } catch (Exception e) {
+ * System.out.println("Exception: " + e.getMessage());
+ * e.printStackTrace();
+ * }
+ * </pre></blockquote>
+ *
+ * @version 2.0, 04/16/2001 - Completely revised class for efficiency.
+ * @version 1.3, 10/12/2000 - Introduced error code capture from native methods.
+ * @version 1.2, 05/30/2000
+ */
+public class File extends java.io.File implements Comparable
+{
+ private String path;
+ private String type;
+ private String target;
+
+ /** Each member is mutually exclusive */
+ private boolean isMountPoint = false;
+ private boolean isDirectory = false;
+ private boolean isFile = false;
+ private boolean isLink = false;
+
+ private boolean exists;
+ private long lastModified;
+ private long length;
+
+ private ACL.Entry acl;
+ private boolean validated = false;
+ private long dirHandle;
+ private int permissionsMask;
+ private int errno;
+
+ /**
+ * Creates a new <code>File</code> instance by converting the given
+ * pathname string into an abstract pathname and validating it against
+ * the file system. If the given string is an empty string, then the
+ * result is the empty abstract pathname; otherwise the abstract pathname
+ * is <code>validated</code> to represent a qualified file object.
+ *
+ * @param pathname A pathname string
+ * @throws NullPointerException
+ * If the <code>pathname</code> argument is <code>null</code>
+ * @throws AFSFileException
+ * If the user constructing this AFS file object is denied
+ * access to stat the file or simply a stat cannot be performed
+ * on the file. The reason code and message will be available
+ * from {@link org.openafs.jafs.AFSFileException#getErrorCode} and
+ * {@link org.openafs.jafs.AFSFileException#getMessage} respectively.
+ * <p> This exception <U>will not</U> be thrown if the file does not
+ * exist. Rather, the {@link #exists} attribute will be set to
+ * <code>false</code>.
+ * @see #validate()
+ */
+ public File(String pathname) throws AFSFileException
+ {
+ super(pathname);
+ path = getAbsolutePath();
+ validated = setAttributes();
+ if (!validated) throw new AFSFileException(errno);
+ }
+ /**
+ * Creates a new <code>File</code> instance by converting the given
+ * pathname string into an abstract pathname. If the given string is
+ * an empty string, then the result is the empty abstract pathname.
+ *
+ * <p> The abstract pathname will remain <B>abstract</B> unless the
+ * <code>validate</code> parameter is set to <code>true</code>. This
+ * means that the abstract pathname will <U>not</U> be <code>validated</code>
+ * and therefore the file object will not represent a qualified, attributed,
+ * AFS file resource. Rather, this constructor provides a method by which
+ * you can construct a non-validated <code>File</code> object (one that
+ * does not contain the file's complete status information).
+ *
+ * <p> This constructor is useful for creating file objects of file/path names
+ * that you know exist, however are unauthorized to <code>validate</code> (or
+ * <code>stat</code> - to obtain complete status information). For example,
+ * if you are permitted to <code>lookup</code> (see: {@link #canLookup}) the
+ * contents of a given directory yet <U>not</U> permitted to <code>read</code>
+ * (see: {@link #canRead}), then this constructor would enable you to render the
+ * contents of the directory without validating each entry.
+ *
+ * <p> <B>Please note:</B> this is the only constructor that does not throw an AFSFileException.
+ *
+ * @param pathname A pathname string
+ * @param validate A boolean flag to indicate if this abstract path
+ * should be validated.
+ * @throws NullPointerException
+ * If the <code>pathname</code> argument is <code>null</code>
+ * @see #File(String)
+ * @see #validate()
+ */
+ public File(String pathname, boolean validate)
+ {
+ super(pathname);
+ path = getAbsolutePath();
+ if (validate) validated = setAttributes();
+ }
+ /**
+ * Creates a new <code>File</code> instance from a parent pathname string
+ * and a child pathname string and validates it against the file system.
+ *
+ * <p> If <code>parent</code> is <code>null</code> then the new
+ * <code>File</code> instance is created as if by invoking the
+ * single-argument <code>File</code> constructor on the given
+ * <code>filename</code> string (child pathname).
+ *
+ * <p> Otherwise the <code>parent</code> pathname string is taken to denote
+ * a directory, and the <code>filename</code> string is taken to
+ * denote either a directory or a file. The directory or file will then be
+ * <code>validated</code> to represent a qualified file object.
+ *
+ * @param parent The parent pathname string
+ * @param filename This file's pathname string (child of specified parent)
+ * @throws NullPointerException
+ * If <code>child</code> is <code>null</code>
+ * @throws AFSFileException
+ * If the user constructing this AFS file object is denied
+ * access to stat the file or simply a stat cannot be performed
+ * on the file. The reason code and message will be available
+ * from {@link org.openafs.jafs.AFSFileException#getErrorCode} and
+ * {@link org.openafs.jafs.AFSFileException#getMessage} respectively.
+ * <p> This exception <U>will not</U> be thrown if the file does not
+ * exist. Rather, the {@link #exists} attribute will be set to
+ * <code>false</code>.
+ * @see #validate()
+ */
+ public File(String parent, String filename) throws AFSFileException
+ {
+ super(parent, filename);
+ path = getAbsolutePath();
+ validated = setAttributes();
+ if (!validated) throw new AFSFileException(errno);
+ }
+ /**
+ * Creates a new <code>File</code> instance from a parent pathname string
+ * and a child pathname string.
+ *
+ * <p> If <code>parent</code> is <code>null</code> then the new
+ * <code>File</code> instance is created as if by invoking the
+ * single-argument <code>File</code> constructor on the given
+ * <code>filename</code> string (child pathname).
+ *
+ * <p> Otherwise the <code>parent</code> pathname string is taken to denote
+ * a directory, and the <code>filename</code> string is taken to
+ * denote either a directory or a file.
+ *
+ * <p> The abstract pathname will remain <B>abstract</B> unless the
+ * <code>validate</code> parameter is set to <code>true</code>. This
+ * means that the abstract pathname will <U>not</U> be <code>validated</code>
+ * and therefore the file object will not represent a qualified, attributed,
+ * AFS file resource. Rather, this constructor provides a method by which
+ * you can construct a non-validated <code>File</code> object (one that
+ * does not contain the file's complete status information).
+ *
+ * <p> This constructor is useful for creating file objects of file/path names
+ * that you know exist, however are unauthorized to <code>validate</code> (or
+ * <code>stat</code> - to obtain complete status information). For example,
+ * if you are permitted to <code>lookup</code> (see: {@link #canLookup}) the
+ * contents of a given directory yet <U>not</U> permitted to <code>read</code>
+ * (see: {@link #canRead}), then this constructor would enable you to render the
+ * contents of the directory without validating each entry.
+ *
+ * @param parent The parent pathname string
+ * @param filename This file's pathname string (child of specified parent)
+ * @param validate A boolean flag to indicate if this abstract path
+ * should be validated.
+ * @throws NullPointerException
+ * If <code>child</code> is <code>null</code>
+ * @throws AFSFileException
+ * If the user constructing this AFS file object is denied
+ * access to stat the file or simply a stat cannot be performed
+ * on the file. The reason code and message will be available
+ * from {@link org.openafs.jafs.AFSFileException#getErrorCode} and
+ * {@link org.openafs.jafs.AFSFileException#getMessage} respectively.
+ * <p> This exception <U>will not</U> be thrown if the file does not
+ * exist. Rather, the {@link #exists} attribute will be set to
+ * <code>false</code>.
+ * @see #File(String, String)
+ * @see #validate()
+ */
+ public File(String parent, String filename, boolean validate) throws AFSFileException
+ {
+ super(parent, filename);
+ path = getAbsolutePath();
+ if (validate) {
+ validated = setAttributes();
+ if (!validated) throw new AFSFileException(errno);
+ }
+ }
+ /**
+ * Creates a new <code>File</code> instance from a parent abstract
+ * pathname and a child pathname string and validates it against the file system.
+ *
+ * <p> If <code>parent</code> is <code>null</code> then the new
+ * <code>File</code> instance is created as if by invoking the
+ * single-argument <code>File</code> constructor on the given
+ * <code>filename</code> string (child pathname).
+ *
+ * <p> Otherwise the <code>parent</code> abstract pathname is taken to
+ * denote a directory, and the <code>filename</code> string is taken
+ * to denote either a directory or a file. The directory or file will then be
+ * <code>validated</code> to represent a qualified file object.
+ *
+ * @param parent The parent abstract pathname
+ * @param filename This file's pathname string (child of specified parent)
+ * @param validate A boolean flag to indicate if this abstract path
+ * should be validated.
+ * @throws NullPointerException
+ * If <code>child</code> is <code>null</code>
+ * @throws AFSFileException
+ * If the user constructing this AFS file object is denied
+ * access to stat the file or simply a stat cannot be performed
+ * on the file. The reason code and message will be available
+ * from {@link org.openafs.jafs.AFSFileException#getErrorCode} and
+ * {@link org.openafs.jafs.AFSFileException#getMessage} respectively.
+ * <p> This exception <U>will not</U> be thrown if the file does not
+ * exist. Rather, the {@link #exists} attribute will be set to
+ * <code>false</code>.
+ * @see #validate()
+ */
+ public File(File parent, String filename) throws AFSFileException
+ {
+ super(parent, filename);
+ path = getAbsolutePath();
+ validated = setAttributes();
+ if (!validated) throw new AFSFileException(errno);
+ }
+ /**
+ * Creates a new <code>File</code> instance from a parent abstract
+ * pathname and a child pathname string.
+ *
+ * <p> If <code>parent</code> is <code>null</code> then the new
+ * <code>File</code> instance is created as if by invoking the
+ * single-argument <code>File</code> constructor on the given
+ * <code>filename</code> string (child pathname).
+ *
+ * <p> Otherwise the <code>parent</code> abstract pathname is taken to
+ * denote a directory, and the <code>filename</code> string is taken
+ * to denote either a directory or a file.
+ *
+ * <p> The abstract pathname will remain <B>abstract</B> unless the
+ * <code>validate</code> parameter is set to <code>true</code>. This
+ * means that the abstract pathname will <U>not</U> be <code>validated</code>
+ * and therefore the file object will not represent a qualified, attributed,
+ * AFS file resource. Rather, this constructor provides a method by which
+ * you can construct a non-validated <code>File</code> object (one that
+ * does not contain the file's complete status information).
+ *
+ * <p> This constructor is useful for creating file objects of file/path names
+ * that you know exist, however are unauthorized to <code>validate</code> (or
+ * <code>stat</code> - to obtain complete status information). For example,
+ * if you are permitted to <code>lookup</code> (see: {@link #canLookup}) the
+ * contents of a given directory yet <U>not</U> permitted to <code>read</code>
+ * (see: {@link #canRead}), then this constructor would enable you to render the
+ * contents of the directory without validating each entry.
+ *
+ * @param parent The parent abstract pathname
+ * @param filename This file's pathname string (child of specified parent)
+ * @param validate A boolean flag to indicate if this abstract path
+ * should be validated.
+ * @throws NullPointerException
+ * If <code>child</code> is <code>null</code>
+ * @throws AFSFileException
+ * If the user constructing this AFS file object is denied
+ * access to stat the file or simply a stat cannot be performed
+ * on the file. The reason code and message will be available
+ * from {@link org.openafs.jafs.AFSFileException#getErrorCode} and
+ * {@link org.openafs.jafs.AFSFileException#getMessage} respectively.
+ * <p> This exception <U>will not</U> be thrown if the file does not
+ * exist. Rather, the {@link #exists} attribute will be set to
+ * <code>false</code>.
+ * @see #validate()
+ * @see #File(File, String)
+ */
+ public File(File parent, String filename, boolean validate) throws AFSFileException
+ {
+ super(parent, filename);
+ path = getAbsolutePath();
+ if (validate) {
+ validated = setAttributes();
+ if (!validated) throw new AFSFileException(errno);
+ }
+ }
+
+ /*****************************************************************************/
+
+ /**
+ * Validates this abstract pathname as an attributed AFS file object.
+ * This method will, if authorized, perform a <code>stat</code> on the
+ * actual AFS file and update its respective field members; defining
+ * this file object's attributes.
+ *
+ * @throws AFSSecurityException
+ * If an AFS exception occurs while attempting to stat and set this
+ * AFS file object's attributes.
+ */
+ public void validate() throws AFSSecurityException
+ {
+ validated = setAttributes();
+ if (!validated) throw new AFSSecurityException(errno);
+ }
+ /**
+ * Tests whether the file denoted by this abstract pathname has
+ * been validated.
+ *
+ * <P> Validation is always attempted upon construction of the file object,
+ * therefore if this method returns false, then you are not permitted to
+ * <code>validate</code> this file and consequently all attribute accessors
+ * will be invalid.
+ *
+ * <P> This method should return <code>true</code> even if this abstract
+ * pathname does not exist. If this is abstract pathname does not exist then
+ * the <code>{@link #exists}</code> method should return false, however this
+ * implies that the attribute accessors are valid and accurate; thus implying
+ * successful validation.
+ *
+ * <P> This method is useful before calling any of the attribute accessors
+ * to ensure a valid response.
+ *
+ * @return <code>true</code> if and only if the file denoted by this
+ * abstract pathname has been validated during or after object construction;
+ * <code>false</code> otherwise
+ */
+ public boolean isValidated()
+ {
+ return validated;
+ }
+ /**
+ * Refreshes this AFS file object by updating its attributes.
+ * This method currently provides the same functionality as
+ * {@link #validate}.
+ *
+ * @throws AFSSecurityException
+ * If an AFS exception occurs while attempting to stat and update this
+ * AFS file object's attributes.
+ * @see #validate()
+ */
+ public void refresh() throws AFSSecurityException
+ {
+ validate();
+ }
+ /*-------------------------------------------------------------------------*/
+ /**
+ * Tests whether the file denoted by this abstract pathname is a
+ * directory.
+ *
+ * @return <code>true</code> if and only if the file denoted by this
+ * abstract pathname exists <em>and</em> is a directory;
+ * <code>false</code> otherwise
+ */
+ public boolean isDirectory()
+ {
+ return (isDirectory || isMountPoint) ? true : false;
+ }
+ /**
+ * Tests whether the file denoted by this abstract pathname is a normal
+ * file. A file is <em>normal</em> if it is not a directory and, in
+ * addition, satisfies other system-dependent criteria. Any non-directory
+ * file created by a Java application is guaranteed to be a normal file.
+ *
+ * @return <code>true</code> if and only if the file denoted by this
+ * abstract pathname exists <em>and</em> is a normal file;
+ * <code>false</code> otherwise
+ */
+ public boolean isFile()
+ {
+ return isFile;
+ }
+ /**
+ * Tests whether the file denoted by this abstract pathname is an
+ * AFS Volume Mount Point.
+ *
+ * @return <code>true</code> if and only if the file denoted by this
+ * abstract pathname exists <em>and</em> is a mount point;
+ * <code>false</code> otherwise
+ */
+ public boolean isMountPoint()
+ {
+ return isMountPoint;
+ }
+ /**
+ * Tests whether the file denoted by this abstract pathname is a
+ * symbolic-link.
+ *
+ * @return <code>true</code> if and only if the file denoted by this
+ * abstract pathname exists <em>and</em> is a symbolic-link;
+ * <code>false</code> otherwise
+ */
+ public boolean isLink()
+ {
+ return isLink;
+ }
+ /*-------------------------------------------------------------------------*/
+ /**
+ * Tests whether the file denoted by this abstract pathname exists.
+ *
+ * @return <code>true</code> if and only if the file denoted by this
+ * abstract pathname exists; <code>false</code> otherwise
+ */
+ public boolean exists()
+ {
+ return exists;
+ }
+ /**
+ * Returns the time that the file denoted by this abstract pathname was
+ * last modified.
+ *
+ * @return A <code>long</code> value representing the time the file was
+ * last modified, measured in milliseconds since the epoch
+ * (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
+ * file does not exist or if an I/O error occurs
+ */
+ public long lastModified()
+ {
+ return lastModified;
+ }
+ /**
+ * Returns the length of the file denoted by this abstract pathname.
+ *
+ * @return The length, in bytes, of the file denoted by this abstract
+ * pathname, or <code>0L</code> if the file does not exist
+ */
+ public long length()
+ {
+ return length;
+ }
+ /**
+ * Returns an abstract pathname string that represents the target resource of
+ * of this file, if it is a symbolic-link.
+ *
+ * <p> If this abstract pathname <B>does not</B> denote a symbolic-link, then this
+ * method returns <code>null</code>. Otherwise a string is
+ * returned that represents the target resource of this symbolic-link.
+ *
+ * @return A string representation of this symbolic-link's target resource.
+ * @see #isLink()
+ */
+ public String getTarget()
+ {
+ return target;
+ }
+ /**
+ * Returns an array of strings naming the files and directories in the
+ * directory denoted by this abstract pathname.
+ *
+ * <p> If this abstract pathname does not denote a directory, then this
+ * method returns <code>null</code>. Otherwise an array of strings is
+ * returned, one for each file or directory in the directory. Names
+ * denoting the directory itself and the directory's parent directory are
+ * not included in the result. Each string is a file name rather than a
+ * complete path.
+ *
+ * <p> There is no guarantee that the name strings in the resulting array
+ * will appear in any specific order; they are not, in particular,
+ * guaranteed to appear in alphabetical order.
+ *
+ * @return An array of strings naming the files and directories in the
+ * directory denoted by this abstract pathname. The array will be
+ * empty if the directory is empty. Returns <code>null</code> if
+ * this abstract pathname does not denote a directory, or if an
+ * I/O error occurs.
+ */
+ public String[] list()
+ {
+ try {
+ if (isFile()) {
+ errno = ErrorTable.NOT_DIRECTORY;
+ return null;
+ }
+ ArrayList buffer = new ArrayList();
+ dirHandle = listNative(buffer);
+ if (dirHandle == 0) {
+ return null;
+ } else {
+ return (String[])buffer.toArray(new String[0]);
+ }
+ } catch (Exception e) {
+ System.out.println(e);
+ return null;
+ }
+ }
+ /**
+ * Returns an ArrayList object containing strings naming the files and
+ * directories in the directory denoted by this abstract pathname.
+ *
+ * <p> If this abstract pathname does not denote a directory, then this
+ * method returns <code>null</code>. Otherwise an array of strings is
+ * returned, one for each file or directory in the directory. Names
+ * denoting the directory itself and the directory's parent directory are
+ * not included in the result. Each string is a file name rather than a
+ * complete path.
+ *
+ * <p> There is no guarantee that the name strings in the resulting array
+ * will appear in any specific order; they are not, in particular,
+ * guaranteed to appear in alphabetical order.
+ *
+ * @return An array of strings naming the files and directories in the
+ * directory denoted by this abstract pathname. The array will be
+ * empty if the directory is empty. Returns <code>null</code> if
+ * this abstract pathname does not denote a directory, or if an
+ * I/O error occurs.
+ * @throws AFSSecurityException
+ * If you are not authorized to list the contents of this directory
+ * @throws AFSFileException
+ * If this file object is not a <code>mount point</code>, <code>link
+ * </code>, or <code>directory</code> <B>or</B> an unexpected AFS
+ * error occurs.
+ * @see #list()
+ */
+ public ArrayList listArray() throws AFSFileException
+ {
+ try {
+ if (isFile()) throw new AFSFileException(ErrorTable.NOT_DIRECTORY);
+ ArrayList buffer = new ArrayList();
+ dirHandle = listNative(buffer);
+ if (dirHandle == 0) {
+ if (errno == ErrorTable.PERMISSION_DENIED) {
+ throw new AFSSecurityException(errno);
+ } else {
+ throw new AFSFileException(errno);
+ }
+ } else {
+ return buffer;
+ }
+ } catch (Exception e) {
+ System.out.println(e);
+ throw new AFSFileException(errno);
+ }
+ }
+ /*-------------------------------------------------------------------------*/
+ /**
+ * Deletes the file or directory denoted by this abstract pathname. If
+ * this pathname denotes a directory, then the directory must be empty in
+ * order to be deleted.
+ *
+ * @return <code>true</code> if and only if the file or directory is
+ * successfully deleted; <code>false</code> otherwise
+ */
+ public boolean delete()
+ {
+ try {
+ if(this.isDirectory()) {
+ return this.rmdir();
+ } else if(this.isFile() || this.isLink()) {
+ return this.rmfile();
+ }
+ return false;
+ } catch (Exception e) {
+ System.out.println(e);
+ return false;
+ }
+ }
+ /**
+ * Copies the file denoted by this abstract pathname to the destination
+ * file provided. Then checks the newly copied file's size to
+ * test for file size consistency.
+ *
+ * @param dest The new abstract pathname for the named file
+ *
+ * @return <code>true</code> if and only if the file that was copied
+ * reports the same file size (length) as that of this file;
+ * <code>false</code> otherwise
+ *
+ * @throws AFSFileException
+ * If an I/O or AFS exception is encountered while copying the file.
+ */
+ public boolean copyTo(File dest) throws AFSFileException
+ {
+ FileInputStream fis = new FileInputStream(this);
+ FileOutputStream fos = new FileOutputStream(dest);
+ byte[] buf = new byte[1024];
+ int i = 0;
+ while((i=fis.read(buf))!=-1) {
+ fos.write(buf, 0, i);
+ }
+ fis.close();
+ fos.close();
+ dest.validate();
+ return (dest.length() == this.length());
+ }
+ /*-------------------------------------------------------------------------*/
+ /**
+ * Returns the permissions mask of the ACL for this object relative to the user accessing it.
+ *
+ * @return the permissions mask of this object based upon the current user.
+ * @see org.openafs.jafs.ACL.Entry#getPermissionsMask()
+ */
+ public int getPermissionsMask()
+ {
+ return getRights();
+ }
+ /**
+ * Tests whether the user can administer the ACL (see: {@link org.openafs.jafs.ACL}
+ * of the directory denoted by this abstract pathname.
+ *
+ * @see org.openafs.jafs.ACL.Entry#canAdmin
+ * @return <code>true</code> if and only if the directory specified by this
+ * abstract pathname exists <em>and</em> can be administered by the
+ * current user; <code>false</code> otherwise
+ */
+ public boolean canAdmin()
+ {
+ if (acl == null) acl = new ACL.Entry(getRights());
+ return acl.canAdmin();
+ }
+ /**
+ * Tests whether the current user can delete the files or subdirectories of
+ * the directory denoted by this abstract pathname.
+ *
+ * @see org.openafs.jafs.ACL.Entry#canDelete
+ * @return <code>true</code> if and only if the directory specified by this
+ * abstract pathname exists <em>and</em> permits deletion of its files
+ * and subdirectories by the current user; <code>false</code> otherwise
+ */
+ public boolean canDelete()
+ {
+ if (acl == null) acl = new ACL.Entry(getRights());
+ return acl.canDelete();
+ }
+ /**
+ * Tests whether the current user can insert a file into the directory
+ * denoted by this abstract pathname.
+ *
+ * @see org.openafs.jafs.ACL.Entry#canInsert
+ * @return <code>true</code> if and only if the directory specified by this
+ * abstract pathname exists <em>and</em> a file can be inserted by the
+ * current user; <code>false</code> otherwise
+ */
+ public boolean canInsert()
+ {
+ if (acl == null) acl = new ACL.Entry(getRights());
+ return acl.canInsert();
+ }
+ /**
+ * Tests whether the current user can lock the file denoted by this
+ * abstract pathname.
+ *
+ * @see org.openafs.jafs.ACL.Entry#canLock
+ * @return <code>true</code> if and only if the file specified by this
+ * abstract pathname exists <em>and</em> can be locked by the
+ * current user; <code>false</code> otherwise
+ */
+ public boolean canLock()
+ {
+ if (acl == null) acl = new ACL.Entry(getRights());
+ return acl.canLock();
+ }
+ /**
+ * Tests whether the current user can lookup the contents of the directory
+ * denoted by this abstract pathname.
+ *
+ * @see org.openafs.jafs.ACL.Entry#canLookup
+ * @return <code>true</code> if and only if the directory specified by this
+ * abstract pathname exists <em>and</em> its contents can be listed by the
+ * current user; <code>false</code> otherwise
+ */
+ public boolean canLookup()
+ {
+ if (acl == null) acl = new ACL.Entry(getRights());
+ return acl.canLookup();
+ }
+ /**
+ * Tests whether the current user can read the file denoted by this
+ * abstract pathname.
+ *
+ * @see org.openafs.jafs.ACL.Entry#canRead
+ * @return <code>true</code> if and only if the file specified by this
+ * abstract pathname exists <em>and</em> can be read by the
+ * current user; <code>false</code> otherwise
+ */
+ public boolean canRead()
+ {
+ if (acl == null) acl = new ACL.Entry(getRights());
+ return acl.canRead();
+ }
+ /**
+ * Tests whether the current user can modify to the file denoted by this
+ * abstract pathname.
+ *
+ * @see org.openafs.jafs.ACL.Entry#canWrite
+ * @return <code>true</code> if and only if the file system actually
+ * contains a file denoted by this abstract pathname <em>and</em>
+ * the current user is allowed to write to the file;
+ * <code>false</code> otherwise.
+ */
+ public boolean canWrite()
+ {
+ if (acl == null) acl = new ACL.Entry(getRights());
+ return acl.canWrite();
+ }
+ /*-------------------------------------------------------------------------*/
+ /**
+ * Closes the directory denoted by this abstract pathname.
+ *
+ * @return <code>true</code> if and only if the directory is
+ * successfully closed; <code>false</code> otherwise
+ */
+ public boolean close()
+ {
+ if (dirHandle == 0) {
+ return false;
+ }
+ return closeDir(dirHandle);
+ }
+ /*-------------------------------------------------------------------------*/
+ /**
+ * Returns the AFS specific error number (code). This code can be interpreted
+ * by use of <code>{@link org.openafs.jafs.ErrorTable}</code> static class method
+ * <code>{@link org.openafs.jafs.ErrorTable#getMessage}</code>
+ *
+ * @return the AFS error code (number) associated with the last action performed
+ * on this object.
+ * @see org.openafs.jafs.ErrorTable#getMessage(int)
+ */
+ public int getErrorCode()
+ {
+ return errno;
+ }
+ /**
+ * Returns the AFS error message string defined by the <code>{@link org.openafs.jafs.ErrorTable}</code>
+ * class.
+ *
+ * @return the AFS error message string associated with the last action performed
+ * on this object.
+ * @see org.openafs.jafs.ErrorTable#getMessage(int)
+ */
+ public String getErrorMessage()
+ {
+ return ErrorTable.getMessage(errno);
+ }
+
+ /////////////// custom override methods ////////////////////
+
+ /**
+ * Compares two File objects relative to their filenames and <B>does not</B>
+ * compare their respective absolute paths. Alphabetic case is significant in
+ * comparing filenames.
+ *
+ * @param file The File object to be compared to this file's filename
+ *
+ * @return Zero if the argument is equal to this file's filename, a
+ * value less than zero if this file's filename is
+ * lexicographically less than the argument, or a value greater
+ * than zero if this file's filename is lexicographically
+ * greater than the argument
+ *
+ * @since JDK1.2
+ */
+ public int compareTo(File file) {
+ return this.getName().compareTo(file.getName());
+ }
+ /**
+ * Compares this file to another File object. If the other object
+ * is an abstract pathname, then this function behaves like <code>{@link
+ * #compareTo(File)}</code>. Otherwise, it throws a
+ * <code>ClassCastException</code>, since File objects can only be
+ * compared to File objects.
+ *
+ * @param o The <code>Object</code> to be compared to this abstract pathname
+ *
+ * @return If the argument is an File object, returns zero
+ * if the argument is equal to this file's filename, a value
+ * less than zero if this file's filename is lexicographically
+ * less than the argument, or a value greater than zero if this
+ * file's filename is lexicographically greater than the
+ * argument
+ *
+ * @throws <code>ClassCastException</code> if the argument is not an
+ * File object
+ *
+ * @see java.lang.Comparable
+ * @since JDK1.2
+ */
+ public int compareTo(Object o) throws ClassCastException
+ {
+ File file = (File)o;
+ return compareTo(file);
+ }
+
+ /////////////// public native methods ////////////////////
+
+ /**
+ * Creates the directory named by this abstract pathname.
+ *
+ * @return <code>true</code> if and only if the directory was
+ * created; <code>false</code> otherwise
+ */
+ public native boolean mkdir();
+ /**
+ * Renames the file denoted by this abstract pathname.
+ *
+ * @param dest The new abstract pathname for the named file
+ *
+ * @return <code>true</code> if and only if the renaming succeeded;
+ * <code>false</code> otherwise
+ *
+ * @throws NullPointerException
+ * If parameter <code>dest</code> is <code>null</code>
+ */
+ public native boolean renameTo(File dest);
+ /**
+ * Performs a file <code>stat</code> on the actual AFS file and populates
+ * this object's respective field members with the appropriate values.
+ * method will, if authorized, perform a <code>stat</code> on the
+ * actual AFS file and update its respective field members; defining
+ * this file object's attributes.
+ *
+ * <P><B>This method should not be used directly for refreshing or validating
+ * this AFS file object. Please use {@link #validate} instead.</B>
+ *
+ * @return <code>true</code> if and only if the current user is allowed to stat the file;
+ * <code>false</code> otherwise.
+ * @see #validate()
+ */
+ public native boolean setAttributes() throws AFSSecurityException;
+
+ /////////////// private native methods ////////////////////
+
+ /**
+ * List the contents of this directory.
+ *
+ * @return the directory handle
+ */
+ private native long listNative(ArrayList buffer) throws AFSSecurityException;
+ /**
+ * Close the currently open directory using a previously obtained handle.
+ *
+ * @return true if the directory closes without error
+ */
+ private native boolean closeDir(long dp) throws AFSSecurityException;
+ /**
+ * Removes/deletes the current directory.
+ *
+ * @return true if the directory is removed without error
+ */
+ private native boolean rmdir() throws AFSSecurityException;
+ /**
+ * Removes/deletes the current file.
+ *
+ * @return true if the file is removed without error
+ */
+ private native boolean rmfile() throws AFSSecurityException;
+ /**
+ * Returns the permission/ACL mask for this directory
+ *
+ * @return permission/ACL mask
+ */
+ private native int getRights() throws AFSSecurityException;
+ /*-------------------------------------------------------------------------*/
+}
+
+
+
+
+
+
--- /dev/null
+/*
+ * @(#)FilterInputStream.java 1.0 00/10/10
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.io.InputStream;
+
+/**
+ * This class is a file input stream for files within AFS.
+ * It is an input stream for reading data from a
+ * <code>{@link org.openafs.jafs.File}</code>.
+ *
+ * @version 2.1, 08/03/2001
+ * @see org.openafs.jafs.File
+ * @see org.openafs.jafs.FileOutputStream
+ * @see java.io.FileInputStream
+ */
+public class FileInputStream extends InputStream
+{
+ /** Status indicator for the current state of this file input stream */
+ private int fileDescriptor;
+
+ /**
+ * Creates a <code>FileInputStream</code> by
+ * opening a connection to an actual AFS file,
+ * the file named by the path name <code>name</code>
+ * in the AFS file system.
+ *
+ * @param name the name of the file to read from
+ * @exception AFSFileException If an AFS specific error occurs,
+ * if the file does not, or cannot be opened for any
+ * other reason, including authorization.
+ */
+ public FileInputStream(String name) throws AFSFileException
+ {
+ this.fileDescriptor = this.openReadOnly(name);
+ }
+ /**
+ * Creates a <code>FileInputStream</code> by
+ * opening a connection to an actual AFS file,
+ * the file represented by file <code>file</code>
+ * in the AFS file system.
+ *
+ * @param file an AFS file object representing a file to read from
+ * @exception AFSFileException If an AFS specific error occurs,
+ * if the file does not, or cannot be opened for any
+ * other reason, including authorization.
+ */
+ public FileInputStream(File file) throws AFSFileException
+ {
+ this(file.getPath());
+ }
+
+ /*-------------------------------------------------------------------------*/
+
+ /**
+ * Reads the next byte of data from this input stream. The value
+ * byte is returned as an <code>int</code> in the range
+ * <code>0</code> to <code>255</code>. If no byte is available
+ * because the end of the stream has been reached, the value
+ * <code>-1</code> is returned. This method blocks until input data
+ * is available, the end of the stream is detected, or an exception
+ * is thrown.
+ *
+ * <p>This method simply performs <code>in.read()</code> and returns
+ * the result.
+ *
+ * @return the next byte of data, or <code>-1</code> if the end of the
+ * stream is reached.
+ * @exception AFSFileException if an I/O or other file related error occurs.
+ * @see java.io.FileInputStream#read
+ */
+ public int read() throws AFSFileException
+ {
+ byte[] bytes = new byte[1];
+ this.read(bytes, 0, 1);
+ return bytes[0];
+ }
+ /**
+ * Reads up to <code>b.length</code> bytes of data from this input
+ * stream into an array of bytes. This method blocks until some input
+ * is available.
+ *
+ * @param b the buffer into which the data is read.
+ * @return the total number of bytes read into the buffer, or
+ * <code>-1</code> if there is no more data because the end of
+ * the file has been reached.
+ * @exception AFSFileException if an I/O or other file related error occurs.
+ */
+ public int read(byte[] b) throws AFSFileException
+ {
+ return this.read(b, 0, b.length);
+ }
+
+ /////////////// public native methods ////////////////////
+
+ /**
+ * Reads up to <code>len</code> bytes of data from this input stream
+ * into an array of bytes. This method blocks until some input is
+ * available.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset of the data.
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or
+ * <code>-1</code> if there is no more data because the end of
+ * the file has been reached.
+ * @exception AFSFileException if an I/O or other file related error occurs.
+ */
+ public native int read(byte[] b, int off, int len) throws AFSFileException;
+ /**
+ * Skips over and discards <code>n</code> bytes of data from the
+ * input stream. The <code>skip</code> method may, for a variety of
+ * reasons, end up skipping over some smaller number of bytes,
+ * possibly <code>0</code>. The actual number of bytes skipped is returned.
+ *
+ * @param n the number of bytes to be skipped.
+ * @return the actual number of bytes skipped.
+ * @exception AFSFileException if an I/O or other file related error occurs.
+ */
+ public native long skip(long n) throws AFSFileException;
+ /**
+ * Closes this file input stream and releases any system resources
+ * associated with the stream.
+ *
+ * @exception AFSFileException if an I/O or other file related error occurs.
+ */
+ public native void close() throws AFSFileException;
+
+ /////////////// private native methods ////////////////////
+
+ /**
+ * Opens the specified AFS file for reading.
+ *
+ * @param name fileName of file to be opened
+ * @return file descriptor
+ * @exception AFSFileException if an I/O or other file related error occurs.
+ */
+ private native int openReadOnly(String fileName) throws AFSFileException;
+
+ /*-------------------------------------------------------------------------*/
+}
+
+
+
+
+
--- /dev/null
+/*
+ * @(#)FilterOutputStream.java 1.0 00/10/10
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.io.OutputStream;
+
+/**
+ * This class is a file output stream for files within AFS.
+ * It is an output stream for writing data to a
+ * <code>{@link org.openafs.jafs.File}</code>.
+ *
+ * @version 2.1, 08/03/2001
+ * @see org.openafs.jafs.File
+ * @see org.openafs.jafs.FileInputStream
+ * @see java.io.FileOutputStream
+ */
+public class FileOutputStream extends OutputStream
+{
+ /** Status indicator for the current state of this file output stream */
+ private int fileDescriptor;
+
+ /**
+ * Creates an output file stream to write to the AFS file with the
+ * specified name.
+ * <p>
+ * If the file exists but is a directory rather than a regular file, does
+ * not exist but cannot be created, or cannot be opened for any other
+ * reason then a <code>AFSFileException</code> is thrown.
+ *
+ * @param name the name of the file to write to
+ * @exception AFSFileException If an AFS specific error occurs,
+ * if the file exists but is a directory
+ * rather than a regular file, does not exist but cannot
+ * be created, or cannot be opened for any other reason, including
+ * authorization.
+ */
+ public FileOutputStream(String name) throws AFSFileException
+ {
+ this(name, false);
+ }
+ /**
+ * Creates an output file stream to write to the AFS file with the specified
+ * <code>name</code>. If the second argument is <code>true</code>, then
+ * bytes will be written to the end of the file rather than the beginning.
+ * <p>
+ * If the file exists but is a directory rather than a regular file, does
+ * not exist but cannot be created, or cannot be opened for any other
+ * reason then a <code>AFSFileException</code> is thrown.
+ *
+ * @param name the name of the file to write to
+ * @param append if <code>true</code>, then bytes will be written
+ * to the end of the file rather than the beginning
+ * @exception AFSFileException If an AFS specific error occurs,
+ * if the file exists but is a directory
+ * rather than a regular file, does not exist but cannot
+ * be created, or cannot be opened for any other reason, including
+ * authorization.
+ */
+ public FileOutputStream(String name, boolean append) throws AFSFileException
+ {
+ if (append) {
+ fileDescriptor = this.openAppend(name);
+ } else {
+ fileDescriptor = this.openWrite(name);
+ }
+ }
+ /**
+ * Creates a file output stream to write to the AFS file represented by
+ * the specified <code>File</code> object.
+ * <p>
+ * If the file exists but is a directory rather than a regular file, does
+ * not exist but cannot be created, or cannot be opened for any other
+ * reason then a <code>AFSFileException</code> is thrown.
+ *
+ * @param file the AFS file to be opened for writing.
+ * @exception AFSFileException If an AFS specific error occurs,
+ * if the file exists but is a directory
+ * rather than a regular file, does not exist but cannot
+ * be created, or cannot be opened for any other reason, including
+ * authorization.
+ * @see org.openafs.jafs.File#getPath()
+ */
+ public FileOutputStream(File file) throws AFSFileException
+ {
+ this(file.getPath(), false);
+ }
+ /**
+ * Creates a file output stream to write to the AFS file represented by
+ * the specified <code>File</code> object.
+ * <p>
+ * If the file exists but is a directory rather than a regular file, does
+ * not exist but cannot be created, or cannot be opened for any other
+ * reason then a <code>AFSFileException</code> is thrown.
+ *
+ * @param file the AFS file to be opened for writing.
+ * @param append if <code>true</code>, then bytes will be written
+ * to the end of the file rather than the beginning
+ * @exception AFSFileException If an AFS specific error occurs,
+ * if the file exists but is a directory
+ * rather than a regular file, does not exist but cannot
+ * be created, or cannot be opened for any other reason, including
+ * authorization.
+ * @see org.openafs.jafs.File#getPath()
+ */
+ public FileOutputStream(File file, boolean append) throws AFSFileException
+ {
+ this(file.getPath(), append);
+ }
+
+ /*-------------------------------------------------------------------------*/
+
+ /**
+ * Writes the specified <code>byte</code> to this file output stream.
+ * <p>
+ * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
+ *
+ * @param b the byte to be written.
+ * @exception AFSFileException if an error occurs.
+ */
+ public void write(int b) throws AFSFileException
+ {
+ byte[] bytes = new byte[1];
+ bytes[0] = (byte) b;
+ this.write(bytes, 0, 1);
+ }
+ /**
+ * Writes <code>b.length</code> bytes from the specified byte array
+ * to this file output stream.
+ * <p>
+ * Implements the <code>write</code> method of three arguments with the
+ * arguments <code>b</code>, <code>0</code>, and
+ * <code>b.length</code>.
+ * <p>
+ * Note that this method does not call the one-argument
+ * <code>write</code> method of its underlying stream with the single
+ * argument <code>b</code>.
+ *
+ * @param b the data to be written.
+ * @exception AFSFileException if an error occurs.
+ * @see #write(byte[], int, int)
+ * @see java.io.FilterOutputStream#write(byte[], int, int)
+ */
+ public void write(byte[] b) throws AFSFileException
+ {
+ this.write(b, 0, b.length);
+ }
+
+ /////////////// public native methods ////////////////////
+
+ /**
+ * Writes <code>len</code> bytes from the specified
+ * <code>byte</code> array starting at offset <code>off</code> to
+ * this file output stream.
+ *
+ * @param b the data to be written
+ * @param off the start offset in the data
+ * @param len the number of bytes that are written
+ * @exception AFSFileException if an I/O or other file related error occurs.
+ * @see java.io.FilterOutputStream#write(int)
+ */
+ public native void write(byte[] b, int off, int len) throws AFSFileException;
+ /**
+ * Closes this file output stream and releases any system resources
+ * associated with this stream. This file output stream may no longer
+ * be used for writing bytes.
+ *
+ * @exception AFSFileException if an I/O or other file related error occurs.
+ */
+ public native void close() throws AFSFileException;
+
+ /////////////// private native methods ////////////////////
+
+ /**
+ * Opens an AFS file, with the specified name, for writing.
+ *
+ * @param filename name of file to be opened
+ * @return file descriptor
+ * @exception AFSFileException if an I/O or other file related error occurs.
+ */
+ private native int openWrite(String filename) throws AFSFileException;
+ /**
+ * Opens an AFS file, with the specified name, for appending.
+ *
+ * @param filename name of file to be opened
+ * @return file descriptor
+ * @exception AFSFileException if an I/O or other file related error occurs.
+ */
+ private native int openAppend(String filename) throws AFSFileException;
+
+ /*-------------------------------------------------------------------------*/
+}
+
+
+
+
+
--- /dev/null
+/*
+ * @(#)Group.java 1.0 6/29/2001
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.ArrayList;
+import java.io.Serializable;
+
+/**
+ * An abstract representation of an AFS group. It holds information about
+ * the group, such as what groups it owns.<BR><BR>
+ *
+ * Constructing an instance of a <code>Group</code> does not mean an actual
+ * AFS group is created in a cell -- usually a <code>Group</code>
+ * object is a representation of an already existing AFS group. If,
+ * however, the <code>Group</code> is constructed with the name of a
+ * group that does not exist in the cell represented by the provided
+ * <code>Cell</code>, a new group with that name can be
+ * created in that cell by calling the {@link #create(String, int)} or
+ * {@link #create(String)} method. If such a group does already exist when
+ * one of these methods is called, an exception will be thrown.<BR><BR>
+ *
+ * Each <code>Group</code> object has its own individual set of
+ * <code>Group</code>s that it owns and <code>User</code>s that belong
+ * to it. These represents the properties and attributes
+ * of an actual AFS group.
+ * <BR><BR>
+ *
+ * <!--Information on how member values are set-->
+ *
+ * Associated with an AFS group are many attributes, such as whether or not
+ * who is allowed to list the members of this group. The <code>Group</code>
+ * class has many "set" methods to indicate values for these attributes (i.e.
+ * {@link #setListMembership(int)}. However, in order for these values to be
+ * written to the actual AFS group, the {@link #flushInfo()} method needs to
+ * be called. This writes all user attributes set through this API to AFS.
+ * This is done to minimize calls through JNI.<BR><BR>
+ *
+ * <!--Example of how to use class-->
+ * The following is a simple example of how to construct and use a
+ * <code>Group</code> object. It lists the name and owner of a specified
+ * group.
+ *
+ * <PRE>
+ * import org.openafs.jafs.Cell;
+ * import org.openafs.jafs.AFSException;
+ * import org.openafs.jafs.Partition;
+ * import org.openafs.jafs.Group;
+ * ...
+ * public class ...
+ * {
+ * ...
+ * private Cell cell;
+ * private Group group;
+ * ...
+ * public static void main(String[] args) throws Exception
+ * {
+ * String username = arg[0];
+ * String password = arg[1];
+ * String cellName = arg[2];
+ * String groupName = arg[3];
+ *
+ * token = new Token(username, password, cellName);
+ * cell = new Cell(token);
+ * group = new Group(groupName, cell);
+ *
+ * System.out.println("Owner of group " + group.getName() + " is "
+ * + group.getOwnerName());
+ * ...
+ * }
+ * ...
+ * }
+ * </PRE>
+ *
+ */
+public class Group implements PTSEntry, Serializable, Comparable
+{
+ /**
+ * Only the owner of the group has access
+ */
+ public static final int GROUP_OWNER_ACCESS = 0;
+ /**
+ * Members of the group have access
+ */
+ public static final int GROUP_GROUP_ACCESS = 1;
+ /**
+ * Any user has access
+ */
+ public static final int GROUP_ANYUSER_ACCESS = 2;
+
+ protected Cell cell;
+ protected int cellHandle;
+ protected String name;
+
+ protected int membershipCount;
+ protected int nameUID;
+ protected int ownerUID;
+ protected int creatorUID;
+
+ protected String owner;
+ protected String creator;
+
+ /**
+ * who is allowed to execute PTS examine for this group. Valid values are:
+ * <ul>
+ * <li>{@link #GROUP_OWNER_ACCESS} -- only the owner has permission</li>
+ * <li>{@link #GROUP_GROUP_ACCESS}
+ * -- only members of the group have permission</li>
+ * <li>{@link #GROUP_ANYUSER_ACCESS} -- any user has permission</li></ul>
+ */
+ protected int listStatus;
+ /**
+ * who is allowed to execute PTS examine for this group. Valid values are:
+ * <ul>
+ * <li>{@link #GROUP_OWNER_ACCESS} -- only the owner has permission</li>
+ * <li>{@link #GROUP_GROUP_ACCESS}
+ * -- only members of the group have permission</li>
+ * <li>{@link #GROUP_ANYUSER_ACCESS} -- any user has permission</li></ul>
+ */
+ protected int listGroupsOwned;
+ /**
+ * who is allowed to execute PTS listowned for this group. Valid values are:
+ * <ul>
+ * <li>{@link #GROUP_OWNER_ACCESS} -- only the owner has permission</li>
+ * <li>{@link #GROUP_GROUP_ACCESS}
+ * -- only members of the group have permission</li>
+ * <li>{@link #GROUP_ANYUSER_ACCESS} -- any user has permission</li></ul>
+ */
+ protected int listMembership;
+ /**
+ * who is allowed to execute PTS adduser for this group. Valid values are:
+ * <ul>
+ * <li>{@link #GROUP_OWNER_ACCESS} -- only the owner has permission</li>
+ * <li>{@link #GROUP_GROUP_ACCESS}
+ * -- only members of the group have permission</li>
+ * <li>{@link #GROUP_ANYUSER_ACCESS} -- any user has permission</li></ul>
+ */
+ protected int listAdd;
+ /**
+ * who is allowed to execute PTS removeuser for this group. Valid
+ * values are:
+ * <ul>
+ * <li>{@link #GROUP_OWNER_ACCESS} -- only the owner has permission</li>
+ * <li>{@link #GROUP_GROUP_ACCESS}
+ * -- only members of the group have permission</li>
+ * <li>{@link #GROUP_ANYUSER_ACCESS} -- any user has permission</li></ul>
+ */
+ protected int listDelete;
+
+ protected ArrayList members;
+ protected ArrayList memberNames;
+ protected ArrayList groupsOwned;
+ protected ArrayList groupsOwnedNames;
+
+ /**
+ * Whether or not the information fields of this group have been filled.
+ */
+ protected boolean cachedInfo;
+
+ /**
+ * Constructs a new <code>Group</code> object instance given the name
+ * of the AFS group and the AFS cell, represented by
+ * <CODE>cell</CODE>, to which it belongs. This does not actually
+ * create a new AFS group, it just represents one.
+ * If <code>name</code> is not an actual AFS group, exceptions
+ * will be thrown during subsequent method invocations on this
+ * object, unless the {@link #create(String, int)} or {@link #create(String)}
+ * method is explicitly called to create it.
+ *
+ * @param name the name of the group to represent
+ * @param cell the cell to which the group belongs.
+ * @exception AFSException If an error occurs in the native code
+ */
+ public Group( String name, Cell cell ) throws AFSException
+ {
+ this.name = name;
+ this.cell = cell;
+ cellHandle = cell.getCellHandle();
+
+ members = null;
+ memberNames = null;
+ groupsOwned = null;
+ groupsOwnedNames = null;
+ cachedInfo = false;
+ }
+
+ /**
+ * Constructs a new <code>Group</code> object instance given the name
+ * of the AFS group and the AFS cell, represented by
+ * <CODE>cell</CODE>, to which it belongs. This does not actually
+ * create a new AFS group, it just represents one.
+ * If <code>name</code> is not an actual AFS group, exceptions
+ * will be thrown during subsequent method invocations on this
+ * object, unless the {@link #create(String, int)} or {@link #create(String)}
+ * method is explicitly called to create it. Note that if the process
+ * doesn't exist and <code>preloadAllMembers</code> is true, an exception
+ * will be thrown.
+ *
+ * <P> This constructor is ideal for point-in-time representation and
+ * transient applications. It ensures all data member values are set and
+ * available without calling back to the filesystem at the first request
+ * for them. Use the {@link #refresh()} method to address any coherency
+ * concerns.
+ *
+ * @param name the name of the group to represent
+ * @param cell the cell to which the group belongs.
+ * @param preloadAllMembers true will ensure all object members are
+ * set upon construction;
+ * otherwise members will be set upon access,
+ * which is the default behavior.
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh
+ */
+ public Group( String name, Cell cell, boolean preloadAllMembers )
+ throws AFSException
+ {
+ this(name, cell);
+ if (preloadAllMembers) refresh(true);
+ }
+
+ /**
+ * Creates a blank <code>Group</code> given the cell to which the group
+ * belongs. Other methods cvan then be used to fill the fields of this
+ * blank object.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @param cell the cell to which the group belongs.
+ */
+ Group( Cell cell ) throws AFSException
+ {
+ this( null, cell );
+ }
+
+ /*-------------------------------------------------------------------------*/
+
+ /**
+ * Creates the PTS entry for a new group in this cell. Automatically assigns
+ * a group id.
+ *
+ * @param ownerName the owner of this group
+ */
+ public void create( String ownerName ) throws AFSException
+ {
+ this.create( ownerName, 0 );
+ }
+
+ /**
+ * Creates the PTS entry for a new group in this cell.
+ *
+ * @param ownerName the owner of this group
+ * @param gid the group id to assign to the new group
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void create( String ownerName, int gid ) throws AFSException
+ {
+ Group.create( cell.getCellHandle(), name, ownerName, gid );
+ }
+
+ /**
+ * Deletes the PTS entry for a group in this cell. Deletes this group
+ * from the membership list of the user that belonged to it, but does not
+ * delete the groups owned by this group. Also nullifies the Java object.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void delete() throws AFSException
+ {
+ Group.delete( cell.getCellHandle(), name );
+
+ cell = null;
+ name = null;
+ owner = null;
+ creator = null;
+ members = null;
+ memberNames = null;
+ groupsOwned = null;
+ groupsOwnedNames = null;
+ try {
+ finalize();
+ } catch( Throwable t ) {
+ throw new AFSException( t.getMessage() );
+ }
+ }
+
+ /**
+ * Flushes the current information of this <code>Group</code> object to disk.
+ * This will update the information of the actual AFS group to match the
+ * settings that have been modified in this <code>Group</code> object.
+ * This function must be called before any changes made to the information
+ * fields of this group will be seen by the AFS system.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void flushInfo() throws AFSException
+ {
+ Group.setGroupInfo( cell.getCellHandle(), name, this );
+ }
+
+ /**
+ * Add the specified member to this group.
+ *
+ * @param userName the <code>User</code> object to add
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void addMember( User theUser ) throws AFSException
+ {
+ String userName = theUser.getName();
+
+ Group.addMember( cell.getCellHandle(), name, userName );
+
+ // add to cache
+ if( memberNames != null ) {
+ memberNames.add( userName );
+ }
+ if( members != null ) {
+ members.add( new User( userName, cell ) );
+ }
+ }
+
+ /**
+ * Remove the specified member from this group.
+ * @param userName the <code>User</code> object to remove
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void removeMember( User theUser ) throws AFSException
+ {
+ String userName = theUser.getName();
+ Group.removeMember( cell.getCellHandle(), name, userName );
+
+ // remove from cache
+ if( memberNames != null ) {
+ memberNames.remove( memberNames.indexOf(userName) );
+ memberNames.trimToSize();
+ }
+ if( members != null && members.indexOf(theUser) > -1) {
+ members.remove( members.indexOf(theUser) );
+ members.trimToSize();
+ }
+ }
+
+ /**
+ * Change the owner of this group.
+ *
+ * @param ownerName the new owner <code>User</code> object
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void changeOwner( User theOwner ) throws AFSException
+ {
+ String ownerName = theOwner.getName();
+
+ Group.changeOwner( cell.getCellHandle(), name, ownerName );
+
+ if( cachedInfo ) {
+ owner = ownerName;
+ }
+ }
+
+ /**
+ * Change the owner of this group.
+ *
+ * @param ownerName the new owner <code>Group</code> object
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void changeOwner( Group theOwner ) throws AFSException
+ {
+ String ownerName = theOwner.getName();
+ Group.changeOwner( cell.getCellHandle(), name, ownerName );
+ if( cachedInfo ) {
+ owner = ownerName;
+ }
+ }
+
+ /**
+ * Change the name of this group.
+ *
+ * @param newName the new name for this group
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void rename( String newName ) throws AFSException
+ {
+ Group.rename( cell.getCellHandle(), name, newName );
+ name = newName;
+ }
+
+ /**
+ * Refreshes the properties of this Group object instance with values from
+ * the AFS group it represents. All properties that have been initialized
+ * and/or accessed will be renewed according to the values of the AFS group
+ * this <code>Group</code> object instance represents.
+ *
+ * <P>Since in most environments administrative changes can be administered
+ * from an AFS command-line program or an alternate GUI application, this
+ * method provides a means to refresh the Java object representation and
+ * thereby ascertain any possible modifications that may have been made
+ * from such alternate administrative programs. Using this method before
+ * an associated instance accessor will ensure the highest level of
+ * representative accuracy, accommodating changes made external to the
+ * Java application space. If administrative changes to the underlying AFS
+ * system are only allowed via this API, then the use of this method is
+ * unnecessary.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void refresh() throws AFSException
+ {
+ refresh(false);
+ }
+
+ /**
+ * Refreshes the properties of this Group object instance with values from
+ * the AFS group it represents. If <CODE>all</CODE> is <CODE>true</CODE>
+ * then <U>all</U> of the properties of this Group object instance will be
+ * set, or renewed, according to the values of the AFS group it represents,
+ * disregarding any previously set properties.
+ *
+ * <P> Thus, if <CODE>all</CODE> is <CODE>false</CODE> then properties that
+ * are currently set will be refreshed and properties that are not set will
+ * remain uninitialized. See {@link #refresh()} for more information.
+ *
+ * @param all if true set or renew all object properties; otherwise renew
+ * all set properties
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh()
+ */
+ protected void refresh(boolean all) throws AFSException
+ {
+ if( all || cachedInfo ) {
+ refreshInfo();
+ }
+ if( all || groupsOwned != null ) {
+ refreshGroupsOwned();
+ }
+ if( all || groupsOwnedNames != null ) {
+ refreshGroupsOwnedNames();
+ }
+ if( all || members != null ) {
+ refreshMembers();
+ }
+ if( all || memberNames != null ) {
+ refreshMemberNames();
+ }
+ }
+
+ /**
+ * Refreshes the information fields of this <code>Group</code> to reflect
+ * the current state of the AFS group. Does not refresh the members that
+ * belong to the group, nor the groups the group owns.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshInfo() throws AFSException
+ {
+ cachedInfo = true;
+ Group.getGroupInfo( cell.getCellHandle(), name, this );
+ }
+
+ /**
+ * Refreshes the current information about the <code>User</code> objects
+ * belonging to this group. Does not refresh the information fields of
+ * the group or groups owned.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshMembers() throws AFSException
+ {
+ User currUser;
+
+ int iterationID = Group.getGroupMembersBegin( cell.getCellHandle(), name );
+
+ members = new ArrayList();
+
+ currUser = new User( cell );
+ while( Group.getGroupMembersNext( cellHandle, iterationID, currUser )
+ != 0 ) {
+ members.add( currUser );
+ currUser = new User( cell );
+ }
+
+ Group.getGroupMembersDone( iterationID );
+ }
+
+ /**
+ * Refreshes the current information about the names of members belonging
+ * to this group. Does not refresh the information fields of the group
+ * or groups owned.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshMemberNames() throws AFSException
+ {
+ String currName;
+ int iterationID = Group.getGroupMembersBegin( cell.getCellHandle(), name );
+
+ memberNames = new ArrayList();
+
+ while( ( currName = Group.getGroupMembersNextString( iterationID ) )
+ != null ) {
+ memberNames.add( currName );
+ }
+ Group.getGroupMembersDone( iterationID );
+ }
+
+ /**
+ * Refreshes the current information about the <code>Group</code> objects the
+ * group owns. Does not refresh the information fields of the group or
+ * members.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshGroupsOwned() throws AFSException
+ {
+ Group currGroup;
+
+ int iterationID = User.getGroupsOwnedBegin( cell.getCellHandle(), name );
+
+ groupsOwned = new ArrayList();
+
+ currGroup = new Group( cell );
+ while( User.getGroupsOwnedNext( cellHandle, iterationID, currGroup )
+ != 0 ) {
+ groupsOwned.add( currGroup );
+ currGroup = new Group( cell );
+ }
+
+ User.getGroupsOwnedDone( iterationID );
+ }
+
+ /**
+ * Refreshes the current information about the names of groups the group
+ * owns. Does not refresh the information fields of the group or members.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshGroupsOwnedNames() throws AFSException
+ {
+ String currName;
+
+ int iterationID = User.getGroupsOwnedBegin( cell.getCellHandle(), name );
+
+ groupsOwnedNames = new ArrayList();
+ while( ( currName = User.getGroupsOwnedNextString( iterationID ) )
+ != null ) {
+ groupsOwnedNames.add( currName );
+ }
+ User.getGroupsOwnedDone( iterationID );
+ }
+
+ /**
+ * Adds an access control list entry for some AFS directory for this group.
+ *
+ * @param directory the full path of the place in the AFS file system
+ * for which to add an entry
+ * @param read whether or not to allow read access to this user
+ * @param write whether or not to allow write access to this user
+ * @param lookup whether or not to allow lookup access to this user
+ * @param delete whether or not to allow deletion access to this user
+ * @param insert whether or not to allow insertion access to this user
+ * @param lock whether or not to allow lock access to this user
+ * @param admin whether or not to allow admin access to this user
+ * @exception AFSException If an error occurs in the native code
+ public void setACL( String directory, boolean read, boolean write, boolean lookup, boolean delete, boolean insert, boolean lock, boolean admin )
+ throws AFSException
+ {
+ Cell.setACL( directory, name, read, write, lookup, delete, insert, lock, admin );
+ }
+ */
+
+ ////////////////////// accessors: ///////////////
+
+ /**
+ * Returns the name of this group.
+ *
+ * @return the name of this group
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns the numeric AFS id of this group.
+ *
+ * @return the AFS id of this group
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getUID() throws AFSException
+ {
+ if( !cachedInfo ) {
+ refreshInfo();
+ }
+ return nameUID;
+ }
+
+ /**
+ * Returns the Cell this group belongs to.
+ *
+ * @return the Cell this group belongs to
+ */
+ public Cell getCell()
+ {
+ return cell;
+ }
+
+ /**
+ * Returns an array of the <code>User</code> object members of this group.
+ *
+ * @return an array of the members of this group
+ * @exception AFSException If an error occurs in the native code
+ */
+ public User[] getMembers() throws AFSException
+ {
+ if( members == null ) {
+ refreshMembers();
+ }
+ return (User[]) members.toArray( new User[members.size()] );
+ }
+
+ /**
+ * Returns an array of the member names of this group.
+ *
+ * @return an array of the member names of this group
+ * @exception AFSException If an error occurs in the native code
+ */
+ public String[] getMemberNames() throws AFSException
+ {
+ if( memberNames == null ) {
+ refreshMemberNames();
+ }
+ return (String[]) memberNames.toArray( new String[memberNames.size()] );
+ }
+
+ /**
+ * Returns an array of the <code>Group</code> objects this group owns.
+ *
+ * @return an array of the <code>Groups</code> this group owns
+ * @exception AFSException If an error occurs in the native code
+ */
+ public Group[] getGroupsOwned() throws AFSException
+ {
+ if( groupsOwned == null ) {
+ refreshGroupsOwned();
+ }
+ return (Group[]) groupsOwned.toArray( new Group[groupsOwned.size()] );
+ }
+
+ /**
+ * Returns an array of the group names this group owns.
+ * Contains <code>String</code> objects.
+ *
+ * @return an array of the group names this group owns
+ * @exception AFSException If an error occurs in the native code
+ */
+ public String[] getGroupsOwnedNames() throws AFSException
+ {
+ if( groupsOwnedNames == null ) {
+ refreshGroupsOwnedNames();
+ }
+ return (String[])
+ groupsOwnedNames.toArray(new String[groupsOwnedNames.size()] );
+ }
+
+ /**
+ * Returns the number of members of this group.
+ *
+ * @return the membership count
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getMembershipCount() throws AFSException
+ {
+ if( !cachedInfo ) {
+ refreshInfo();
+ }
+ return membershipCount;
+ }
+
+ /**
+ * PTS: Returns the owner of this group in the form of a {@link PTSEntry}.
+ *
+ * <P>The returning object could be either a {@link User} or {@link Group};
+ * to determine what type of object the {@link PTSEntry} represents,
+ * call the {@link PTSEntry#getType()} method.
+ *
+ * @return the owner of this group
+ * @exception AFSException If an error occurs in the native code
+ * @see PTSEntry
+ * @see PTSEntry#getType()
+ * @see #refresh()
+ */
+ public PTSEntry getOwner() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ if (owner == null) return null;
+ if (ownerUID > 0) {
+ return new User(owner, cell);
+ } else {
+ return new Group(owner, cell);
+ }
+ }
+
+ /**
+ * PTS: Returns the creator of this group in the form of a {@link PTSEntry}.
+ *
+ * <P>The returning object could be either a {@link User} or {@link Group};
+ * to determine what type of object the {@link PTSEntry} represents,
+ * call the {@link PTSEntry#getType()} method.
+ *
+ * @return the creator of this group
+ * @exception AFSException If an error occurs in the native code
+ * @see PTSEntry
+ * @see PTSEntry#getType()
+ * @see #refresh()
+ */
+ public PTSEntry getCreator() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ if (creator == null) return null;
+ if (creatorUID > 0) {
+ return new User(creator, cell);
+ } else {
+ return new Group(creator, cell);
+ }
+ }
+
+ /**
+ * Returns the type of {@link PTSEntry} this object represents.
+ *
+ * <P>This method will always return {@link PTSEntry#PTS_GROUP}.
+ *
+ * @return the type of PTSEntry this object represents
+ (will always return {@link PTSEntry#PTS_GROUP})
+ * @see PTSEntry
+ * @see PTSEntry#getType()
+ */
+ public short getType()
+ {
+ return PTSEntry.PTS_GROUP;
+ }
+
+ /**
+ * Returns who can list the status (pts examine) of this group.
+ * Valid values are:
+ * <ul>
+ * <li><code>{@link #GROUP_OWNER_ACCESS}</code>
+ * -- only the owner has permission</li>
+ * <li><code>{@link #GROUP_GROUP_ACCESS}</code>
+ * -- only members of the group have permission</li>
+ * <li><code>{@link #GROUP_ANYUSER_ACCESS}</code>
+ * -- any user has permission</li>
+ * </ul>
+ *
+ * @return the status listing permission
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getListStatus() throws AFSException
+ {
+ if( !cachedInfo ) refreshInfo();
+ return listStatus;
+ }
+
+ /**
+ * Returns who can list the groups owned (pts listowned) by this group.
+ * Valid values are:
+ * <ul>
+ * <li><code>{@link #GROUP_OWNER_ACCESS}</code>
+ * -- only the owner has permission</li>
+ * <li><code>{@link #GROUP_GROUP_ACCESS}</code>
+ * -- only members of the group have permission</li>
+ * <li><code>{@link #GROUP_ANYUSER_ACCESS}</code>
+ * -- any user has permission</li>
+ * </ul>
+ *
+ * @return the groups owned listing permission
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getListGroupsOwned() throws AFSException
+ {
+ if( !cachedInfo ) refreshInfo();
+ return listGroupsOwned;
+ }
+
+ /**
+ * Returns who can list the users (pts membership) that belong to this group.
+ * Valid values are:
+ * <ul>
+ * <li><code>{@link #GROUP_OWNER_ACCESS}</code>
+ * -- only the owner has permission</li>
+ * <li><code>{@link #GROUP_GROUP_ACCESS}</code>
+ * -- only members of the group have permission</li>
+ * <li><code>{@link #GROUP_ANYUSER_ACCESS}</code>
+ * -- any user has permission</li>
+ * </ul>
+ *
+ * @return the membership listing permission
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getListMembership() throws AFSException
+ {
+ if( !cachedInfo ) refreshInfo();
+ return listMembership;
+ }
+
+ /**
+ * Returns who can add members (pts adduser) to this group.
+ * Valid values are:
+ * <ul>
+ * <li><code>{@link #GROUP_OWNER_ACCESS}</code>
+ * -- only the owner has permission</li>
+ * <li><code>{@link #GROUP_GROUP_ACCESS}</code>
+ * -- only members of the group have permission</li>
+ * <li><code>{@link #GROUP_ANYUSER_ACCESS}</code>
+ * -- any user has permission</li>
+ * </ul>
+ *
+ * @return the member adding permission
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getListAdd() throws AFSException
+ {
+ if( !cachedInfo ) refreshInfo();
+ return listAdd;
+ }
+
+ /**
+ * Returns who can delete members (pts removemember) from this group.
+ * Valid values are:
+ * <ul>
+ * <li><code>{@link #GROUP_OWNER_ACCESS}</code>
+ * -- only the owner has permission</li>
+ * <li><code>{@link #GROUP_GROUP_ACCESS}</code>
+ * -- only members of the group have permission</li>
+ * <li><code>{@link #GROUP_ANYUSER_ACCESS}</code>
+ * -- any user has permission</li>
+ * </ul>
+ *
+ * @return the member deleting permission
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getListDelete() throws AFSException
+ {
+ if( !cachedInfo ) refreshInfo();
+ return listDelete;
+ }
+
+ /////////////////// mutators: //////////////////////
+
+ /**
+ * Sets who can list the status (pts examine) of this group.
+ * Valid values are:
+ * <ul>
+ * <li><code>{@link #GROUP_OWNER_ACCESS}</code>
+ * -- only the owner has permission</li>
+ * <li><code>{@link #GROUP_GROUP_ACCESS}</code>
+ * -- only members of the group have permission</li>
+ * <li><code>{@link #GROUP_ANYUSER_ACCESS}</code>
+ * -- any user has permission</li>
+ * </ul>
+ *
+ * @param value the value of the new list membership permission
+ * @exception AFSException if an error occurs in the native code
+ * @exception IllegalArgumentException if an invalud argument is provided
+ */
+ public void setListStatus( int value ) throws AFSException
+ {
+ if( (value != Group.GROUP_OWNER_ACCESS) &&
+ (value != Group.GROUP_GROUP_ACCESS) &&
+ (value != Group.GROUP_ANYUSER_ACCESS) ) {
+ throw new IllegalArgumentException( "Cannot set listStatus to "
+ + value );
+ } else {
+ listStatus = value;
+ }
+ }
+
+ /**
+ * Sets who can list the groups owned (pts listowned) by this group.
+ * Valid values are:
+ * <ul>
+ * <li><code>{@link #GROUP_OWNER_ACCESS}</code>
+ * -- only the owner has permission</li>
+ * <li><code>{@link #GROUP_GROUP_ACCESS}</code>
+ * -- only members of the group have permission</li>
+ * <li><code>{@link #GROUP_ANYUSER_ACCESS}</code>
+ * -- any user has permission</li>
+ * </ul>
+ *
+ * @param value the value of the new list membership permission
+ * @exception AFSException if an error occurs in the native code
+ * @exception IllegalArgumentException if an invalud argument is provided
+ */
+ public void setListGroupsOwned( int value ) throws AFSException
+ {
+ if( (value != Group.GROUP_OWNER_ACCESS) &&
+ (value != Group.GROUP_GROUP_ACCESS) &&
+ (value != Group.GROUP_ANYUSER_ACCESS) ) {
+ throw new IllegalArgumentException( "Cannot set listGroupsOwned to "
+ + value );
+ } else {
+ listGroupsOwned = value;
+ }
+ }
+
+ /**
+ * Sets who can list the users (pts membership) that belong to this group.
+ * Valid values are:
+ * <ul>
+ * <li><code>{@link #GROUP_OWNER_ACCESS}</code>
+ * -- only the owner has permission</li>
+ * <li><code>{@link #GROUP_GROUP_ACCESS}</code>
+ * -- only members of the group have permission</li>
+ * <li><code>{@link #GROUP_ANYUSER_ACCESS}</code>
+ * -- any user has permission</li>
+ * </ul>
+ *
+ * @param value the value of the new list membership permission
+ * @exception AFSException if an error occurs in the native code
+ * @exception IllegalArgumentException if an invalud argument is provided
+ */
+ public void setListMembership( int value ) throws AFSException
+ {
+ if( (value != Group.GROUP_OWNER_ACCESS) &&
+ (value != Group.GROUP_GROUP_ACCESS) &&
+ (value != Group.GROUP_ANYUSER_ACCESS) ) {
+ throw new IllegalArgumentException( "Cannot set listMembership to "
+ + value );
+ } else {
+ listMembership = value;
+ }
+ }
+
+ /**
+ * Sets who can add members (pts adduser) to this group.
+ * Valid values are:
+ * <ul>
+ * <li><code>{@link #GROUP_OWNER_ACCESS}</code>
+ * -- only the owner has permission</li>
+ * <li><code>{@link #GROUP_GROUP_ACCESS}</code>
+ * -- only members of the group have permission</li>
+ * <li><code>{@link #GROUP_ANYUSER_ACCESS}</code>
+ * -- any user has permission</li>
+ * </ul>
+ *
+ * @param value the value of the new list membership permission
+ * @exception AFSException if an invalid value is provided
+ */
+ public void setListAdd( int value ) throws AFSException
+ {
+ if( (value != Group.GROUP_OWNER_ACCESS) &&
+ (value != Group.GROUP_GROUP_ACCESS) &&
+ (value != Group.GROUP_ANYUSER_ACCESS) ) {
+ throw new IllegalArgumentException( "Cannot set listAdd to " + value );
+ } else {
+ listAdd = value;
+ }
+ }
+
+ /**
+ * Sets who can delete members (pts removemember) from this group.
+ * Valid values are:
+ * <ul>
+ * <li><code>{@link #GROUP_OWNER_ACCESS}</code>
+ * -- only the owner has permission</li>
+ * <li><code>{@link #GROUP_GROUP_ACCESS}</code>
+ * -- only members of the group have permission</li>
+ * <li><code>{@link #GROUP_ANYUSER_ACCESS}</code>
+ * -- any user has permission</li>
+ * </ul>
+ *
+ * @param value the value of the new list membership permission
+ * @exception AFSException if an invalid value is provided
+ */
+ public void setListDelete( int value ) throws AFSException
+ {
+ if( (value != Group.GROUP_OWNER_ACCESS) &&
+ (value != Group.GROUP_GROUP_ACCESS) &&
+ (value != Group.GROUP_ANYUSER_ACCESS) ) {
+ throw new IllegalArgumentException( "Cannot set listDelete to "
+ + value );
+ } else {
+ listDelete = value;
+ }
+ }
+
+ /////////////// information methods ////////////////////
+
+ /**
+ * Returns a <code>String</code> representation of this <code>Group</code>.
+ * Contains the information fields and members.
+ *
+ * @return a <code>String</code> representation of the <code>Group</code>
+ */
+ protected String getInfo()
+ {
+ String r;
+ try {
+ r = "Group: " + getName() + ", uid: " + getUID() + "\n";
+ r += "\towner: " + getOwner().getName() + ", uid: " + getOwner().getUID() + "\n";
+ r += "\tcreator: " + getCreator().getName() + ", uid: "
+ + getCreator().getUID() + "\n";
+ r += "\tMembership count: " + getMembershipCount() + "\n";
+ r += "\tList status: " + getListStatus() + "\n";
+ r += "\tList groups owned: " + getListGroupsOwned() + "\n";
+ r += "\tList membership: " + getListMembership() + "\n";
+ r += "\tAdd members: " + getListAdd() + "\n";
+ r += "\tDelete members: " + getListDelete() + "\n";
+
+ r += "\tGroup members: \n";
+ String names[] = getMemberNames();
+ for( int i = 0; i < names.length; i++ ) {
+ r += "\t\t" + names[i] + "\n";
+ }
+
+ r += "\tOwns groups: \n";
+ names = getGroupsOwnedNames();
+ for( int i = 0; i < names.length; i++ ) {
+ r += "\t\t" + names[i] + "\n";
+ }
+ return r;
+ } catch ( AFSException e ) {
+ return e.toString();
+ }
+ }
+
+ /////////////// custom override methods ////////////////////
+
+ /**
+ * Compares two Group objects respective to their names and does not
+ * factor any other attribute. Alphabetic case is significant in
+ * comparing names.
+ *
+ * @param group The Group object to be compared to this Group instance
+ *
+ * @return Zero if the argument is equal to this Group's name, a
+ * value less than zero if this Group's name is
+ * lexicographically less than the argument, or a value greater
+ * than zero if this Group's name is lexicographically
+ * greater than the argument
+ */
+ public int compareTo(Group group)
+ {
+ return this.getName().compareTo(group.getName());
+ }
+
+ /**
+ * Comparable interface method.
+ *
+ * @see #compareTo(Group)
+ */
+ public int compareTo(Object obj)
+ {
+ return compareTo((Group)obj);
+ }
+
+ /**
+ * Tests whether two <code>Group</code> objects are equal, based on their
+ * names.
+ *
+ * @param otherGroup the Group to test
+ * @return whether the specifed Group is the same as this Group
+ */
+ public boolean equals( Group otherGroup )
+ {
+ return name.equals( otherGroup.getName() );
+ }
+
+ /**
+ * Returns the name of this <CODE>Group</CODE>
+ *
+ * @return the name of this <CODE>Group</CODE>
+ */
+ public String toString()
+ {
+ return getName();
+ }
+
+ /////////////// native methods ////////////////////
+
+ /**
+ * Creates the PTS entry for a new group. Pass in 0 for the uid if PTS is to
+ * automatically assign the group id.
+ *
+ * @param cellHandle the handle of the cell to which the group belongs
+ * @see Cell#getCellHandle
+ * @param groupName the name of the group to create
+ * @param ownerName the owner of this group
+ * @param gid the group id to assign to the group (0 to have one
+ * automatically assigned)
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void create( int cellHandle, String groupName,
+ String ownerName, int gid )
+ throws AFSException;
+
+ /**
+ * Deletes the PTS entry for a group. Deletes this group from the
+ * membership list of the users that belonged to it, but does not delete
+ * the groups owned by this group.
+ *
+ * @param cellHandle the handle of the cell to which the group belongs
+ * @see Cell#getCellHandle
+ * @param groupName the name of the group to delete
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void delete( int cellHandle, String groupName )
+ throws AFSException;
+
+ /**
+ * Fills in the information fields of the provided <code>Group</code>.
+ * Fills in values based on the current PTS information of the group.
+ *
+ * @param cellHandle the handle of the cell to which the group belongs
+ * @see Cell#getCellHandle
+ * @param name the name of the group for which to get the information
+ * @param group the <code>Group</code> object in which to fill in the
+ * information
+ * @see Group
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void getGroupInfo( int cellHandle, String name,
+ Group group )
+ throws AFSException;
+
+ /**
+ * Sets the information values of this AFS group to be the parameter values.
+ *
+ * @param cellHandle the handle of the cell to which the user belongs
+ * @see Cell#getCellHandle
+ * @param name the name of the user for which to set the information
+ * @param theGroup the group object containing the desired information
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void setGroupInfo( int cellHandle, String name,
+ Group theGroup )
+ throws AFSException;
+
+ /**
+ * Begin the process of getting the users that belong to the group. Returns
+ * an iteration ID to be used by subsequent calls to
+ * <code>getGroupMembersNext</code> and <code>getGroupMembersDone</code>.
+ *
+ * @param cellHandle the handle of the cell to which the group belongs
+ * @see Cell#getCellHandle
+ * @param name the name of the group for which to get the members
+ * @return an iteration ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getGroupMembersBegin( int cellHandle,
+ String name )
+ throws AFSException;
+
+ /**
+ * Returns the next members that belongs to the group. Returns
+ * <code>null</code> if there are no more members.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see getGroupMembersBegin
+ * @return the name of the next member
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native String getGroupMembersNextString( int iterationId )
+ throws AFSException;
+
+ /**
+ * Fills the next user object belonging to that group. Returns 0 if there
+ * are no more users, != 0 otherwise.
+ *
+ * @param cellHandle the handle of the cell to which the users belong
+ * @see Cell#getCellHandle
+ * @param iterationId the iteration ID of this iteration
+ * @see getGroupMembersBegin
+ * @param theUser a User object to be populated with the values of the
+ * next user
+ * @return 0 if there are no more users, != 0 otherwise
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getGroupMembersNext( int cellHandle,
+ int iterationId,
+ User theUser )
+ throws AFSException;
+
+ /**
+ * Signals that the iteration is complete and will not be accessed anymore.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see getGroupMembersBegin
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void getGroupMembersDone( int iterationId )
+ throws AFSException;
+
+ /**
+ * Adds a user to the specified group.
+ *
+ * @param cellHandle the handle of the cell to which the group belongs
+ * @see Cell#getCellHandle
+ * @param groupName the name of the group to which to add a member
+ * @param userName the name of the user to add
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void addMember( int cellHandle, String groupName,
+ String userName )
+ throws AFSException;
+
+ /**
+ * Removes a user from the specified group.
+ *
+ * @param cellHandle the handle of the cell to which the group belongs
+ * @see Cell#getCellHandle
+ * @param groupName the name of the group from which to remove a
+ * member
+ * @param userName the name of the user to remove
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void removeMember( int cellHandle, String groupName,
+ String userName )
+ throws AFSException;
+
+ /**
+ * Change the owner of the specified group.
+ *
+ * @param cellHandle the handle of the cell to which the group belongs
+ * @see Cell#getCellHandle
+ * @param groupName the name of the group of which to change the
+ * owner
+ * @param ownerName the name of the new owner
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void changeOwner( int cellHandle, String groupName,
+ String ownerName )
+ throws AFSException;
+
+ /**
+ * Change the name of the specified group.
+ *
+ * @param cellHandle the handle of the cell to which the group belongs
+ * @see Cell#getCellHandle
+ * @param oldGroupName the old name of the group
+ * @param newGroupName the new name for the group
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void rename( int cellHandle, String oldGroupName,
+ String newGroupName )
+ throws AFSException;
+
+ /**
+ * Reclaims all memory being saved by the group portion of the native
+ * library.
+ * This method should be called when no more <code>Groups</code> are expected
+ * to be used.
+ */
+ protected static native void reclaimGroupMemory();
+}
+
+
+
+
+
--- /dev/null
+/*
+ * @(#)Key.java 1.0 6/29/2001
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.util.GregorianCalendar;
+import java.util.Date;
+import java.io.Serializable;
+
+/**
+ * An abstract representation of an AFS key. It holds information about
+ * the key, such as what its version is.
+ * <BR><BR>
+ *
+ * Constructing an instance of a <code>Key</code> does not mean an actual
+ * AFS key is created on a server -- usually a <code>Key</code>
+ * object is a representation of an already existing AFS key. If,
+ * however, the <code>Key</code> is constructed with the version number of a
+ * key that does not exist on the server represented by the provided
+ * <code>Server</code>, a new key with that version number can be
+ * created on that server by calling the {@link #create(String)} methods If
+ * such a key does already exist when this method is called,
+ * an exception will be thrown.<BR><BR>
+ *
+ * <!--Example of how to use class-->
+ * The following is a simple example of how to construct and use a
+ * <code>Key</code> object. It obtains the list of <code>Key</code>s from
+ * a specified server, and prints the string representation of each key.
+ * <PRE>
+ * import org.openafs.jafs.Cell;
+ * import org.openafs.jafs.AFSException;
+ * import org.openafs.jafs.Key;
+ * import org.openafs.jafs.Server;
+ * ...
+ * public class ...
+ * {
+ * ...
+ * private Cell cell;
+ * private Server server;
+ * ...
+ * public static void main(String[] args) throws Exception
+ * {
+ * String username = arg[0];
+ * String password = arg[1];
+ * String cellName = arg[2];
+ * String serverName = arg[3];
+ *
+ * token = new Token(username, password, cellName);
+ * cell = new Cell(token);
+ * server = new Server(serverName, cell);
+ *
+ * System.out.println("Keys in Server " + server.getName() + ":");
+ * Key[] keys = server.getKeys();
+ * for (int i = 0; i < keys.length; i++) {
+ * System.out.println(" -> " + keys[i] );
+ * }
+ * }
+ * ...
+ * }
+ * </PRE>
+ *
+ */
+public class Key implements Serializable, Comparable
+{
+ protected Server server;
+
+ protected int version;
+ protected long checkSum;
+ protected String encryptionKey;
+ protected int lastModDate;
+ protected int lastModMs;
+
+ protected GregorianCalendar lastModDateDate;
+
+ protected boolean cachedInfo;
+
+ /**
+ * Constructs a new <CODE>Key</CODE> object instance given the version of
+ * the AFS key and the AFS server, represented by <CODE>server</CODE>,
+ * to which it belongs. This does not actually
+ * create a new AFS key, it just represents one.
+ * If <code>version</code> is not an actual AFS key, exceptions
+ * will be thrown during subsequent method invocations on this
+ * object, unless the {@link #create(String)}
+ * method is explicitly called to create it.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @param version the version of the key to represent
+ * @param server the server to which the key belongs.
+ */
+ public Key( int version, Server server ) throws AFSException
+ {
+ this.server = server;
+ this.version = version;
+
+ lastModDateDate = null;
+
+ cachedInfo = false;
+ }
+
+ /**
+ * Constructs a new <CODE>Key</CODE> object instance given the version of
+ * the AFS key and the AFS server, represented by <CODE>server</CODE>,
+ * to which it belongs. This does not actually
+ * create a new AFS key, it just represents one.
+ * If <code>version</code> is not an actual AFS key, exceptions
+ * will be thrown during subsequent method invocations on this
+ * object, unless the {@link #create(String)}
+ * method is explicitly called to create it. Note that if the key does not
+ * exist and <code>preloadAllMembers</code> is true, an exception will
+ * be thrown.
+ *
+ * <P> This constructor is ideal for point-in-time representation and
+ * transient applications. It ensures all data member values are set and
+ * available without calling back to the filesystem at the first request
+ * for them. Use the {@link #refresh()} method to address any coherency
+ * concerns.
+ *
+ * @param version the version of the key to represent
+ * @param server the server to which the key belongs.
+ * @param preloadAllMembers true will ensure all object members are set
+ * upon construction; otherwise members will be
+ * set upon access, which is the default behavior.
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh
+ */
+ public Key( int version, Server server, boolean preloadAllMembers )
+ throws AFSException
+ {
+ this(version, server);
+ if (preloadAllMembers) refresh(true);
+ }
+
+ /**
+ * Creates a blank <code>Key</code> given the server to which the key
+ * belongs. This blank object can then be passed into other methods to
+ * fill out its properties.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @param server the server to which the key belongs.
+ */
+ Key( Server server ) throws AFSException
+ {
+ this( -1, server );
+ }
+
+ /*-------------------------------------------------------------------------*/
+
+ /**
+ * Refreshes the properties of this Key object instance with values from
+ * the AFS key it represents. All properties that have been initialized
+ * and/or accessed will be renewed according to the values of the AFS key
+ * this Key object instance represents.
+ *
+ * <P>Since in most environments administrative changes can be administered
+ * from an AFS command-line program or an alternate GUI application, this
+ * method provides a means to refresh the Java object representation and
+ * thereby ascertain any possible modifications that may have been made
+ * from such alternate administrative programs. Using this method before
+ * an associated instance accessor will ensure the highest level of
+ * representative accuracy, accommodating changes made external to the
+ * Java application space. If administrative changes to the underlying AFS
+ * system are only allowed via this API, then the use of this method is
+ * unnecessary.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void refresh() throws AFSException
+ {
+ refresh(false);
+ }
+
+ /**
+ * Refreshes the properties of this Key object instance with values from
+ * the AFS key it represents. If <CODE>all</CODE> is <CODE>true</CODE>
+ * then <U>all</U> of the properties of this Key object instance will be
+ * set, or renewed, according to the values of the AFS key it represents,
+ * disregarding any previously set properties.
+ *
+ * <P> Thus, if <CODE>all</CODE> is <CODE>false</CODE> then properties that
+ * are currently set will be refreshed and properties that are not set will
+ * remain uninitialized. See {@link #refresh()} for more information.
+ *
+ * @param all if true set or renew all object properties; otherwise renew
+ * all set properties
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh()
+ */
+ protected void refresh(boolean all) throws AFSException
+ {
+ if( all || cachedInfo ) {
+ refreshInfo();
+ }
+ }
+
+ /**
+ * Refreshes the information fields of this <code>Key</code> to reflect the
+ * current state of the AFS server key. These inlclude the last
+ * modification time, etc.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshInfo() throws AFSException
+ {
+ getKeyInfo( server.getBosHandle(), version, this );
+ cachedInfo = true;
+ lastModDateDate = null;
+ }
+
+ /**
+ * Creates a key with this <code>Key's</code> version number at the server,
+ * using the specified <code>String</code> for the key.
+ *
+ * @param keyString the string to use for the encryption key
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void create( String keyString ) throws AFSException
+ {
+ create( server.getCell().getCellHandle(), server.getBosHandle(), version,
+ keyString );
+ }
+
+ /**
+ * Removes the key with this <code>Key's</code> version number from
+ * the server.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void delete( ) throws AFSException
+ {
+ delete( server.getBosHandle(), version );
+
+ encryptionKey = null;
+ cachedInfo = false;
+ }
+
+ //////////////// accessors: ////////////////////////
+
+ /**
+ * Returns the version of this key in primitive form.
+ *
+ * @return the version number of this key
+ */
+ public int getVersion()
+ {
+ return version;
+ }
+
+ /**
+ * Returns the server this key is associated with.
+ *
+ * @return this key's server
+ */
+ public Server getServer()
+ {
+ return server;
+ }
+
+ /**
+ * Returns the encrypted key as a string in octal form. This is how AFS
+ * prints it out on the command line. An example would be:
+ * '\040\205\211\241\345\002\023\211'.
+ *
+ * @return the encrypted key
+ * @exception AFSException If an error occurs in the native code
+ */
+ public String getEncryptionKey() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return encryptionKey;
+ }
+
+ /**
+ * Returns the check sum of this key.
+ *
+ * @return the check sum of this key
+ * @exception AFSException If an error occurs in the native code
+ */
+ public long getCheckSum() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return checkSum;
+ }
+
+ /**
+ * Returns the last modification date of this key.
+ *
+ * @return the last modification date of this key
+ * @exception AFSException If an error occurs in the native code
+ */
+ public GregorianCalendar getLastModDate() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ if ( lastModDateDate == null && cachedInfo ) {
+ // make it into a date . . .
+ lastModDateDate = new GregorianCalendar();
+ long longTime = ((long) lastModDate)*1000;
+ Date d = new Date( longTime );
+ lastModDateDate.setTime( d );
+ }
+ return lastModDateDate;
+ }
+
+ /////////////// information methods ////////////////////
+
+ /**
+ * Returns a <code>String</code> representation of this <code>Key</code>.
+ * Contains the information fields.
+ *
+ * @return a <code>String</code> representation of the <code>Key</code>
+ */
+ protected String getInfo()
+ {
+ String r;
+ try {
+ r = "Key version number: " + getVersion() + "\n";
+ r += "\tencrypted key: " + getEncryptionKey() + "\n";
+ r += "\tcheck sum: " + getCheckSum() + "\n";
+ r += "\tlast mod time: " + getLastModDate().getTime() + "\n";
+ } catch( Exception e ) {
+ return e.toString();
+ }
+ return r;
+ }
+
+ /////////////// override methods ////////////////////
+
+ /**
+ * Compares two Key objects respective to their key version and does not
+ * factor any other attribute.
+ *
+ * @param key The Key object to be compared to this Key instance
+ *
+ * @return Zero if the argument is equal to this Key's version, a
+ * value less than zero if this Key's version is less than
+ * the argument, or a value greater than zero if this Key's
+ * version is greater than the argument
+ */
+ public int compareTo(Key key)
+ {
+ return (this.getVersion() - key.getVersion());
+ }
+
+ /**
+ * Comparable interface method.
+ *
+ * @see #compareTo(Key)
+ */
+ public int compareTo(Object obj)
+ {
+ return compareTo((Key)obj);
+ }
+
+ /**
+ * Tests whether two <code>Key</code> objects are equal, based on their
+ * encryption key, version, and associated Server.
+ *
+ * @param otherKey the Key to test
+ * @return whether the specifed Key is the same as this Key
+ */
+ public boolean equals( Key otherKey )
+ {
+ try {
+ return ( this.getEncryptionKey().equals(otherKey.getEncryptionKey()) ) &&
+ ( this.getVersion() == otherKey.getVersion() ) &&
+ ( this.getServer().equals(otherKey.getServer()) );
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the name of this <CODE>Key</CODE>
+ *
+ * @return the name of this <CODE>Key</CODE>
+ */
+ public String toString()
+ {
+ try {
+ return getVersion() + " - " + getEncryptionKey() + " - " + getCheckSum();
+ } catch (Exception e) {
+ return e.toString();
+ }
+ }
+
+ /////////////// native methods ////////////////////
+
+ /**
+ * Fills in the information fields of the provided <code>Key</code>.
+ *
+ * @param serverHandle the bos handle of the server to which the key
+ * belongs
+ * @see Server#getBosServerHandle
+ * @param version the version of the key for which to get the information
+ * @param key the <code>Key</code> object in which to fill in the
+ * information
+ * @see Server
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void getKeyInfo( int serverHandle, int version,
+ Key key )
+ throws AFSException;
+
+ /**
+ * Create a server key.
+ *
+ * @param cellHandle the handle of the cell to which the server belongs
+ * @see Cell#getCellHandle
+ * @param serverHandle the bos handle of the server to which the key will
+ * belong
+ * @see Server#getBosServerHandle
+ * @param versionNumber the version number of the key to create (0 to 255)
+ * @param keyString the <code>String</code> version of the key that will
+ * be encrypted
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void create( int cellHandle, int serverHandle, int versionNumber, String keyString )
+ throws AFSException;
+
+ /**
+ * Delete a server key.
+ *
+ * @param serverHandle the bos handle of the server to which the key belongs
+ * @see Server#getBosServerHandle
+ * @param versionNumber the version number of the key to remove (0 to 255)
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void delete( int serverHandle, int versionNumber )
+ throws AFSException;
+
+ /**
+ * Reclaims all memory being saved by the key portion of the native library.
+ * This method should be called when no more <code>Key</code> objects are
+ * expected to be
+ * used.
+ */
+ protected static native void reclaimKeyMemory();
+
+}
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * @(#)PTSEntry.java 1.2 10/23/2001
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+/**
+ * An interface representation of a PTS entry as it applies to
+ * AFS users and groups. This interface is implemented in both
+ * {@link User} and {@link Group} object abstractions.
+ * <BR><BR>
+ *
+ *
+ * @version 1.0, 3/31/02
+ * @see User
+ * @see Group
+ */
+public interface PTSEntry
+{
+ /**
+ * Constant for {@link User} object implementers,
+ * used with {@link #getType()}
+ */
+ public static final short PTS_USER = 0;
+ /**
+ * Constant for {@link Group} object implementers,
+ * used with {@link #getType()}
+ */
+ public static final short PTS_GROUP = 1;
+ /**
+ * Returns the Cell this PTS user or group belongs to.
+ *
+ * @return the Cell this PTS user or group belongs to
+ */
+ public Cell getCell();
+ /**
+ * Returns the creator of this PTS user or group.
+ *
+ * @return the creator of this PTS user or group
+ * @exception AFSException If an error occurs in the native code
+ */
+ public PTSEntry getCreator() throws AFSException;
+ /**
+ * Returns the name of this PTS user or group.
+ *
+ * @return the name of this PTS user or group
+ */
+ public String getName();
+ /**
+ * Returns the owner of this PTS user or group.
+ *
+ * @return the owner of this PTS user or group
+ * @exception AFSException If an error occurs in the native code
+ */
+ public PTSEntry getOwner() throws AFSException;
+ /**
+ * Returns the type of PTS entry the implementing object represents.
+ *
+ * <P>Possible values are:<BR>
+ * <ul>
+ * <li><code>{@link #PTS_USER}</code>
+ * -- a {@link User} object</li>
+ * <li><code>{@link #PTS_GROUP}</code>
+ * -- a {@link Group} object</li>
+ * </ul>
+ *
+ * @return the name of this PTS user or group
+ */
+ public short getType();
+ /**
+ * Returns the numeric AFS id of this user or group.
+ *
+ * @return the AFS id of this user/group
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getUID() throws AFSException;
+}
+
+
+
--- /dev/null
+/*
+ * @(#)Partition.java 1.0 6/29/2001
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+/**
+ * An abstract representation of an AFS partition. It holds information about
+ * the partition, such as what its total space is.
+ * <BR><BR>
+ *
+ * Constructing an instance of a <code>Partition</code> does not mean
+ * an actual AFS partition is created on a server -- on the contrary,
+ * a <code>Partition</code> object must be a representation of an already
+ * existing AFS partition. There is no way to create a new AFS partition
+ * through this API.<BR><BR>
+ *
+ * Each <code>Partition</code> object has its own individual set of
+ * <code>Volume</code>s. This represents the properties and attributes
+ * of an actual AFS cell.<BR><BR>
+ *
+ * <!--Example of how to use class-->
+ * The following is a simple example of how to obtain and use a
+ * <code>Partition</code> object. In this example, a list of the
+ * <code>Partition</code> objects of a server are obtained, and the name
+ * and number of volumes is printed out for each one.<BR><BR>
+ *
+ * <PRE>
+ * import org.openafs.jafs.Cell;
+ * import org.openafs.jafs.AFSException;
+ * import org.openafs.jafs.Partition;
+ * import org.openafs.jafs.Server;
+ * ...
+ * public class ...
+ * {
+ * ...
+ * private Cell cell;
+ * private Server server;
+ * ...
+ * public static void main(String[] args) throws Exception
+ * {
+ * String username = arg[0];
+ * String password = arg[1];
+ * String cellName = arg[2];
+ * String serverName = arg[3];
+ *
+ * token = new Token(username, password, cellName);
+ * cell = new Cell(token);
+ * server = new Server(serverName, cell);
+ *
+ * System.out.println("Partitions in Server " + server.getName() + ":");
+ * Partition[] partitions = server.getPartitions();
+ * for (int i = 0; i < partitions.length; i++) {
+ * System.out.print("Partition " + partitions[i].getName());
+ * System.out.print("hosts " + partitions[i].getVolumeCount());
+ * System.out.print("volumes.\n");
+ * }
+ * }
+ * ...
+ * }
+ * </PRE>
+ *
+ */
+public class Partition implements Serializable, Comparable
+{
+ protected Cell cell;
+ protected Server server;
+
+ /* Populated by native method */
+ protected String name;
+
+ /* Populated by native method */
+ protected int id;
+
+ /* Populated by native method */
+ protected String deviceName;
+
+ /* Populated by native method */
+ protected int lockFileDescriptor;
+
+ /* Populated by native method */
+ protected int totalSpace;
+
+ /* Populated by native method */
+ protected int totalFreeSpace;
+
+ protected int totalQuota;
+
+ protected ArrayList volumes;
+ protected ArrayList volumeNames;
+
+ protected boolean cachedInfo;
+
+ /**
+ * Constructs a new <code>Partition</code> object instance given the
+ * name of the AFS partition and the AFS server, represented by
+ * <CODE>server</CODE>, to which it belongs. This does not actually
+ * create a new AFS partition, it just represents an existing one.
+ * If <code>name</code> is not an actual AFS partition, exceptions
+ * will be thrown during subsequent method invocations on this
+ * object.
+ *
+ * @param name the name of the partition to represent
+ * @param server the server on which the partition resides
+ * @exception AFSException If an error occurs in the native code
+ */
+ public Partition( String name, Server server ) throws AFSException
+ {
+ this.name = name;
+ this.server = server;
+ this.cell = server.getCell();
+
+ id = -1;
+
+ volumes = null;
+ volumeNames = null;
+
+ cachedInfo = false;
+ }
+
+ /**
+ * Constructs a new <CODE>Partition</CODE> object instance given the name
+ * of the AFS partition and the AFS server, represented by
+ * <CODE>server</CODE>, to which it belongs. This does not actually
+ * create a new AFS partition, it just represents an existing one.
+ * If <code>name</code> is not an actual AFS partition, exceptions
+ * will be thrown during subsequent method invocations on this
+ * object.
+ *
+ * <P> This constructor is ideal for point-in-time representation and
+ * transient applications. It ensures all data member values are set and
+ * available without calling back to the filesystem at the first request
+ * for them. Use the {@link #refresh()} method to address any coherency
+ * concerns.
+ *
+ * @param name the name of the partition to represent
+ * @param server the server to which the partition belongs.
+ * @param preloadAllMembers true will ensure all object members are
+ * set upon construction;
+ * otherwise members will be set upon access,
+ * which is the default behavior.
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh
+ */
+ public Partition( String name, Server server, boolean preloadAllMembers )
+ throws AFSException
+ {
+ this(name, server);
+ if (preloadAllMembers) refresh(true);
+ }
+
+ /**
+ * Creates a blank <code>Server</code> given the cell to which the partition
+ * belongs and the server on which the partition resides. This blank
+ * object can then be passed into other methods to fill out its properties.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @param cell the cell to which the partition belongs.
+ * @param server the server on which the partition resides
+ */
+ Partition( Server server ) throws AFSException
+ {
+ this( null, server );
+ }
+
+ /*-------------------------------------------------------------------------*/
+
+ /**
+ * Refreshes the properties of this Partition object instance with values
+ * from the AFS partition
+ * it represents. All properties that have been initialized and/or
+ * accessed will be renewed according to the values of the AFS partition
+ * this Partition object instance represents.
+ *
+ * <P>Since in most environments administrative changes can be administered
+ * from an AFS command-line program or an alternate GUI application, this
+ * method provides a means to refresh the Java object representation and
+ * thereby ascertain any possible modifications that may have been made
+ * from such alternate administrative programs. Using this method before
+ * an associated instance accessor will ensure the highest level of
+ * representative accuracy, accommodating changes made external to the
+ * Java application space. If administrative changes to the underlying AFS
+ * system are only allowed via this API, then the use of this method is
+ * unnecessary.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void refresh() throws AFSException
+ {
+ refresh(false);
+ }
+
+ /**
+ * Refreshes the properties of this Partition object instance with values
+ * from the AFS partition it represents. If <CODE>all</CODE> is
+ * <CODE>true</CODE> then <U>all</U> of the properties of this Partition
+ * object instance will be set, or renewed, according to the values of the
+ * AFS partition it represents, disregarding any previously set properties.
+ *
+ * <P> Thus, if <CODE>all</CODE> is <CODE>false</CODE> then properties
+ * that are currently set will be refreshed and properties that are not
+ * set will remain uninitialized. See {@link #refresh()} for more
+ * information.
+ *
+ * @param all if true set or renew all object properties; otherwise
+ * renew all set properties
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh()
+ */
+ protected void refresh(boolean all) throws AFSException
+ {
+ if (all || volumes != null) {
+ refreshVolumes();
+ }
+ if (all || volumeNames != null) {
+ refreshVolumeNames();
+ }
+ if (all || cachedInfo) {
+ refreshInfo();
+ }
+ }
+
+ /**
+ * Refreshes the information fields of this <code>Partition</code> to
+ * reflect the current state of the AFS partition. These include total
+ * free space, id, etc.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshInfo() throws AFSException
+ {
+ getPartitionInfo( cell.getCellHandle(), server.getVosHandle(), getID(),
+ this );
+ cachedInfo = true;
+ }
+
+ /**
+ * Obtains the most current list of <code>Volume</code> objects of this
+ * partition.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshVolumes() throws AFSException
+ {
+ Volume currVolume;
+
+ int iterationID = getVolumesBegin( cell.getCellHandle(),
+ server.getVosHandle(), getID() );
+
+ volumes = new ArrayList();
+
+ currVolume = new Volume( this );
+ while( getVolumesNext( iterationID, currVolume ) != 0 ) {
+ volumes.add( currVolume );
+ currVolume = new Volume( this );
+ }
+ getVolumesDone( iterationID );
+ }
+
+ /**
+ * Obtains the most current list of volume names of this partition.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshVolumeNames() throws AFSException
+ {
+ String currName;
+
+ int iterationID = getVolumesBegin( cell.getCellHandle(),
+ server.getVosHandle(), getID() );
+
+ volumeNames = new ArrayList();
+
+ while( ( currName = getVolumesNextString( iterationID ) ) != null ) {
+ volumeNames.add( currName );
+ }
+ getVolumesDone( iterationID );
+ }
+
+ /**
+ * Syncs this partition to the VLDB.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void syncPartition() throws AFSException
+ {
+ server.syncServerWithVLDB( cell.getCellHandle(), server.getVosHandle(),
+ getID() );
+ }
+
+ /**
+ * Syncs the VLDB to this partition.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void syncVLDB() throws AFSException
+ {
+ server.syncVLDBWithServer( cell.getCellHandle(), server.getVosHandle(),
+ getID(), false );
+ }
+
+ /**
+ * Salvages (restores consistency to) this partition. Uses default values for
+ * most salvager options in order to simplify the API.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void salvage() throws AFSException
+ {
+ server.salvage( cell.getCellHandle(), server.getBosHandle(), name, null,
+ 4, null, null, false, false, false, false, false, false );
+ }
+
+ //////////////// accessors: ////////////////////////
+
+ /**
+ * Returns the name of this partition.
+ *
+ * @return the name of this partition
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns this partition's hosting server.
+ *
+ * @return this partition's server
+ */
+ public Server getServer()
+ {
+ return server;
+ }
+
+ /**
+ * Returns the number of volumes contained in this partition.
+ *
+ * <P>If the total list of volumes or volume names have already been
+ * collected (see {@link #getVolumes()}), then the returning value will
+ * be calculated based upon the current list. Otherwise, AFS will be
+ * explicitly queried for the information.
+ *
+ * <P> The product of this method is not saved, and is recalculated
+ * with every call.
+ *
+ * @return the number of volumes contained in this partition.
+ * @exception AFSException If an error occurs in any
+ * of the associated native methods
+ */
+ public int getVolumeCount() throws AFSException
+ {
+ if (volumes != null) {
+ return volumes.size();
+ } else if (volumeNames != null) {
+ return volumeNames.size();
+ } else {
+ return getVolumeCount( cell.getCellHandle(),
+ server.getVosHandle(), getID() );
+ }
+ }
+
+ /**
+ * Retrieves the <CODE>Volume</CODE> object (which is an abstract
+ * representation of an actual AFS volume of this partition) designated
+ * by <code>name</code> (i.e. "root.afs", etc.). If a volume by
+ * that name does not actually exist in AFS on the partition
+ * represented by this object, an {@link AFSException} will be
+ * thrown.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @exception NullPointerException If <CODE>name</CODE> is
+ * <CODE>null</CODE>.
+ * @param name the name of the volume to retrieve
+ * @return <CODE>Volume</CODE> designated by <code>name</code>.
+ */
+ public Volume getVolume(String name) throws AFSException
+ {
+ if (name == null) throw new NullPointerException();
+ Volume volume = new Volume(name, this);
+ return volume;
+ }
+
+ /**
+ * Retrieves an array containing all of the <code>Volume</code> objects
+ * associated with this <code>Partition</code>, each of which is an
+ * abstract representation of an actual AFS volume of the AFS partition.
+ * After this method is called once, it saves the array of
+ * <code>Volume</code>s and returns that saved array on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current list
+ * is obtained.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return a <code>Volume</code> array of the <code>Volume</code>
+ * objects of the partition.
+ * @see #refresh()
+ */
+ public Volume[] getVolumes() throws AFSException
+ {
+ if (volumes == null) refreshVolumes();
+ return (Volume[]) volumes.toArray( new Volume[volumes.size()] );
+ }
+
+ /**
+ * Returns an array containing a subset of the <code>Volume</code> objects
+ * associated with this <code>Partition</code>, each of which is an abstract
+ * representation of an actual AFS volume of the AFS partition. The subset
+ * is a point-in-time list of volumes (<code>Volume</code> objects
+ * representing AFS volumes) starting at the complete array's index of
+ * <code>startIndex</code> and containing up to <code>length</code>
+ * elements.
+ *
+ * If <code>length</code> is larger than the number of remaining elements,
+ * respective to <code>startIndex</code>, then this method will
+ * ignore the remaining positions requested by <code>length</code> and
+ * return an array that contains the remaining number of elements found in
+ * this partition's complete array of volumes.
+ *
+ * <P>This method is especially useful when managing iterations of very
+ * large lists. {@link #getVolumeCount()} can be used to determine if
+ * iteration management is practical.
+ *
+ * <P>This method does not save the resulting data and therefore
+ * queries AFS for each call.
+ *
+ * <P><B>Example:</B> If there are more than 50,000 volumes within this partition
+ * then only render them in increments of 10,000.
+ * <PRE>
+ * ...
+ * Volume[] volumes;
+ * if (partition.getVolumeCount() > 50000) {
+ * int index = 0;
+ * int length = 10000;
+ * while (index < partition.getVolumeCount()) {
+ * volumes = partition.<B>getVolumes</B>(index, length);
+ * for (int i = 0; i < volumes.length; i++) {
+ * ...
+ * }
+ * index += length;
+ * ...
+ * }
+ * } else {
+ * volumes = partition.getVolumes();
+ * for (int i = 0; i < volumes.length; i++) {
+ * ...
+ * }
+ * }
+ * ...
+ * </PRE>
+ *
+ * @param startIndex the base zero index position at which the subset array
+ * should start from, relative to the complete list of
+ * elements present in AFS.
+ * @param length the number of elements that the subset should contain
+ * @return a subset array of volumes hosted by this partition
+ * @exception AFSException If an error occurs in the native code
+ * @see #getVolumeCount()
+ * @see #getVolumeNames(int, int)
+ * @see #getVolumes()
+ */
+ public Volume[] getVolumes(int startIndex, int length) throws AFSException
+ {
+ Volume[] volumes = new Volume[length];
+ Volume currVolume = new Volume( this );
+ int i = 0;
+
+ int iterationID = getVolumesBeginAt( cell.getCellHandle(),
+ server.getVosHandle(), getID(), startIndex );
+
+ while( getVolumesNext( iterationID, currVolume ) != 0 && i < length ) {
+ volumes[i] = currVolume;
+ currVolume = new Volume( this );
+ i++;
+ }
+ getVolumesDone( iterationID );
+ if (i < length) {
+ Volume[] v = new Volume[i];
+ System.arraycopy(volumes, 0, v, 0, i);
+ return v;
+ } else {
+ return volumes;
+ }
+ }
+
+ /**
+ * Retrieves an array containing all of the names of volumes
+ * associated with this <code>Partition</code>.
+ * After this method is called once, it saves the array of
+ * <code>String</code>s and returns that saved array on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * list is obtained.
+ *
+ * @return a <code>String</code> array of the volumes of the partition.
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh()
+ */
+ public String[] getVolumeNames() throws AFSException
+ {
+ if (volumeNames == null) refreshVolumeNames();
+ return (String []) volumeNames.toArray( new String[volumeNames.size() ] );
+ }
+
+ /**
+ * Returns an array containing a subset of the names of volumes
+ * associated with this <code>Partition</code>. The subset is a
+ * point-in-time list of volume names starting at the complete array's
+ * index of <code>startIndex</code> and containing up to <code>length</code>
+ * elements.
+ *
+ * If <code>length</code> is larger than the number of remaining elements,
+ * respective to <code>startIndex</code>, then this method will
+ * ignore the remaining positions requested by <code>length</code> and
+ * return an array that contains the remaining number of elements found in
+ * this partition's complete array of volume names.
+ *
+ * <P>This method is especially useful when managing iterations of very
+ * large lists. {@link #getVolumeCount()} can be used to determine if
+ * iteration management is practical.
+ *
+ * <P>This method does not save the resulting data and therefore
+ * queries AFS for each call.
+ *
+ * <P><B>Example:</B> If there are more than 50,000 volumes within this partition
+ * then only render them in increments of 10,000.
+ * <PRE>
+ * ...
+ * String[] volumes;
+ * if (partition.getVolumeCount() > 50000) {
+ * int index = 0;
+ * int length = 10000;
+ * while (index < partition.getVolumeCount()) {
+ * volumes = partition.<B>getVolumeNames</B>(index, length);
+ * for (int i = 0; i < volumes.length; i++) {
+ * ...
+ * }
+ * index += length;
+ * ...
+ * }
+ * } else {
+ * volumes = partition.getVolumeNames();
+ * for (int i = 0; i < volumes.length; i++) {
+ * ...
+ * }
+ * }
+ * ...
+ * </PRE>
+ *
+ * @param startIndex the base zero index position at which the subset array
+ * should start from, relative to the complete list of
+ * elements present in AFS.
+ * @param length the number of elements that the subset should contain
+ * @return a subset array of volume names hosted by this partition
+ * @exception AFSException If an error occurs in the native code
+ * @see #getVolumeCount()
+ * @see #getVolumes(int, int)
+ * @see #getVolumes()
+ */
+ public String[] getVolumeNames(int startIndex, int length) throws AFSException
+ {
+ String[] volumes = new String[length];
+ String currName;
+ int i = 0;
+
+ int iterationID = getVolumesBeginAt( cell.getCellHandle(),
+ server.getVosHandle(), getID(), startIndex );
+
+ while( ( currName = getVolumesNextString( iterationID ) ) != null && i < length ) {
+ volumes[i] = currName;
+ i++;
+ }
+ getVolumesDone( iterationID );
+ if (i < length) {
+ String[] v = new String[i];
+ System.arraycopy(volumes, 0, v, 0, i);
+ return v;
+ } else {
+ return volumes;
+ }
+ }
+
+ /**
+ * Returns the id of this partition (i.e. "vicepa" = 0, etc.)
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return the id of this partition
+ */
+ public int getID() throws AFSException
+ {
+ if (id == -1) id = translateNameToID( name );
+ return id;
+ }
+
+ /**
+ * Returns the device name of this partition (i.e. "hda5", etc.)
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return the device name of this partition
+ * @see #refresh()
+ */
+ public String getDeviceName() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return deviceName;
+ }
+
+ /**
+ * Returns the lock file descriptor of this partition
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return the lock file descriptor of this partition
+ * @see #refresh()
+ */
+ public int getLockFileDescriptor() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return lockFileDescriptor;
+ }
+
+ /**
+ * Returns the total space on this partition.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return the total space on this partition
+ * @see #refresh()
+ */
+ public int getTotalSpace() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return totalSpace;
+ }
+
+ /**
+ * Returns the total free space on this partition.
+ * After this method is called once, it saves the total free space
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return the total free space on this partition
+ * @see #refresh()
+ */
+ public int getTotalFreeSpace() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return totalFreeSpace;
+ }
+
+ /**
+ * Returns the total used space on this partition.
+ * After this method is called once, it saves the total used space
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return the total used space on this partition
+ * @see #refresh()
+ */
+ public int getUsedSpace() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return (totalSpace - totalFreeSpace);
+ }
+
+ /**
+ * Returns the total combined quota of all volumes on this partition,
+ * unless a volume has configured an unlimited quota at which case an
+ * {@link AFSException} is thrown.
+ *
+ * <P>After this method is called once, it saves the value and returns
+ * that value on subsequent calls, until the {@link #refresh()}
+ * method is called and a more current value is obtained.
+ *
+ * @exception AFSException If an error occurs while retrieving and
+ * calculating, or a volume has an
+ * unlimited quota.
+ * @return the total combined quota of all volumes on this partition
+ * @see #getTotalQuota(boolean)
+ * @see #hasVolumeWithUnlimitedQuota()
+ * @see Volume#getQuota()
+ */
+ public int getTotalQuota() throws AFSException
+ {
+ return getTotalQuota(false);
+ }
+
+ /**
+ * Returns the total combined quota of all volumes on this partition,
+ * ignoring volumes with unlimited quotas, if <CODE>
+ * ignoreUnlimitedQuotas</CODE> is <CODE>true</CODE>; otherwise an
+ * {@link AFSException} is thrown if a volume has an unlimited quota.
+ *
+ * <P>After this method is called once, it saves the value and returns
+ * that value on subsequent calls, until the {@link #refresh()}
+ * method is called and a more current value is obtained.
+ *
+ * @exception AFSException If an error occurs while retrieving and
+ * calculating, or a volume has an
+ * unlimited quota.
+ * @return the total combined quota of all volumes on this partition
+ * @see #getTotalQuota()
+ * @see #hasVolumeWithUnlimitedQuota()
+ * @see Volume#getQuota()
+ * @see #refresh()
+ */
+ public int getTotalQuota(boolean ignoreUnlimitedQuotas)
+ throws AFSException
+ {
+ if (volumes == null) refreshVolumes();
+ if (totalQuota == 0 || !ignoreUnlimitedQuotas) {
+ Volume[] volumes = getVolumes();
+ for (int i = 0; i < volumes.length; i++) {
+ try {
+ totalQuota += volumes[i].getQuota();
+ } catch (AFSException e) {
+ if (!ignoreUnlimitedQuotas) {
+ totalQuota = 0;
+ throw e;
+ }
+ }
+ }
+ }
+ return totalQuota;
+ }
+
+ /**
+ * Tests whether this partition contains a volume that has an unlimited
+ * quota configured.
+ *
+ * @exception AFSException If an error occurs in the native code
+ * @return <CODE>true</CODE> if a contained volume's quota is configured
+ * as unlimited; otherwise <CODE>false</CODE>.
+ * @see #getTotalQuota()
+ * @see #getTotalQuota(boolean)
+ * @see Volume#isQuotaUnlimited()
+ * @see Volume#getQuota()
+ * @see #refresh()
+ */
+ public boolean hasVolumeWithUnlimitedQuota() throws AFSException
+ {
+ if (volumes == null) refreshVolumes();
+ Volume[] volumes = getVolumes();
+ for (int i = 0; i < volumes.length; i++) {
+ if (volumes[i].isQuotaUnlimited()) return true;
+ }
+ return false;
+ }
+
+ /////////////// custom information methods ////////////////////
+
+ /**
+ * Returns a <code>String</code> representation of this
+ * <code>Partition</code>. Contains the information fields and a list of
+ * volumes.
+ *
+ * @return a <code>String</code> representation of the <code>Partition</code>
+ */
+ protected String getInfo()
+ {
+ String r;
+
+ try {
+
+ r = "Partition: " + name + "\tid: " + getID() + "\n";
+
+ r += "\tDevice name: " + getDeviceName() + "\n";
+ r += "\tLock file descriptor: " + getLockFileDescriptor() + "\n";
+ r += "\tTotal free space: " + getTotalFreeSpace() + " K\n";
+ r += "\tTotal space: " + getTotalSpace() + " K\n";
+
+ r += "\tVolumes:\n";
+
+ String vols[] = getVolumeNames();
+
+ for( int i = 0; i < vols.length; i++ ) {
+ r += "\t\t" + vols[i] + "\n";
+ }
+
+ } catch( Exception e ) {
+ return e.toString();
+ }
+ return r;
+ }
+
+ /**
+ * Returns a <code>String</code> containing the <code>String</code>
+ * representations of all the volumes of this <code>Partition</code>.
+ *
+ * @return a <code>String</code> representation of the volumes
+ * @see Volume#getInfo
+ */
+ protected String getInfoVolumes() throws AFSException
+ {
+ String r;
+
+ r = "Partition: " + name + "\n\n";
+ r += "--Volumes--\n";
+
+ Volume vols[] = getVolumes();
+ for( int i = 0; i < vols.length; i++ ) {
+ r += vols[i].getInfo() + "\n";
+ }
+ return r;
+ }
+
+ /////////////// custom override methods ////////////////////
+
+ /**
+ * Compares two Partition objects respective to their names and does not
+ * factor any other attribute. Alphabetic case is significant in
+ * comparing names.
+ *
+ * @param partition The Partition object to be compared to
+ * this Partition instance
+ *
+ * @return Zero if the argument is equal to this Partition's name, a
+ * value less than zero if this Partition's name is
+ * lexicographically less than the argument, or a value greater
+ * than zero if this Partition's name is lexicographically
+ * greater than the argument
+ */
+ public int compareTo(Partition partition)
+ {
+ return this.getName().compareTo(partition.getName());
+ }
+
+ /**
+ * Comparable interface method.
+ *
+ * @see #compareTo(Partition)
+ */
+ public int compareTo(Object obj)
+ {
+ return compareTo((Partition)obj);
+ }
+
+ /**
+ * Tests whether two <code>Partition</code> objects are equal,
+ * based on their names and hosting server.
+ *
+ * @param otherPartition the Partition to test
+ * @return whether the specifed Partition is the same as this Partition
+ */
+ public boolean equals( Partition otherPartition )
+ {
+ return ( name.equals(otherPartition.getName()) ) &&
+ ( getServer().equals(otherPartition.getServer()) );
+ }
+
+ /**
+ * Returns the name of this <CODE>Partition</CODE>
+ *
+ * @return the name of this <CODE>Partition</CODE>
+ */
+ public String toString()
+ {
+ return getName();
+ }
+
+ /////////////// native methods ////////////////////
+
+ /**
+ * Fills in the information fields of the provided <code>Partition</code>.
+ *
+ * @param cellHandle the handle of the cell to which the partition belongs
+ * @see Cell#getCellHandle
+ * @param serverHandle the vos handle of the server on which the
+ * partition resides
+ * @see Server#getVosServerHandle
+ * @param partition the numeric id of the partition for which to get the
+ * info
+ * @param thePartition the {@link Partition Partition} object in which to
+ * fill in the information
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void getPartitionInfo( int cellHandle,
+ int serverHandle,
+ int partition,
+ Partition thePartition )
+ throws AFSException;
+
+ /**
+ * Returns the total number of volumes hosted by this partition.
+ *
+ * @param cellHandle the handle of the cell to which the partition belongs
+ * @param serverHandle the vos handle of the server to which the partition
+ * belongs
+ * @param partition the numeric id of the partition on which the volumes
+ * reside
+ * @return total number of volumes hosted by this partition
+ * @exception AFSException If an error occurs in the native code
+ * @see Cell#getCellHandle
+ * @see Server#getVosServerHandle
+ */
+ protected static native int getVolumeCount( int cellHandle,
+ int serverHandle,
+ int partition )
+ throws AFSException;
+
+ /**
+ * Begin the process of getting the volumes on a partition. Returns
+ * an iteration ID to be used by subsequent calls to
+ * <code>getVolumesNext</code> and <code>getVolumesDone</code>.
+ *
+ * @param cellHandle the handle of the cell to which the partition belongs
+ * @see Cell#getCellHandle
+ * @param serverHandle the vos handle of the server to which the partition
+ * belongs
+ * @see Server#getVosServerHandle
+ * @param partition the numeric id of the partition on which the volumes
+ * reside
+ * @return an iteration ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getVolumesBegin( int cellHandle,
+ int serverHandle,
+ int partition )
+ throws AFSException;
+
+ /**
+ * Begin the process of getting the volumes on a partition. Returns
+ * an iteration ID to be used by subsequent calls to
+ * <code>getVolumesNext</code> and <code>getVolumesDone</code>.
+ *
+ * @param cellHandle the handle of the cell to which the partition belongs
+ * @see Cell#getCellHandle
+ * @param serverHandle the vos handle of the server to which the partition
+ * belongs
+ * @see Server#getVosServerHandle
+ * @param partition the numeric id of the partition on which the volumes
+ * reside
+ * @return an iteration ID
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getVolumesBeginAt( int cellHandle,
+ int serverHandle,
+ int partition, int index )
+ throws AFSException;
+
+ /**
+ * Returns the next volume of the partition. Returns <code>null</code>
+ * if there are no more volumes.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see #getVolumesBegin
+ * @return the name of the next volume of the server
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native String getVolumesNextString( int iterationId )
+ throws AFSException;
+
+ /**
+ * Fills the next volume object of the partition. Returns 0 if there
+ * are no more volumes, != 0 otherwise.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @param theVolume the Volume object in which to fill the values
+ * of the next volume
+ * @see #getVolumesBegin
+ * @return 0 if there are no more volumes, != 0 otherwise
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getVolumesNext( int iterationId,
+ Volume theVolume )
+ throws AFSException;
+
+ /**
+ * Fills the next volume object of the partition. Returns 0 if there
+ * are no more volumes, != 0 otherwise.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @param theVolume the Volume object in which to fill the values of the
+ * next volume
+ * @see #getVolumesBegin
+ * @return 0 if there are no more volumes, != 0 otherwise
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int getVolumesAdvanceTo( int iterationId,
+ Volume theVolume,
+ int advanceCount )
+ throws AFSException;
+
+ /**
+ * Signals that the iteration is complete and will not be accessed anymore.
+ *
+ * @param iterationId the iteration ID of this iteration
+ * @see #getVolumesBegin
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native void getVolumesDone( int iterationId )
+ throws AFSException;
+
+ /**
+ * Translates a partition name into a partition id
+ *
+ * @param name the name of the partition in question
+ * @return the id of the partition in question
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native int translateNameToID( String name )
+ throws AFSException;
+
+ /**
+ * Translates a partition id into a partition name
+ *
+ * @param id the id of the partition in question
+ * @return the name of the partition in question
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected static native String translateIDToName( int id )
+ throws AFSException;
+
+ /**
+ * Reclaims all memory being saved by the partition portion of the native
+ * library. This method should be called when no more <code>Partition</code>
+ * objects are expected to be
+ * used.
+ */
+ protected static native void reclaimPartitionMemory();
+}
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * @(#)Process.java 1.0 6/29/2001
+ *
+ * Copyright (c) 2001 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.openafs.jafs;
+
+import java.util.GregorianCalendar;
+import java.util.Date;
+import java.io.Serializable;
+
+/**
+ * An abstract representation of an AFS process. It holds information about
+ * the server, such as what its state is.
+ * <BR><BR>
+ *
+ * Constructing an instance of a <code>Process</code> does not mean an actual
+ * AFS process is created on a server -- usually a <code>Process</code>
+ * object is a representation of an already existing AFS process. If,
+ * however, the <code>Process</code> is constructed with the name of a
+ * process that does not exist in the server represented by the provided
+ * <code>Server</code>, a new process with that name can be
+ * created on that server by calling one of the {@link #createSimple(String)},
+ * {@link #createFS(String)}, or {@link #createCron(String,String)} methods. If
+ * such a process does already exist when one of these methods are called,
+ * an exception will be thrown.<BR><BR>
+ *
+ * <!--Information on how member values are set-->
+ *
+ * <!--Example of how to use class-->
+ * The following is a simple example of how to construct and use a
+ * <code>Process</code> object. This example obtains the list of all
+ * <code>Process</code> objects on a particular server and prints out the
+ * name of each one along with its start time.<BR><BR>
+ *
+ * <PRE>
+ * import org.openafs.jafs.Cell;
+ * import org.openafs.jafs.AFSException;
+ * import org.openafs.jafs.Process;
+ * import org.openafs.jafs.Server;
+ * ...
+ * public class ...
+ * {
+ * ...
+ * private Cell cell;
+ * private Server server;
+ * ...
+ * public static void main(String[] args) throws Exception
+ * {
+ * String username = arg[0];
+ * String password = arg[1];
+ * String cellName = arg[2];
+ * String serverName = arg[3];
+ *
+ * token = new Token(username, password, cellName);
+ * cell = new Cell(token);
+ * server = new Server(serverName, cell);
+ *
+ * System.out.println("Processes in Server " + server.getName() + ":");
+ * Process[] processes = server.getProcesss();
+ * for (int i = 0; i < processes.length; i++) {
+ * System.out.print("Process " + processes[i].getName());
+ * System.out.print("was started: " +
+ * processes[i].getStartTimeDate().getTime() + "\n");
+ * }
+ * }
+ * ...
+ * }
+ * </PRE>
+ *
+ */
+public class Process implements Serializable, Comparable
+{
+ /**
+ * Any standard type of process except for fs (such as kaserver,
+ * upclientbin, etc.)
+ */
+ public static final int SIMPLE_PROCESS = 0;
+
+ /**
+ * Combination of File Server, Volume Server, and Salvager processes
+ */
+ public static final int FS_PROCESS = 1;
+
+ /**
+ * A process that should be restarted at a specific time either daily
+ * or weekly.
+ */
+ public static final int CRON_PROCESS = 2;
+
+ /**
+ * Process execution state stopped
+ */
+ public static final int STOPPED = 0;
+
+ /**
+ * Process execution state running
+ */
+ public static final int RUNNING = 1;
+
+ /**
+ * Process execution state stopping
+ */
+ public static final int STOPPING = 2;
+
+ /**
+ * Process execution state starting
+ */
+ public static final int STARTING = 3;
+
+ protected String name;
+ protected Server server;
+ protected int serverHandle;
+
+ protected int type;
+ protected int state;
+ protected int goal;
+
+ protected long startTime;
+ protected long numberStarts;
+ protected long exitTime;
+ protected long exitErrorTime;
+ protected long errorCode;
+ protected long errorSignal;
+
+ protected boolean stateOk;
+ protected boolean stateTooManyErrors;
+ protected boolean stateBadFileAccess;
+
+ protected GregorianCalendar startTimeDate;
+ protected GregorianCalendar exitTimeDate;
+ protected GregorianCalendar exitErrorTimeDate;
+
+ protected boolean cachedInfo;
+
+ /**
+ * Constructs a new <code>Process</code> object instance given the name
+ * of the AFS process and the AFS server, represented by
+ * <CODE>server</CODE>, to which it belongs. This does not actually
+ * create a new AFS process, it just represents one.
+ * If <code>name</code> is not an actual AFS process, exceptions
+ * will be thrown during subsequent method invocations on this
+ * object, unless one of the {@link #createSimple(String)},
+ * {@link #createFS(String)}, or {@link #createCron(String,String)}
+ * methods are explicitly called to create it.
+ *
+ * @param name the name of the server to represent
+ * @param server the server on which the process resides
+ * @exception AFSException If an error occurs in the native code
+ */
+ public Process( String name, Server server ) throws AFSException
+ {
+ this.name = name;
+ this.server = server;
+ serverHandle = server.getBosHandle();
+
+ startTimeDate = null;
+ exitTimeDate = null;
+ exitErrorTimeDate = null;
+
+ cachedInfo = false;
+ }
+
+ /**
+ * Constructs a new <CODE>Process</CODE> object instance given the name
+ * of the AFS process and the AFS server, represented by
+ * <CODE>server</CODE>, to which it belongs. This does not actually
+ * create a new AFS process, it just represents one.
+ * If <code>name</code> is not an actual AFS process, exceptions
+ * will be thrown during subsequent method invocations on this
+ * object, unless one of the {@link #createSimple(String)},
+ * {@link #createFS(String)}, or {@link #createCron(String,String)}
+ * methods are explicitly called to create it. Note that if he process
+ * doesn't exist and <code>preloadAllMembers</code> is true, an exception
+ * will be thrown.
+ *
+ * <P> This constructor is ideal for point-in-time representation and
+ * transient applications. It ensures all data member values are set and
+ * available without calling back to the filesystem at the first request
+ * for them. Use the {@link #refresh()} method to address any coherency
+ * concerns.
+ *
+ * @param name the name of the process to represent
+ * @param server the server to which the process belongs.
+ * @param preloadAllMembers true will ensure all object members are
+ * set upon construction; otherwise members will
+ * be set upon access, which is the default
+ * behavior.
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh
+ */
+ public Process( String name, Server server, boolean preloadAllMembers )
+ throws AFSException
+ {
+ this(name, server);
+ if (preloadAllMembers) refresh(true);
+ }
+
+ /**
+ * Creates a blank <code>Process</code> given the server to which the process
+ * belongs. This blank object can then be passed into other methods to fill
+ * out its properties.
+ *
+ * @param server the server to which the process belongs.
+ * @exception AFSException If an error occurs in the native code
+ */
+ Process( Server server ) throws AFSException
+ {
+ this( null, server );
+ }
+
+ /*-------------------------------------------------------------------------*/
+
+ /**
+ * Refreshes the properties of this Process object instance with values
+ * from the AFS process it represents. All properties that have been
+ * initialized and/or accessed will be renewed according to the values of
+ * the AFS process this Process object instance represents.
+ *
+ * <P>Since in most environments administrative changes can be administered
+ * from an AFS command-line program or an alternate GUI application, this
+ * method provides a means to refresh the Java object representation and
+ * thereby ascertain any possible modifications that may have been made
+ * from such alternate administrative programs. Using this method before
+ * an associated instance accessor will ensure the highest level of
+ * representative accuracy, accommodating changes made external to the
+ * Java application space. If administrative changes to the underlying AFS
+ * system are only allowed via this API, then the use of this method is
+ * unnecessary.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void refresh() throws AFSException
+ {
+ refresh(false);
+ }
+
+ /**
+ * Refreshes the properties of this Process object instance with values from
+ * the AFS process it represents. If <CODE>all</CODE> is <CODE>true</CODE>
+ * then <U>all</U> of the properties of this Process object instance will be
+ * set, or renewed, according to the values of the AFS process it represents,
+ * disregarding any previously set properties.
+ *
+ * <P> Thus, if <CODE>all</CODE> is <CODE>false</CODE> then properties that
+ * are currently set will be refreshed and properties that are not set will
+ * remain uninitialized. See {@link #refresh()} for more information.
+ *
+ * @param all if true set or renew all object properties; otherwise renew
+ * all set properties
+ * @exception AFSException If an error occurs in the native code
+ * @see #refresh()
+ */
+ protected void refresh(boolean all) throws AFSException
+ {
+ if (all || cachedInfo) refreshInfo();
+ }
+
+ /**
+ * Refreshes the information fields of this <code>Process</code> to reflect
+ * the current state of the AFS process, such as the start time, the state,
+ * etc.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ protected void refreshInfo() throws AFSException
+ {
+ getProcessInfo( server.getBosHandle(), name, this );
+ cachedInfo = true;
+ startTimeDate = null;
+ exitTimeDate = null;
+ exitErrorTimeDate = null;
+ }
+
+ /**
+ * Creates this process as a simple process on the server.
+ *
+ * @param executionPath the path to the process's executable
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void createSimple( String executionPath ) throws AFSException
+ {
+ create( server.getBosHandle(), name, SIMPLE_PROCESS, executionPath, null,
+ null );
+ }
+
+ /**
+ * Creates this process as a file server process on the server.
+ *
+ * @param executionPath the path to the process's executable
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void createFS( String executionPath ) throws AFSException
+ {
+ create( server.getBosHandle(), name, FS_PROCESS, executionPath, null,
+ null );
+ }
+
+ /**
+ * Creates this process as a cron process on the server.
+ *
+ * @param executionPath the path to the process's executable
+ * @param cronTime a String representing the time a cron process is
+ * to be run. Acceptable formats are:<ul>
+ * <li>for daily restarts: "23:10" or "11:10 pm"</li>
+ * <li>for weekly restarts: "sunday 11:10pm" or
+ * "sun 11:10pm"</li>
+ * </ul>
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void createCron( String executionPath, String cronTime )
+ throws AFSException
+ {
+ create( server.getBosHandle(), name, CRON_PROCESS, executionPath,
+ cronTime, null );
+ }
+
+ /**
+ * Removes this process from the bos server
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void delete() throws AFSException
+ {
+ delete( server.getBosHandle(), name );
+ }
+
+ /**
+ * Stops this process.
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void stop() throws AFSException
+ {
+ state = STOPPING;
+ goal = STOPPED;
+ stop( server.getBosHandle(), name );
+ }
+
+ /**
+ * Starts this process
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void start() throws AFSException
+ {
+ state = STARTING;
+ start( server.getBosHandle(), name );
+ }
+
+ /**
+ * Restarts this process
+ *
+ * @exception AFSException If an error occurs in the native code
+ */
+ public void restart() throws AFSException
+ {
+ state = STARTING;
+ restart( server.getBosHandle(), name );
+ }
+
+ //////////////// accessors: ////////////////////////
+
+ /**
+ * Returns the name of this process.
+ *
+ * @return the name of this process
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns the server hosting this process.
+ *
+ * @return this process' server
+ */
+ public Server getServer()
+ {
+ return server;
+ }
+
+ /**
+ * Returns the process type. Possible values are:<ul>
+ * <li>{@link #SIMPLE_PROCESS}</li>
+ * <li>{@link #FS_PROCESS}</li>
+ * <li>{@link #CRON_PROCESS}</li></ul>
+ *
+ * @return the process type
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getType() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return type;
+ }
+
+ /**
+ * Returns the process goal. Possible values are:<ul>
+ * <li>{@link #STOPPED}</li>
+ * <li>{@link #RUNNING}</li>
+ * <li>{@link #STARTING}</li>
+ * <li>{@link #STOPPING}</li></ul>
+ * After this method is called once, it saves the value
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @return the process goal
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getGoal() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return goal;
+ }
+
+ /**
+ * Returns the process execution state. Possible values are:<ul>
+ * <li>{@link #STOPPED}</li>
+ * <li>{@link #RUNNING}</li>
+ * <li>{@link #STARTING}</li>
+ * <li>{@link #STOPPING}</li></ul>
+ * After this method is called once, it saves the value
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @return the process execution state
+ * @exception AFSException If an error occurs in the native code
+ */
+ public int getState() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return state;
+ }
+
+ /**
+ * Returns the most recent start time of this process. A
+ * <code>null</code> value
+ * indicates no start time.
+ * After this method is called once, it saves the value
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @return the start time
+ * @exception AFSException If an error occurs in the native code
+ */
+ public long getStartTime() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return startTime;
+ }
+
+ /**
+ * Returns the most recent start time of this process. A <code>null</code>
+ * value indicates no start time.
+ * After this method is called once, it saves the value
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @return the start time
+ * @exception AFSException If an error occurs in the native code
+ */
+ public GregorianCalendar getStartTimeDate() throws AFSException
+ {
+ if (!cachedInfo) {
+ refreshInfo();
+ }
+ if( startTimeDate == null && startTime != 0 ) {
+ // make it into a date . . .
+ startTimeDate = new GregorianCalendar();
+ long longTime = startTime * 1000;
+ Date d = new Date( longTime );
+ startTimeDate.setTime( d );
+ }
+ return startTimeDate;
+ }
+
+ /**
+ * Returns the number of starts of the process.
+ * After this method is called once, it saves the value
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @return the number of starts
+ * @exception AFSException If an error occurs in the native code
+ */
+ public long getNumberOfStarts() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return numberStarts;
+ }
+
+ /**
+ * Returns the most recent exit time of this process. A <code>null</code>
+ * value indicates no exit time.
+ * After this method is called once, it saves the value
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @return the exit time
+ * @exception AFSException If an error occurs in the native code
+ */
+ public long getExitTime() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return exitTime;
+ }
+
+ /**
+ * Returns the most recent exit time of this process. A <code>null</code>
+ * value indicates no exit time
+ * After this method is called once, it saves the value
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @return the exit time
+ * @exception AFSException If an error occurs in the native code
+ */
+ public GregorianCalendar getExitTimeDate() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ if( exitTimeDate == null && exitTime != 0 ) {
+ // make it into a date . . .
+ exitTimeDate = new GregorianCalendar();
+ long longTime = exitTime*1000;
+ Date d = new Date( longTime );
+ exitTimeDate.setTime( d );
+ }
+ return exitTimeDate;
+ }
+
+ /**
+ * Returns the most recent time this process exited with an error. A
+ * <code>null</code> value indicates no exit w/ error time.
+ * After this method is called once, it saves the value
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @return the exit w/ error time
+ * @exception AFSException If an error occurs in the native code
+ */
+ public long getExitErrorTime() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ return exitErrorTime;
+ }
+
+ /**
+ * Returns the most recent time this process exited with an error. A <
+ * code>null</code> value indicates no exit w/ error time.
+ * After this method is called once, it saves the value
+ * and returns that value on subsequent calls,
+ * until the {@link #refresh()} method is called and a more current
+ * value is obtained.
+ *
+ * @return the exit w/ error time
+ * @exception AFSException If an error occurs in the native code
+ */
+ public GregorianCalendar getExitErrorTimeDate() throws AFSException
+ {
+ if (!cachedInfo) refreshInfo();
+ if (exitErrorTimeDate == null && exitErrorTime != 0) {
+ // make it into a date . . .
+ exitErrorTimeDate = new GregorianCalendar();
+ long longTime = exitErrorTime*1000;
+ Date d = new Date( longTime );
+ exitErrorTimeDate.setTime( d );
+ }
+ return exitErrorTimeDate;
+ }
+
+ /**
+ * Returns the error code of the process. A value of 0 indicates
+