Commit | Line | Data |
---|---|---|
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 | ||
24 | package org.openafs.jafs; | |
25 | ||
26 | import java.io.IOException; | |
27 | import 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 | */ | |
97 | public 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 |