Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / JAVA / classes / org / openafs / jafs / File.java
CommitLineData
805e021f
CE
1/*
2 * @(#)File.java 1.3 10/12/2000
3 *
4 * Copyright (c) 2001 International Business Machines Corp.
5 * All rights reserved.
6 *
7 * This software has been released under the terms of the IBM Public
8 * License. For details, see the LICENSE file in the top-level source
9 * directory or online at http://www.openafs.org/dl/license10.html
10 *
11 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
12 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
13 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
15 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 */
23
24package org.openafs.jafs;
25
26import java.io.IOException;
27import java.util.ArrayList;
28
29/*****************************************************************************/
30/**
31 *
32 * An abstract representation of AFS file and directory pathnames.
33 *
34 * This class is an extension of the standard Java File class with file-based
35 * manipulation methods overridden by integrated AFS native methods.
36 *
37 * <p> Extension methods include:
38 *
39 * <ol>
40 * <li> <code>{@link #isMountPoint}</code>
41 * <li> <code>{@link #isLink}</code>
42 * <li> <code>{@link #isValidated}</code>
43 * <li> <code>{@link #validate}</code>
44 * <li> <code>{@link #refresh}</code>
45 * <li> <code>{@link #getErrorCode}</code>
46 * <li> <code>{@link #getErrorMessage}</code>
47 * </ol>
48 *
49 * <p> For performance optimization, all newly constructed <code>File</code>
50 * objects are only validated once. Furthermore, if an abstract pathname
51 * denotes a symbolic-link, then the {@link #isLink} attribute is set
52 * to true and the {@link #getTarget} field member is populated with
53 * this symbolic-link's target resource. (see {@link #getTarget})
54 *
55 * <p> If you are interested in validating the target resource, simply
56 * call {@link #validate} before calling any of the attribute accessors.
57 * This action will <code>stat</code> the target resource, identifying
58 * its associated attributes and populating them in this objects field
59 * members.
60 *
61 * <p> Following is an example of how to construct a new AFS File Object:
62 * <p><blockquote><pre>
63 * try {
64 * File file = new File("/afs/mycell.com/proj/");
65 * if (file.isDirectory()) {
66 * System.out.println("This is a directory.");
67 * } else if (file.isLink()) {
68 * System.out.println("This is a symbolic-link.");
69 * System.out.println(" Its target is: " + file.getTarget());
70 * file.validate();
71 * if (file.isFile()) {
72 * System.out.println(" This object is now a file!");
73 * } else if (file.isDirectory()) {
74 * System.out.println(" This object is now a directory!");
75 * } else if (file.isMountPoint()) {
76 * System.out.println(" This object is now a volume mount point!");
77 * }
78 * } else if (file.isMountPoint()) {
79 * System.out.println("This is a volume mount point.");
80 * } else if (file.isFile()) {
81 * System.out.println("This is file.");
82 * System.out.println(" its size is: " + file.length());
83 * }
84 * } catch (AFSFileException ae) {
85 * System.out.println("AFS Exception: " + ae.getMessage());
86 * System.out.println("AFS Error Code: " + ae.getErrorCode());
87 * } catch (Exception e) {
88 * System.out.println("Exception: " + e.getMessage());
89 * e.printStackTrace();
90 * }
91 * </pre></blockquote>
92 *
93 * @version 2.0, 04/16/2001 - Completely revised class for efficiency.
94 * @version 1.3, 10/12/2000 - Introduced error code capture from native methods.
95 * @version 1.2, 05/30/2000
96 */
97public class File extends java.io.File implements Comparable
98{
99 private String path;
100 private String type;
101 private String target;
102
103 /** Each member is mutually exclusive */
104 private boolean isMountPoint = false;
105 private boolean isDirectory = false;
106 private boolean isFile = false;
107 private boolean isLink = false;
108
109 private boolean exists;
110 private long lastModified;
111 private long length;
112
113 private ACL.Entry acl;
114 private boolean validated = false;
115 private long dirHandle;
116 private int permissionsMask;
117 private int errno;
118
119 /**
120 * Creates a new <code>File</code> instance by converting the given
121 * pathname string into an abstract pathname and validating it against
122 * the file system. If the given string is an empty string, then the
123 * result is the empty abstract pathname; otherwise the abstract pathname
124 * is <code>validated</code> to represent a qualified file object.
125 *
126 * @param pathname A pathname string
127 * @throws NullPointerException
128 * If the <code>pathname</code> argument is <code>null</code>
129 * @throws AFSFileException
130 * If the user constructing this AFS file object is denied
131 * access to stat the file or simply a stat cannot be performed
132 * on the file. The reason code and message will be available
133 * from {@link org.openafs.jafs.AFSFileException#getErrorCode} and
134 * {@link org.openafs.jafs.AFSFileException#getMessage} respectively.
135 * <p> This exception <U>will not</U> be thrown if the file does not
136 * exist. Rather, the {@link #exists} attribute will be set to
137 * <code>false</code>.
138 * @see #validate()
139 */
140 public File(String pathname) throws AFSFileException
141 {
142 super(pathname);
143 path = getAbsolutePath();
144 validated = setAttributes();
145 if (!validated) throw new AFSFileException(errno);
146 }
147 /**
148 * Creates a new <code>File</code> instance by converting the given
149 * pathname string into an abstract pathname. If the given string is
150 * an empty string, then the result is the empty abstract pathname.
151 *
152 * <p> The abstract pathname will remain <B>abstract</B> unless the
153 * <code>validate</code> parameter is set to <code>true</code>. This
154 * means that the abstract pathname will <U>not</U> be <code>validated</code>
155 * and therefore the file object will not represent a qualified, attributed,
156 * AFS file resource. Rather, this constructor provides a method by which
157 * you can construct a non-validated <code>File</code> object (one that
158 * does not contain the file's complete status information).
159 *
160 * <p> This constructor is useful for creating file objects of file/path names
161 * that you know exist, however are unauthorized to <code>validate</code> (or
162 * <code>stat</code> - to obtain complete status information). For example,
163 * if you are permitted to <code>lookup</code> (see: {@link #canLookup}) the
164 * contents of a given directory yet <U>not</U> permitted to <code>read</code>
165 * (see: {@link #canRead}), then this constructor would enable you to render the
166 * contents of the directory without validating each entry.
167 *
168 * <p> <B>Please note:</B> this is the only constructor that does not throw an AFSFileException.
169 *
170 * @param pathname A pathname string
171 * @param validate A boolean flag to indicate if this abstract path
172 * should be validated.
173 * @throws NullPointerException
174 * If the <code>pathname</code> argument is <code>null</code>
175 * @see #File(String)
176 * @see #validate()
177 */
178 public File(String pathname, boolean validate)
179 {
180 super(pathname);
181 path = getAbsolutePath();
182 if (validate) validated = setAttributes();
183 }
184 /**
185 * Creates a new <code>File</code> instance from a parent pathname string
186 * and a child pathname string and validates it against the file system.
187 *
188 * <p> If <code>parent</code> is <code>null</code> then the new
189 * <code>File</code> instance is created as if by invoking the
190 * single-argument <code>File</code> constructor on the given
191 * <code>filename</code> string (child pathname).
192 *
193 * <p> Otherwise the <code>parent</code> pathname string is taken to denote
194 * a directory, and the <code>filename</code> string is taken to
195 * denote either a directory or a file. The directory or file will then be
196 * <code>validated</code> to represent a qualified file object.
197 *
198 * @param parent The parent pathname string
199 * @param filename This file's pathname string (child of specified parent)
200 * @throws NullPointerException
201 * If <code>child</code> is <code>null</code>
202 * @throws AFSFileException
203 * If the user constructing this AFS file object is denied
204 * access to stat the file or simply a stat cannot be performed
205 * on the file. The reason code and message will be available
206 * from {@link org.openafs.jafs.AFSFileException#getErrorCode} and
207 * {@link org.openafs.jafs.AFSFileException#getMessage} respectively.
208 * <p> This exception <U>will not</U> be thrown if the file does not
209 * exist. Rather, the {@link #exists} attribute will be set to
210 * <code>false</code>.
211 * @see #validate()
212 */
213 public File(String parent, String filename) throws AFSFileException
214 {
215 super(parent, filename);
216 path = getAbsolutePath();
217 validated = setAttributes();
218 if (!validated) throw new AFSFileException(errno);
219 }
220 /**
221 * Creates a new <code>File</code> instance from a parent pathname string
222 * and a child pathname string.
223 *
224 * <p> If <code>parent</code> is <code>null</code> then the new
225 * <code>File</code> instance is created as if by invoking the
226 * single-argument <code>File</code> constructor on the given
227 * <code>filename</code> string (child pathname).
228 *
229 * <p> Otherwise the <code>parent</code> pathname string is taken to denote
230 * a directory, and the <code>filename</code> string is taken to
231 * denote either a directory or a file.
232 *
233 * <p> The abstract pathname will remain <B>abstract</B> unless the
234 * <code>validate</code> parameter is set to <code>true</code>. This
235 * means that the abstract pathname will <U>not</U> be <code>validated</code>
236 * and therefore the file object will not represent a qualified, attributed,
237 * AFS file resource. Rather, this constructor provides a method by which
238 * you can construct a non-validated <code>File</code> object (one that
239 * does not contain the file's complete status information).
240 *
241 * <p> This constructor is useful for creating file objects of file/path names
242 * that you know exist, however are unauthorized to <code>validate</code> (or
243 * <code>stat</code> - to obtain complete status information). For example,
244 * if you are permitted to <code>lookup</code> (see: {@link #canLookup}) the
245 * contents of a given directory yet <U>not</U> permitted to <code>read</code>
246 * (see: {@link #canRead}), then this constructor would enable you to render the
247 * contents of the directory without validating each entry.
248 *
249 * @param parent The parent pathname string
250 * @param filename This file's pathname string (child of specified parent)
251 * @param validate A boolean flag to indicate if this abstract path
252 * should be validated.
253 * @throws NullPointerException
254 * If <code>child</code> is <code>null</code>
255 * @throws AFSFileException
256 * If the user constructing this AFS file object is denied
257 * access to stat the file or simply a stat cannot be performed
258 * on the file. The reason code and message will be available
259 * from {@link org.openafs.jafs.AFSFileException#getErrorCode} and
260 * {@link org.openafs.jafs.AFSFileException#getMessage} respectively.
261 * <p> This exception <U>will not</U> be thrown if the file does not
262 * exist. Rather, the {@link #exists} attribute will be set to
263 * <code>false</code>.
264 * @see #File(String, String)
265 * @see #validate()
266 */
267 public File(String parent, String filename, boolean validate) throws AFSFileException
268 {
269 super(parent, filename);
270 path = getAbsolutePath();
271 if (validate) {
272 validated = setAttributes();
273 if (!validated) throw new AFSFileException(errno);
274 }
275 }
276 /**
277 * Creates a new <code>File</code> instance from a parent abstract
278 * pathname and a child pathname string and validates it against the file system.
279 *
280 * <p> If <code>parent</code> is <code>null</code> then the new
281 * <code>File</code> instance is created as if by invoking the
282 * single-argument <code>File</code> constructor on the given
283 * <code>filename</code> string (child pathname).
284 *
285 * <p> Otherwise the <code>parent</code> abstract pathname is taken to
286 * denote a directory, and the <code>filename</code> string is taken
287 * to denote either a directory or a file. The directory or file will then be
288 * <code>validated</code> to represent a qualified file object.
289 *
290 * @param parent The parent abstract pathname
291 * @param filename This file's pathname string (child of specified parent)
292 * @param validate A boolean flag to indicate if this abstract path
293 * should be validated.
294 * @throws NullPointerException
295 * If <code>child</code> is <code>null</code>
296 * @throws AFSFileException
297 * If the user constructing this AFS file object is denied
298 * access to stat the file or simply a stat cannot be performed
299 * on the file. The reason code and message will be available
300 * from {@link org.openafs.jafs.AFSFileException#getErrorCode} and
301 * {@link org.openafs.jafs.AFSFileException#getMessage} respectively.
302 * <p> This exception <U>will not</U> be thrown if the file does not
303 * exist. Rather, the {@link #exists} attribute will be set to
304 * <code>false</code>.
305 * @see #validate()
306 */
307 public File(File parent, String filename) throws AFSFileException
308 {
309 super(parent, filename);
310 path = getAbsolutePath();
311 validated = setAttributes();
312 if (!validated) throw new AFSFileException(errno);
313 }
314 /**
315 * Creates a new <code>File</code> instance from a parent abstract
316 * pathname and a child pathname string.
317 *
318 * <p> If <code>parent</code> is <code>null</code> then the new
319 * <code>File</code> instance is created as if by invoking the
320 * single-argument <code>File</code> constructor on the given
321 * <code>filename</code> string (child pathname).
322 *
323 * <p> Otherwise the <code>parent</code> abstract pathname is taken to
324 * denote a directory, and the <code>filename</code> string is taken
325 * to denote either a directory or a file.
326 *
327 * <p> The abstract pathname will remain <B>abstract</B> unless the
328 * <code>validate</code> parameter is set to <code>true</code>. This
329 * means that the abstract pathname will <U>not</U> be <code>validated</code>
330 * and therefore the file object will not represent a qualified, attributed,
331 * AFS file resource. Rather, this constructor provides a method by which
332 * you can construct a non-validated <code>File</code> object (one that
333 * does not contain the file's complete status information).
334 *
335 * <p> This constructor is useful for creating file objects of file/path names
336 * that you know exist, however are unauthorized to <code>validate</code> (or
337 * <code>stat</code> - to obtain complete status information). For example,
338 * if you are permitted to <code>lookup</code> (see: {@link #canLookup}) the
339 * contents of a given directory yet <U>not</U> permitted to <code>read</code>
340 * (see: {@link #canRead}), then this constructor would enable you to render the
341 * contents of the directory without validating each entry.
342 *
343 * @param parent The parent abstract pathname
344 * @param filename This file's pathname string (child of specified parent)
345 * @param validate A boolean flag to indicate if this abstract path
346 * should be validated.
347 * @throws NullPointerException
348 * If <code>child</code> is <code>null</code>
349 * @throws AFSFileException
350 * If the user constructing this AFS file object is denied
351 * access to stat the file or simply a stat cannot be performed
352 * on the file. The reason code and message will be available
353 * from {@link org.openafs.jafs.AFSFileException#getErrorCode} and
354 * {@link org.openafs.jafs.AFSFileException#getMessage} respectively.
355 * <p> This exception <U>will not</U> be thrown if the file does not
356 * exist. Rather, the {@link #exists} attribute will be set to
357 * <code>false</code>.
358 * @see #validate()
359 * @see #File(File, String)
360 */
361 public File(File parent, String filename, boolean validate) throws AFSFileException
362 {
363 super(parent, filename);
364 path = getAbsolutePath();
365 if (validate) {
366 validated = setAttributes();
367 if (!validated) throw new AFSFileException(errno);
368 }
369 }
370
371 /*****************************************************************************/
372
373 /**
374 * Validates this abstract pathname as an attributed AFS file object.
375 * This method will, if authorized, perform a <code>stat</code> on the
376 * actual AFS file and update its respective field members; defining
377 * this file object's attributes.
378 *
379 * @throws AFSSecurityException
380 * If an AFS exception occurs while attempting to stat and set this
381 * AFS file object's attributes.
382 */
383 public void validate() throws AFSSecurityException
384 {
385 validated = setAttributes();
386 if (!validated) throw new AFSSecurityException(errno);
387 }
388 /**
389 * Tests whether the file denoted by this abstract pathname has
390 * been validated.
391 *
392 * <P> Validation is always attempted upon construction of the file object,
393 * therefore if this method returns false, then you are not permitted to
394 * <code>validate</code> this file and consequently all attribute accessors
395 * will be invalid.
396 *
397 * <P> This method should return <code>true</code> even if this abstract
398 * pathname does not exist. If this is abstract pathname does not exist then
399 * the <code>{@link #exists}</code> method should return false, however this
400 * implies that the attribute accessors are valid and accurate; thus implying
401 * successful validation.
402 *
403 * <P> This method is useful before calling any of the attribute accessors
404 * to ensure a valid response.
405 *
406 * @return <code>true</code> if and only if the file denoted by this
407 * abstract pathname has been validated during or after object construction;
408 * <code>false</code> otherwise
409 */
410 public boolean isValidated()
411 {
412 return validated;
413 }
414 /**
415 * Refreshes this AFS file object by updating its attributes.
416 * This method currently provides the same functionality as
417 * {@link #validate}.
418 *
419 * @throws AFSSecurityException
420 * If an AFS exception occurs while attempting to stat and update this
421 * AFS file object's attributes.
422 * @see #validate()
423 */
424 public void refresh() throws AFSSecurityException
425 {
426 validate();
427 }
428 /*-------------------------------------------------------------------------*/
429 /**
430 * Tests whether the file denoted by this abstract pathname is a
431 * directory.
432 *
433 * @return <code>true</code> if and only if the file denoted by this
434 * abstract pathname exists <em>and</em> is a directory;
435 * <code>false</code> otherwise
436 */
437 public boolean isDirectory()
438 {
439 return (isDirectory || isMountPoint) ? true : false;
440 }
441 /**
442 * Tests whether the file denoted by this abstract pathname is a normal
443 * file. A file is <em>normal</em> if it is not a directory and, in
444 * addition, satisfies other system-dependent criteria. Any non-directory
445 * file created by a Java application is guaranteed to be a normal file.
446 *
447 * @return <code>true</code> if and only if the file denoted by this
448 * abstract pathname exists <em>and</em> is a normal file;
449 * <code>false</code> otherwise
450 */
451 public boolean isFile()
452 {
453 return isFile;
454 }
455 /**
456 * Tests whether the file denoted by this abstract pathname is an
457 * AFS Volume Mount Point.
458 *
459 * @return <code>true</code> if and only if the file denoted by this
460 * abstract pathname exists <em>and</em> is a mount point;
461 * <code>false</code> otherwise
462 */
463 public boolean isMountPoint()
464 {
465 return isMountPoint;
466 }
467 /**
468 * Tests whether the file denoted by this abstract pathname is a
469 * symbolic-link.
470 *
471 * @return <code>true</code> if and only if the file denoted by this
472 * abstract pathname exists <em>and</em> is a symbolic-link;
473 * <code>false</code> otherwise
474 */
475 public boolean isLink()
476 {
477 return isLink;
478 }
479 /*-------------------------------------------------------------------------*/
480 /**
481 * Tests whether the file denoted by this abstract pathname exists.
482 *
483 * @return <code>true</code> if and only if the file denoted by this
484 * abstract pathname exists; <code>false</code> otherwise
485 */
486 public boolean exists()
487 {
488 return exists;
489 }
490 /**
491 * Returns the time that the file denoted by this abstract pathname was
492 * last modified.
493 *
494 * @return A <code>long</code> value representing the time the file was
495 * last modified, measured in milliseconds since the epoch
496 * (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
497 * file does not exist or if an I/O error occurs
498 */
499 public long lastModified()
500 {
501 return lastModified;
502 }
503 /**
504 * Returns the length of the file denoted by this abstract pathname.
505 *
506 * @return The length, in bytes, of the file denoted by this abstract
507 * pathname, or <code>0L</code> if the file does not exist
508 */
509 public long length()
510 {
511 return length;
512 }
513 /**
514 * Returns an abstract pathname string that represents the target resource of
515 * of this file, if it is a symbolic-link.
516 *
517 * <p> If this abstract pathname <B>does not</B> denote a symbolic-link, then this
518 * method returns <code>null</code>. Otherwise a string is
519 * returned that represents the target resource of this symbolic-link.
520 *
521 * @return A string representation of this symbolic-link's target resource.
522 * @see #isLink()
523 */
524 public String getTarget()
525 {
526 return target;
527 }
528 /**
529 * Returns an array of strings naming the files and directories in the
530 * directory denoted by this abstract pathname.
531 *
532 * <p> If this abstract pathname does not denote a directory, then this
533 * method returns <code>null</code>. Otherwise an array of strings is
534 * returned, one for each file or directory in the directory. Names
535 * denoting the directory itself and the directory's parent directory are
536 * not included in the result. Each string is a file name rather than a
537 * complete path.
538 *
539 * <p> There is no guarantee that the name strings in the resulting array
540 * will appear in any specific order; they are not, in particular,
541 * guaranteed to appear in alphabetical order.
542 *
543 * @return An array of strings naming the files and directories in the
544 * directory denoted by this abstract pathname. The array will be
545 * empty if the directory is empty. Returns <code>null</code> if
546 * this abstract pathname does not denote a directory, or if an
547 * I/O error occurs.
548 */
549 public String[] list()
550 {
551 try {
552 if (isFile()) {
553 errno = ErrorTable.NOT_DIRECTORY;
554 return null;
555 }
556 ArrayList buffer = new ArrayList();
557 dirHandle = listNative(buffer);
558 if (dirHandle == 0) {
559 return null;
560 } else {
561 return (String[])buffer.toArray(new String[0]);
562 }
563 } catch (Exception e) {
564 System.out.println(e);
565 return null;
566 }
567 }
568 /**
569 * Returns an ArrayList object containing strings naming the files and
570 * directories in the directory denoted by this abstract pathname.
571 *
572 * <p> If this abstract pathname does not denote a directory, then this
573 * method returns <code>null</code>. Otherwise an array of strings is
574 * returned, one for each file or directory in the directory. Names
575 * denoting the directory itself and the directory's parent directory are
576 * not included in the result. Each string is a file name rather than a
577 * complete path.
578 *
579 * <p> There is no guarantee that the name strings in the resulting array
580 * will appear in any specific order; they are not, in particular,
581 * guaranteed to appear in alphabetical order.
582 *
583 * @return An array of strings naming the files and directories in the
584 * directory denoted by this abstract pathname. The array will be
585 * empty if the directory is empty. Returns <code>null</code> if
586 * this abstract pathname does not denote a directory, or if an
587 * I/O error occurs.
588 * @throws AFSSecurityException
589 * If you are not authorized to list the contents of this directory
590 * @throws AFSFileException
591 * If this file object is not a <code>mount point</code>, <code>link
592 * </code>, or <code>directory</code> <B>or</B> an unexpected AFS
593 * error occurs.
594 * @see #list()
595 */
596 public ArrayList listArray() throws AFSFileException
597 {
598 try {
599 if (isFile()) throw new AFSFileException(ErrorTable.NOT_DIRECTORY);
600 ArrayList buffer = new ArrayList();
601 dirHandle = listNative(buffer);
602 if (dirHandle == 0) {
603 if (errno == ErrorTable.PERMISSION_DENIED) {
604 throw new AFSSecurityException(errno);
605 } else {
606 throw new AFSFileException(errno);
607 }
608 } else {
609 return buffer;
610 }
611 } catch (Exception e) {
612 System.out.println(e);
613 throw new AFSFileException(errno);
614 }
615 }
616 /*-------------------------------------------------------------------------*/
617 /**
618 * Deletes the file or directory denoted by this abstract pathname. If
619 * this pathname denotes a directory, then the directory must be empty in
620 * order to be deleted.
621 *
622 * @return <code>true</code> if and only if the file or directory is
623 * successfully deleted; <code>false</code> otherwise
624 */
625 public boolean delete()
626 {
627 try {
628 if(this.isDirectory()) {
629 return this.rmdir();
630 } else if(this.isFile() || this.isLink()) {
631 return this.rmfile();
632 }
633 return false;
634 } catch (Exception e) {
635 System.out.println(e);
636 return false;
637 }
638 }
639 /**
640 * Copies the file denoted by this abstract pathname to the destination
641 * file provided. Then checks the newly copied file's size to
642 * test for file size consistency.
643 *
644 * @param dest The new abstract pathname for the named file
645 *
646 * @return <code>true</code> if and only if the file that was copied
647 * reports the same file size (length) as that of this file;
648 * <code>false</code> otherwise
649 *
650 * @throws AFSFileException
651 * If an I/O or AFS exception is encountered while copying the file.
652 */
653 public boolean copyTo(File dest) throws AFSFileException
654 {
655 FileInputStream fis = new FileInputStream(this);
656 FileOutputStream fos = new FileOutputStream(dest);
657 byte[] buf = new byte[1024];
658 int i = 0;
659 while((i=fis.read(buf))!=-1) {
660 fos.write(buf, 0, i);
661 }
662 fis.close();
663 fos.close();
664 dest.validate();
665 return (dest.length() == this.length());
666 }
667 /*-------------------------------------------------------------------------*/
668 /**
669 * Returns the permissions mask of the ACL for this object relative to the user accessing it.
670 *
671 * @return the permissions mask of this object based upon the current user.
672 * @see org.openafs.jafs.ACL.Entry#getPermissionsMask()
673 */
674 public int getPermissionsMask()
675 {
676 return getRights();
677 }
678 /**
679 * Tests whether the user can administer the ACL (see: {@link org.openafs.jafs.ACL}
680 * of the directory denoted by this abstract pathname.
681 *
682 * @see org.openafs.jafs.ACL.Entry#canAdmin
683 * @return <code>true</code> if and only if the directory specified by this
684 * abstract pathname exists <em>and</em> can be administered by the
685 * current user; <code>false</code> otherwise
686 */
687 public boolean canAdmin()
688 {
689 if (acl == null) acl = new ACL.Entry(getRights());
690 return acl.canAdmin();
691 }
692 /**
693 * Tests whether the current user can delete the files or subdirectories of
694 * the directory denoted by this abstract pathname.
695 *
696 * @see org.openafs.jafs.ACL.Entry#canDelete
697 * @return <code>true</code> if and only if the directory specified by this
698 * abstract pathname exists <em>and</em> permits deletion of its files
699 * and subdirectories by the current user; <code>false</code> otherwise
700 */
701 public boolean canDelete()
702 {
703 if (acl == null) acl = new ACL.Entry(getRights());
704 return acl.canDelete();
705 }
706 /**
707 * Tests whether the current user can insert a file into the directory
708 * denoted by this abstract pathname.
709 *
710 * @see org.openafs.jafs.ACL.Entry#canInsert
711 * @return <code>true</code> if and only if the directory specified by this
712 * abstract pathname exists <em>and</em> a file can be inserted by the
713 * current user; <code>false</code> otherwise
714 */
715 public boolean canInsert()
716 {
717 if (acl == null) acl = new ACL.Entry(getRights());
718 return acl.canInsert();
719 }
720 /**
721 * Tests whether the current user can lock the file denoted by this
722 * abstract pathname.
723 *
724 * @see org.openafs.jafs.ACL.Entry#canLock
725 * @return <code>true</code> if and only if the file specified by this
726 * abstract pathname exists <em>and</em> can be locked by the
727 * current user; <code>false</code> otherwise
728 */
729 public boolean canLock()
730 {
731 if (acl == null) acl = new ACL.Entry(getRights());
732 return acl.canLock();
733 }
734 /**
735 * Tests whether the current user can lookup the contents of the directory
736 * denoted by this abstract pathname.
737 *
738 * @see org.openafs.jafs.ACL.Entry#canLookup
739 * @return <code>true</code> if and only if the directory specified by this
740 * abstract pathname exists <em>and</em> its contents can be listed by the
741 * current user; <code>false</code> otherwise
742 */
743 public boolean canLookup()
744 {
745 if (acl == null) acl = new ACL.Entry(getRights());
746 return acl.canLookup();
747 }
748 /**
749 * Tests whether the current user can read the file denoted by this
750 * abstract pathname.
751 *
752 * @see org.openafs.jafs.ACL.Entry#canRead
753 * @return <code>true</code> if and only if the file specified by this
754 * abstract pathname exists <em>and</em> can be read by the
755 * current user; <code>false</code> otherwise
756 */
757 public boolean canRead()
758 {
759 if (acl == null) acl = new ACL.Entry(getRights());
760 return acl.canRead();
761 }
762 /**
763 * Tests whether the current user can modify to the file denoted by this
764 * abstract pathname.
765 *
766 * @see org.openafs.jafs.ACL.Entry#canWrite
767 * @return <code>true</code> if and only if the file system actually
768 * contains a file denoted by this abstract pathname <em>and</em>
769 * the current user is allowed to write to the file;
770 * <code>false</code> otherwise.
771 */
772 public boolean canWrite()
773 {
774 if (acl == null) acl = new ACL.Entry(getRights());
775 return acl.canWrite();
776 }
777 /*-------------------------------------------------------------------------*/
778 /**
779 * Closes the directory denoted by this abstract pathname.
780 *
781 * @return <code>true</code> if and only if the directory is
782 * successfully closed; <code>false</code> otherwise
783 */
784 public boolean close()
785 {
786 if (dirHandle == 0) {
787 return false;
788 }
789 return closeDir(dirHandle);
790 }
791 /*-------------------------------------------------------------------------*/
792 /**
793 * Returns the AFS specific error number (code). This code can be interpreted
794 * by use of <code>{@link org.openafs.jafs.ErrorTable}</code> static class method
795 * <code>{@link org.openafs.jafs.ErrorTable#getMessage}</code>
796 *
797 * @return the AFS error code (number) associated with the last action performed
798 * on this object.
799 * @see org.openafs.jafs.ErrorTable#getMessage(int)
800 */
801 public int getErrorCode()
802 {
803 return errno;
804 }
805 /**
806 * Returns the AFS error message string defined by the <code>{@link org.openafs.jafs.ErrorTable}</code>
807 * class.
808 *
809 * @return the AFS error message string associated with the last action performed
810 * on this object.
811 * @see org.openafs.jafs.ErrorTable#getMessage(int)
812 */
813 public String getErrorMessage()
814 {
815 return ErrorTable.getMessage(errno);
816 }
817
818 /////////////// custom override methods ////////////////////
819
820 /**
821 * Compares two File objects relative to their filenames and <B>does not</B>
822 * compare their respective absolute paths. Alphabetic case is significant in
823 * comparing filenames.
824 *
825 * @param file The File object to be compared to this file's filename
826 *
827 * @return Zero if the argument is equal to this file's filename, a
828 * value less than zero if this file's filename is
829 * lexicographically less than the argument, or a value greater
830 * than zero if this file's filename is lexicographically
831 * greater than the argument
832 *
833 * @since JDK1.2
834 */
835 public int compareTo(File file) {
836 return this.getName().compareTo(file.getName());
837 }
838 /**
839 * Compares this file to another File object. If the other object
840 * is an abstract pathname, then this function behaves like <code>{@link
841 * #compareTo(File)}</code>. Otherwise, it throws a
842 * <code>ClassCastException</code>, since File objects can only be
843 * compared to File objects.
844 *
845 * @param o The <code>Object</code> to be compared to this abstract pathname
846 *
847 * @return If the argument is an File object, returns zero
848 * if the argument is equal to this file's filename, a value
849 * less than zero if this file's filename is lexicographically
850 * less than the argument, or a value greater than zero if this
851 * file's filename is lexicographically greater than the
852 * argument
853 *
854 * @throws <code>ClassCastException</code> if the argument is not an
855 * File object
856 *
857 * @see java.lang.Comparable
858 * @since JDK1.2
859 */
860 public int compareTo(Object o) throws ClassCastException
861 {
862 File file = (File)o;
863 return compareTo(file);
864 }
865
866 /////////////// public native methods ////////////////////
867
868 /**
869 * Creates the directory named by this abstract pathname.
870 *
871 * @return <code>true</code> if and only if the directory was
872 * created; <code>false</code> otherwise
873 */
874 public native boolean mkdir();
875 /**
876 * Renames the file denoted by this abstract pathname.
877 *
878 * @param dest The new abstract pathname for the named file
879 *
880 * @return <code>true</code> if and only if the renaming succeeded;
881 * <code>false</code> otherwise
882 *
883 * @throws NullPointerException
884 * If parameter <code>dest</code> is <code>null</code>
885 */
886 public native boolean renameTo(File dest);
887 /**
888 * Performs a file <code>stat</code> on the actual AFS file and populates
889 * this object's respective field members with the appropriate values.
890 * method will, if authorized, perform a <code>stat</code> on the
891 * actual AFS file and update its respective field members; defining
892 * this file object's attributes.
893 *
894 * <P><B>This method should not be used directly for refreshing or validating
895 * this AFS file object. Please use {@link #validate} instead.</B>
896 *
897 * @return <code>true</code> if and only if the current user is allowed to stat the file;
898 * <code>false</code> otherwise.
899 * @see #validate()
900 */
901 public native boolean setAttributes() throws AFSSecurityException;
902
903 /////////////// private native methods ////////////////////
904
905 /**
906 * List the contents of this directory.
907 *
908 * @return the directory handle
909 */
910 private native long listNative(ArrayList buffer) throws AFSSecurityException;
911 /**
912 * Close the currently open directory using a previously obtained handle.
913 *
914 * @return true if the directory closes without error
915 */
916 private native boolean closeDir(long dp) throws AFSSecurityException;
917 /**
918 * Removes/deletes the current directory.
919 *
920 * @return true if the directory is removed without error
921 */
922 private native boolean rmdir() throws AFSSecurityException;
923 /**
924 * Removes/deletes the current file.
925 *
926 * @return true if the file is removed without error
927 */
928 private native boolean rmfile() throws AFSSecurityException;
929 /**
930 * Returns the permission/ACL mask for this directory
931 *
932 * @return permission/ACL mask
933 */
934 private native int getRights() throws AFSSecurityException;
935 /*-------------------------------------------------------------------------*/
936}
937
938
939
940
941
942