001: // Copyright (c) 2007 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ../../COPYING.
003:
004: package gnu.text;
005:
006: import java.io.*;
007: import java.net.*;
008: import gnu.mapping.*;
009:
010: /** A wrapper around a {@code java.io.File} that extends {@code Path}. */
011:
012: public class FilePath extends Path
013: /* #ifdef JAVA2 */
014: /* #ifdef JAVA5 */
015: // implements Comparable<FilePath>
016: /* #else */
017: implements Comparable
018: /* #endif */
019: /* #endif */
020: {
021: File file;
022: /** Usually the same as {@code file.toString()}.
023: * One important difference: {@code isDirectory} is true
024: * if {@code path} ends with the {@code '/'} or the {@code separatorChar}.
025: * (
026: * The original String if constructed from a String.
027: */
028: String path;
029:
030: private FilePath(File file) {
031: this .file = file;
032: this .path = file.toString();
033: }
034:
035: private FilePath(File file, String path) {
036: this .file = file;
037: this .path = path;
038: }
039:
040: public static FilePath valueOf(String str) {
041: String orig = str;
042: /* FIXME: Should we expand '~'?
043: Issues: is (path "~/bar") absolute?
044: What about: (base:resolve "~/bar") ?
045: What if base above isn't a FilePath?
046: int len = str.length();
047: if (len > 0 && str.charAt(0) == '~' && File.separatorChar == '/')
048: {
049: if (len == 1 || str.charAt(1) == '/')
050: {
051: String user = System.getProperty("user.home");
052: if (user != null)
053: str = user + str.substring(1);
054: }
055: else
056: {
057: // We don't support '~USER/...' Do that using /bin/sh. FIXME
058: }
059: }
060: */
061: return new FilePath(new File(str), orig);
062: }
063:
064: public static FilePath valueOf(File file) {
065: return new FilePath(file);
066: }
067:
068: public static FilePath coerceToFilePathOrNull(Object path) {
069: if (path instanceof FilePath)
070: return (FilePath) path;
071: if (path instanceof URIPath)
072: return FilePath.valueOf(new File(((URIPath) path).uri));
073: /*
074: if (path instanceof URL)
075: return URLPath.valueOf((URL) path);
076: */
077: /* #ifdef use:java.net.URI */
078: if (path instanceof URI)
079: return FilePath.valueOf(new File((URI) path));
080: /* #endif */
081: if (path instanceof File)
082: return FilePath.valueOf((File) path);
083: String str;
084: if (path instanceof gnu.lists.FString) // FIXME: || UntypedAtomic
085: str = path.toString();
086: else if (path instanceof String)
087: str = (String) path;
088: else
089: return null;
090: return FilePath.valueOf(str);
091: }
092:
093: public static FilePath makeFilePath(Object arg) {
094: FilePath path = coerceToFilePathOrNull(arg);
095: if (path == null)
096: throw new WrongType((String) null, WrongType.ARG_CAST, arg,
097: "filepath");
098: return path;
099: }
100:
101: public boolean isAbsolute() {
102: return this == Path.userDirPath || file.isAbsolute();
103: }
104:
105: public boolean isDirectory() {
106: if (file.isDirectory())
107: return true;
108: if (!file.exists()) {
109: int len = path.length();
110: if (len > 0) {
111: char last = path.charAt(len - 1);
112: if (last == '/' || last == File.separatorChar)
113: return true;
114: }
115: }
116: return false;
117: }
118:
119: public long getLastModified() {
120: return file.lastModified();
121: }
122:
123: public boolean exists() {
124: return file.exists();
125: }
126:
127: public long getContentLength() {
128: long length = file.length();
129: return length == 0 && !file.exists() ? -1 : length;
130: }
131:
132: public String getPath() {
133: return file.getPath();
134: }
135:
136: public String getLast() {
137: return file.getName();
138: }
139:
140: public/* #ifdef JAVA5 */
141: // FilePath
142: /* #else */
143: Path
144: /* #endif */
145: getParent() {
146: File parent = file.getParentFile();
147: if (parent == null)
148: return null;
149: else
150: return FilePath.valueOf(parent);
151: }
152:
153: public int compareTo(FilePath path) {
154: return file.compareTo(path.file);
155: }
156:
157: /* #ifndef JAVA5 */
158: public int compareTo(Object obj) {
159: return compareTo((FilePath) obj);
160: }
161:
162: /* #endif */
163:
164: public boolean equals(Object obj) {
165: return obj instanceof FilePath
166: && file.equals(((FilePath) obj).file);
167: }
168:
169: public int hashCode() {
170: return file.hashCode();
171: }
172:
173: public String toString() {
174: return path;
175: }
176:
177: public File toFile() {
178: return file;
179: }
180:
181: public URL toURL() {
182: if (this == Path.userDirPath)
183: return resolve("").toURL();
184: if (!isAbsolute())
185: return getAbsolute().toURL();
186: try {
187: /* #ifdef JAVA2 */
188: /* #ifdef use:java.net.URI */
189: return file.toURI().toURL();
190: /* #else */
191: // return file.toURL();
192: /* #endif */
193: /* #else */
194: // char fileSep = File.separatorChar;
195: // return new URL("file:" + file.getAbsolutePath().replace(fileSep, '/'));
196: /* #endif */
197: } catch (Throwable ex) {
198: throw WrappedException.wrapIfNeeded(ex);
199: }
200: }
201:
202: /* #ifndef use:java.net.URI */
203: // public String toURIString ()
204: // {
205: // if (file.isAbsolute())
206: // return toURL().toString();
207: // else
208: // return file.toString().replace(File.separatorChar, '/');
209: // }
210: /* #endif */
211:
212: /* #ifdef use:java.net.URI */
213: private static URI toURI(File file) {
214: try {
215: if (file.isAbsolute())
216: return file.toURI();
217: /* We don't want to just use File.toURI(),
218: because that turns a relative File into an absolute URI. */
219: String fname = file.toString();
220: char fileSep = File.separatorChar;
221: if (fileSep != '/')
222: fname = fname.replace(fileSep, '/');
223: return new URI(null, null, fname, null);
224: } catch (Throwable ex) {
225: throw WrappedException.wrapIfNeeded(ex);
226: }
227:
228: }
229:
230: public URI toURI() {
231: if (this == Path.userDirPath)
232: return resolve("").toURI();
233: return toURI(file);
234: }
235:
236: /* #endif */
237:
238: public InputStream openInputStream() throws IOException {
239: return new FileInputStream(file);
240: }
241:
242: public OutputStream openOutputStream() throws IOException {
243: return new FileOutputStream(file);
244: }
245:
246: public String getScheme() {
247: return isAbsolute() ? "file" : null;
248: }
249:
250: public Path resolve(String relative) {
251: if (Path.uriSchemeSpecified(relative))
252: return URLPath.valueOf(relative);
253: File rfile = new File(relative);
254: if (rfile.isAbsolute())
255: return FilePath.valueOf(rfile);
256: char sep = File.separatorChar;
257: if (sep != '/')
258: relative = relative.replace('/', sep);
259: // FIXME? Or: if (file.getPath().length() == 0) return relative;
260: File nfile;
261: if (this == Path.userDirPath)
262: nfile = new File(System.getProperty("user.dir"), relative);
263: else
264: nfile = new File(isDirectory() ? file : file
265: .getParentFile(), relative);
266: return valueOf(nfile);
267: }
268:
269: public Path getCanonical() {
270: try {
271: File canon = file.getCanonicalFile();
272: if (!canon.equals(file))
273: return valueOf(canon);
274: } catch (Throwable ex) {
275: }
276: return this;
277: }
278: }
|