001: /*
002: * @(#)FileIO.java 1.12 05/03/12
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.io;
029:
030: import java.io.InputStream;
031: import java.io.OutputStream;
032: import java.io.IOException;
033: import java.io.Serializable;
034:
035: /**
036: * Instances of this class represent the name of a file or directory
037: * on the host file system. A file is specified by a pathname, which
038: * can either be an absolute pathname or a pathname relative to the
039: * current working directory. The pathname must follow the naming
040: * conventions of the host platform.
041: * <p>
042: * The <code>File</code> class is intended to provide an abstraction
043: * that deals with most of the machine dependent complexities of
044: * files and pathnames in a machine-independent fashion.
045: * <p>
046: * Note that whenever a filename or path is used it is
047: * assumed that the host's file naming conventions are used.
048: *
049: * @version 1.10, 02/08/19
050: * @author Saul Wold
051: * @since JDK1.0
052: */
053: public abstract class FileIO implements Serializable {
054: /**
055: * The path of the file. The host's file separator is used.
056: */
057: protected String path;
058: /**
059: * The system-dependent path separator character. This field is
060: * initialized to contain the value of <code>File.separator</code>.
061: *
062: * @see java.io.File#separator(java.lang.String)
063: * @since JDK1.0
064: */
065: // Fix for 6292536 and 6292996.
066: public static final String separator = java.io.File.separator;
067: /**
068: * The system-dependent path separator string. This field is
069: * initialized to contain the first character of the value of
070: * <code>File.separator</code>. This character
071: * separates the directory and file components in a filename.
072: *
073: * @see java.io.File#separator(java.lang.String)
074: * @since JDK1.0
075: */
076: public static final char separatorChar = separator.charAt(0);
077: /**
078: * The system-dependent path separator string. This field is
079: * initialized to contain the value of <code>File.pathSeparator</code>.
080: *
081: * @see java.io.File#pathSeparator(java.lang.String)
082: * @since JDK1.0
083: */
084: // Fix for 6292536 and 6292996.
085: public static final String pathSeparator = java.io.File.pathSeparator;
086: /**
087: * The system-dependent path separator character. This field is
088: * initialized to contain the first character of
089: * <code>File.pathSeparator</code>. This character is
090: * often used to separate filenames in a sequence of files given as a
091: * "path list".
092: *
093: * @see java.io.File#pathSeparator(java.lang.String)
094: * @since JDK1.0
095: */
096: public static final char pathSeparatorChar = pathSeparator
097: .charAt(0);
098:
099: public FileIO() {
100: }
101:
102: /**
103: * Creates a <code>File</code> instance that represents the file
104: * whose pathname is the given path argument.
105: *
106: * @param path the file pathname.
107: * @exception NullPointerException if the file path is equal to
108: * <code>null</code>.
109: * @see java.io.File#getPath()
110: * @since JDK1.0
111: */
112: protected FileIO(String path) {
113: if (path == null) {
114: throw new NullPointerException();
115: }
116: this .path = path;
117: }
118:
119: /**
120: * Creates a <code>File</code> instance whose pathname is the
121: * pathname of the specified directory, followed by the separator
122: * character, followed by the <code>name</code> argument.
123: *
124: * @param path the directory pathname.
125: * @param name the file pathname.
126: * @see java.io.File#getPath()
127: * @see java.io.File#separator
128: * @since JDK1.0
129: */
130: protected FileIO(String path, String name) {
131: if (name == null) {
132: /* raise exception, per Java Language Spec
133: * 22.24.6 & 22.24.7
134: */
135: throw new NullPointerException();
136: }
137: if (path != null) {
138: if (path.endsWith(separator)) {
139: this .path = path + name;
140: } else {
141: this .path = path + separator + name;
142: }
143: } else {
144: this .path = name;
145: }
146: }
147:
148: /**
149: * Creates a <code>File</code> instance that represents the file
150: * with the specified name in the specified directory.
151: * <p>
152: * If the directory argument is <code>null</code>, the resulting
153: * <code>File</code> instance represents a file in the
154: * (system-dependent) current directory whose pathname is the
155: * <code>name</code> argument. Otherwise, the <code>File</code>
156: * instance represents a file whose pathname is the pathname of the
157: * directory, followed by the separator character, followed by the
158: * <code>name</code> argument.
159: *
160: * @param dir the directory.
161: * @param name the file pathname.
162: * @see java.io.File#getPath()
163: * @see java.io.File#separator
164: * @since JDK1.0
165: */
166: protected FileIO(FileIO dir, String name) {
167: this (dir.getPath(), name);
168: }
169:
170: public abstract InputStream getInputStream() throws IOException;
171:
172: public abstract OutputStream getOutputStream() throws IOException;
173:
174: /**
175: * Returns the name of the file represented by this object. The name
176: * is everything in the pathame after the last occurrence of the
177: * separator character.
178: *
179: * @return the name of the file (without any directory components)
180: * represented by this <code>File</code> object.
181: * @see java.io.File#getPath()
182: * @see java.io.File#separator
183: * @since JDK1.0
184: */
185: public String getName() {
186: int index = path.lastIndexOf(separatorChar);
187: return (index < 0) ? path : path.substring(index + 1);
188: }
189:
190: /**
191: * Returns the pathname of the file represented by this object.
192: *
193: * @return the pathname represented by this <code>File</code> object.
194: * @since JDK1.0
195: */
196: public String getPath() {
197: return path;
198: }
199:
200: /**
201: * Returns the absolute pathname of the file represented by this object.
202: * If this object represents an absolute pathname, then return the
203: * pathname. Otherwise, return a pathname that is a concatenation of
204: * the current user directory, the separator character, and the
205: * pathname of this file object.
206: * <p>
207: * The system property <code>user.dir</code> contains the current
208: * user directory.
209: *
210: * @return a system-dependent absolute pathname for this <code>File</code>.
211: * @see java.io.File#getPath()
212: * @see java.io.File#isAbsolute()
213: * @see java.lang.System#getProperty(java.lang.String)
214: * @since JDK1.0
215: */
216: public String getAbsolutePath() {
217: if (isAbsolute())
218: return path;
219: SecurityManager security = System.getSecurityManager();
220: if (security != null) {
221: security.checkPropertyAccess("user.dir");
222: }
223: return System.getProperty("user.dir") + separator + path;
224: }
225:
226: /**
227: * Returns the canonical form of this <code>File</code> object's pathname.
228: * The precise definition of canonical form is system-dependent, but it
229: * usually specifies an absolute pathname in which all relative references
230: * and references to the current user directory have been completely
231: * resolved. The canonical form of a pathname of a nonexistent file may
232: * not be defined.
233: *
234: * @exception IOException If an I/O error occurs, which is possible because
235: * the construction of the canonical path may require filesystem queries.
236: *
237: * @since JDK1.1
238: */
239: public String getCanonicalPath() throws IOException {
240: if (isAbsolute())
241: return canonPath(path);
242: SecurityManager security = System.getSecurityManager();
243: if (security != null) {
244: security.checkPropertyAccess("user.dir");
245: }
246: return canonPath(System.getProperty("user.dir") + separator
247: + path);
248: }
249:
250: /**
251: * Returns the parent part of the pathname of this <code>File</code>
252: * object, or <code>null</code> if the name has no parent part. The parent
253: * part is generally everything leading up to the last occurrence of the
254: * separator character, although the precise definition is system
255: * dependent. On UNIX, for example, the parent part of
256: * <code>"/usr/lib"</code> is <code>"/usr"</code>, whose parent part is
257: * <code>"/"</code>, which in turn has no parent. On Windows platforms,
258: * the parent part of <code>"c:\java"</code> is <code>"c:\"</code>, which
259: * in turn has no parent.
260: *
261: * @see java.io.File#getPath()
262: * @see java.io.File#getCanonicalPath()
263: * @see java.io.File#separator
264: * @since JDK1.0
265: */
266: public String getParent() {
267: /* This is correct for Unix and Win32; other platforms may require a
268: different algorithm */
269: int index = path.lastIndexOf(separatorChar);
270: if (index < 0)
271: return null;
272: if (!isAbsolute() || (path.indexOf(separatorChar) != index))
273: return path.substring(0, index);
274: if (index < path.length() - 1)
275: return path.substring(0, index + 1);
276: return null;
277: }
278:
279: abstract String canonPath(String path) throws IOException;
280:
281: /**
282: * Tests if this <code>File</code> exists.
283: *
284: * @return <code>true</code> if the file specified by this object
285: * exists; <code>false</code> otherwise.
286: * @exception SecurityException if a security manager exists, its
287: * <code>checkRead</code> method is called with the pathname
288: * of this <code>File</code> to see if the application is
289: * allowed read access to the file.
290: * @see java.io.File#getPath()
291: * @see java.lang.SecurityManager#checkRead(java.lang.String)
292: * @since JDK1.0
293: */
294: public abstract boolean exists();
295:
296: /**
297: * Tests if the application can write to this file.
298: *
299: * @return <code>true</code> if the application is allowed to write to
300: * a file whose name is specified by this object;
301: * <code>false</code> otherwise.
302: * @exception SecurityException if a security manager exists, its
303: * <code>checkWrite</code> method is called with the pathname
304: * of this <code>File</code> to see if the application is
305: * allowed write access to the file.
306: * @see java.io.File#getPath()
307: * @see java.lang.SecurityManager#checkWrite(java.lang.String)
308: * @since JDK1.0
309: */
310: public abstract boolean canWrite();
311:
312: /**
313: * Tests if the application can read from the specified file.
314: *
315: * @return <code>true</code> if the file specified by this object exists
316: * and the application can read the file;
317: * <code>false</code> otherwise.
318: * @exception SecurityException if a security manager exists, its
319: * <code>checkRead</code> method is called with the pathname
320: * of this <code>File</code> to see if the application is
321: * allowed read access to the file.
322: * @see java.io.File#getPath()
323: * @see java.lang.SecurityManager#checkRead(java.lang.String)
324: * @since JDK1.0
325: */
326: public abstract boolean canRead();
327:
328: /**
329: * Tests if the file represented by this <code>File</code>
330: * object is a "normal" file.
331: * <p>
332: * A file is "normal" if it is not a directory and, in
333: * addition, satisfies other system-dependent criteria. Any
334: * non-directory file created by a Java application is guaranteed to
335: * be a normal file.
336: *
337: * @return <code>true</code> if the file specified by this object
338: * exists and is a "normal" file; <code>false</code> otherwise.
339: * @exception SecurityException If a security manager exists, its
340: * <code>checkRead</code> method is called with the pathname
341: * of this <code>File</code> to see if the application is
342: * allowed read access to the file.
343: * @see java.io.File#getPath()
344: * @see java.lang.SecurityManager#checkRead(java.lang.String)
345: * @since JDK1.0
346: */
347: public abstract boolean isFile();
348:
349: /**
350: * Tests if the file represented by this <code>File</code>
351: * object is a directory.
352: *
353: * @return <code>true</code> if this <code>File</code> exists and is a
354: * directory; <code>false</code> otherwise.
355: * @exception SecurityException if a security manager exists, its
356: * <code>checkRead</code> method is called with the pathname
357: * of this <code>File</code> to see if the application is
358: * allowed read access to the file.
359: * @see java.io.File#getPath()
360: * @see java.lang.SecurityManager#checkRead(java.lang.String)
361: * @since JDK1.0
362: */
363: public abstract boolean isDirectory();
364:
365: /**
366: * Tests if the file represented by this <code>File</code> object is an
367: * absolute pathname. The definition of an absolute pathname is system
368: * dependent. For example, on UNIX, a pathname is absolute if its
369: * first character is the separator character. On Windows platforms,
370: * a pathname is absolute if its first character is an ASCII '\' or
371: * '/', or if it begins with a letter followed by a colon.
372: *
373: * @return <code>true</code> if the pathname indicated by the
374: * <code>File</code> object is an absolute pathname;
375: * <code>false</code> otherwise.
376: * @see java.io.File#getPath()
377: * @see java.io.File#separator
378: * @since JDK1.0
379: */
380: public abstract boolean isAbsolute();
381:
382: /**
383: * Returns the time that the file represented by this
384: * <code>File</code> object was last modified.
385: * <p>
386: * The return value is system dependent and should only be used to
387: * compare with other values returned by last modified. It should not
388: * be interpreted as an absolute time.
389: *
390: * @return the time the file specified by this object was last modified,
391: * or <code>0L</code> if the specified file does not exist.
392: * @exception SecurityException if a security manager exists, its
393: * <code>checkRead</code> method is called with the pathname
394: * of this <code>File</code> to see if the application is
395: * allowed read access to the file.
396: * @see java.io.File#getPath()
397: * @see java.lang.SecurityManager#checkRead(java.lang.String)
398: * @since JDK1.0
399: */
400: public abstract long lastModified();
401:
402: /**
403: * Returns the length of the file represented by this
404: * <code>File</code> object.
405: *
406: * @return the length, in bytes, of the file specified by this object,
407: * or <code>0L</code> if the specified file does not exist.
408: * @exception SecurityException if a security manager exists, its
409: * <code>checkRead</code> method is called with the pathname
410: * of this <code>File</code> to see if the application is
411: * allowed read access to the file.
412: * @see java.io.File#getPath()
413: * @see java.lang.SecurityManager#checkRead(java.lang.String)
414: * @since JDK1.0
415: */
416: public abstract long length();
417:
418: /**
419: * Creates a directory whose pathname is specified by this
420: * <code>File</code> object.
421: *
422: * @return <code>true</code> if the directory could be created;
423: * <code>false</code> otherwise.
424: * @exception SecurityException if a security manager exists, its
425: * <code>checkWrite</code> method is called with the pathname
426: * of this <code>File</code> to see if the application is
427: * allowed write access to the file.
428: * @see java.io.File#getPath()
429: * @see java.lang.SecurityManager#checkWrite(java.lang.String)
430: * @since JDK1.0
431: */
432: public abstract boolean mkdir();
433:
434: /**
435: * Creates a directory whose pathname is specified by this
436: * <code>File</code> object, including any necessary parent directories.
437: *
438: * @return <code>true</code> if the directory (or directories) could be
439: * created; <code>false</code> otherwise.
440: * @exception SecurityException if a security manager exists, its
441: * <code>checkWrite</code> method is called with the pathname
442: * of each of the directories that is to be created, before
443: * any of the directories are created.
444: * @see java.io.File#getPath()
445: * @see java.lang.SecurityManager#checkWrite(java.lang.String)
446: * @since JDK1.0
447: */
448: public boolean mkdirs() {
449: if (exists()) {
450: return false;
451: }
452: if (mkdir()) {
453: return true;
454: }
455: String parent = getParent();
456: return (parent != null)
457: && (FileIOFactory.newInstance(parent).mkdirs() && mkdir());
458: }
459:
460: /**
461: * Renames the file specified by this <code>File</code> object to
462: * have the pathname given by the <code>File</code> argument.
463: *
464: * @param dest the new filename.
465: * @return <code>true</code> if the renaming succeeds;
466: * <code>false</code> otherwise.
467: * @exception SecurityException if a security manager exists, its
468: * <code>checkWrite</code> method is called both with the
469: * pathname of this file object and with the pathname of the
470: * destination target object to see if the application is
471: * allowed to write to both files.
472: * @see java.io.File#getPath()
473: * @see java.lang.SecurityManager#checkWrite(java.lang.String)
474: * @since JDK1.0
475: abstract boolean renameTo(FileIO dest);
476: */
477:
478: /**
479: * Returns a list of the files in the directory specified by this
480: * <code>File</code> object.
481: *
482: * @return an array of file names in the specified directory.
483: * This list does not include the current directory or the
484: * parent directory ("<code>.</code>" and "<code>..</code>"
485: * on Unix systems).
486: * @exception SecurityException If a security manager exists, its
487: * <code>checkRead</code> method is called with the pathname
488: * of this <code>File</code> to see if the application is
489: * allowed read access to the file.
490: * @see java.io.File#getPath()
491: * @see java.lang.SecurityManager#checkRead(java.lang.String)
492: * @since JDK1.0
493: */
494: public abstract String[] list();
495:
496: /**
497: * Deletes the file specified by this object. If the target
498: * file to be deleted is a directory, it must be empty for deletion
499: * to succeed.
500: *
501: * @return <code>true</code> if the file is successfully deleted;
502: * <code>false</code> otherwise.
503: * @exception SecurityException if a security manager exists, its
504: * <code>checkDelete</code> method is called with the
505: * pathname of this <code>File</code> to see if the
506: * application is allowed to delete the file.
507: * @see java.io.File#getPath()
508: * @see java.lang.SecurityManager#checkDelete(java.lang.String)
509: * @since JDK1.0
510: */
511: abstract boolean delete();
512:
513: /**
514: * Computes a hashcode for the file.
515: *
516: * @return a hash code value for this <code>File</code> object.
517: * @since JDK1.0
518: */
519: public int hashCode() {
520: return path.hashCode() ^ 1234321;
521: }
522:
523: /**
524: * Compares this object against the specified object.
525: * Returns <code>true</code> if and only if the argument is
526: * not <code>null</code> and is a <code>File</code> object whose
527: * pathname is equal to the pathname of this object.
528: *
529: * @param obj the object to compare with.
530: * @return <code>true</code> if the objects are the same;
531: * <code>false</code> otherwise.
532: * @since JDK1.0
533: */
534: public boolean equals(Object obj) {
535: if ((obj != null) && (obj instanceof FileIO)) {
536: return path.equals(((FileIO) obj).path);
537: }
538: return false;
539: }
540:
541: /**
542: * Returns a string representation of this object.
543: *
544: * @return a string giving the pathname of this object.
545: * @see java.io.File#getPath()
546: * @since JDK1.0
547: */
548: public String toString() {
549: return getPath();
550: }
551:
552: /**
553: * WriteObject is called to save this filename.
554: * The separator character is saved also so it can be replaced
555: * in case the path is reconstituted on a different host type.
556: */
557: private synchronized void writeObject(java.io.ObjectOutputStream s)
558: throws IOException {
559: s.defaultWriteObject();
560: s.writeChar(separatorChar); // Add the separator character
561: }
562:
563: /**
564: * readObject is called to restore this filename.
565: * The original separator character is read. If it is different
566: * than the separator character on this system. The old seperator
567: * is replaced by the current separator.
568: */
569: private synchronized void readObject(java.io.ObjectInputStream s)
570: throws IOException, ClassNotFoundException {
571: s.defaultReadObject();
572: char sep = s.readChar(); // read the previous seperator char
573: if (sep != separatorChar)
574: path = path.replace(sep, separatorChar);
575: }
576: }
|