0001: /*
0002: * File.java
0003: *
0004: * Copyright (C) 1998-2002 Peter Graves
0005: * $Id: File.java,v 1.13 2002/12/09 15:00:11 piso Exp $
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License
0009: * as published by the Free Software Foundation; either version 2
0010: * of the License, or (at your option) any later version.
0011: *
0012: * This program is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0015: * GNU General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * along with this program; if not, write to the Free Software
0019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0020: */
0021:
0022: package org.armedbear.j;
0023:
0024: import java.io.BufferedReader;
0025: import java.io.FileInputStream;
0026: import java.io.FileNotFoundException;
0027: import java.io.FileOutputStream;
0028: import java.io.FilenameFilter;
0029: import java.io.IOException;
0030: import java.io.InputStreamReader;
0031: import java.io.RandomAccessFile;
0032: import java.lang.reflect.Method;
0033: import java.util.ArrayList;
0034: import java.util.StringTokenizer;
0035:
0036: public class File implements Comparable {
0037: public static final int PROTOCOL_FILE = 0;
0038: public static final int PROTOCOL_HTTP = 1;
0039: public static final int PROTOCOL_HTTPS = 2;
0040: public static final int PROTOCOL_FTP = 3;
0041: public static final int PROTOCOL_SSH = 4;
0042:
0043: public static final String PREFIX_HTTP = "http://";
0044: public static final String PREFIX_HTTPS = "https://";
0045: public static final String PREFIX_FTP = "ftp://";
0046: public static final String PREFIX_SSH = "ssh://";
0047: public static final String PREFIX_FILE = "file://";
0048:
0049: public static final String PREFIX_LOCAL_HOST = LocalFile
0050: .getLocalHostName().concat(":");
0051:
0052: public static final int TYPE_UNKNOWN = 0;
0053: public static final int TYPE_FILE = 1;
0054: public static final int TYPE_DIRECTORY = 2;
0055: public static final int TYPE_LINK = 3;
0056:
0057: private static final boolean ignoreCase = Platform
0058: .isPlatformWindows();
0059:
0060: private java.io.File file;
0061:
0062: protected boolean isRemote;
0063: protected String hostName;
0064: protected String userName;
0065: protected String password;
0066: protected int port;
0067: protected int type; // unknown, file, directory, link
0068: protected String canonicalPath;
0069: protected int protocol = PROTOCOL_FILE;
0070:
0071: private String encoding;
0072:
0073: protected File() {
0074: }
0075:
0076: private File(String path) {
0077: file = new java.io.File(path);
0078: if (Platform.isPlatformWindows() && path.indexOf('*') >= 0) {
0079: // Workaround for Windows 2000, Java 1.1.8.
0080: canonicalPath = path;
0081: } else {
0082: try {
0083: canonicalPath = file.getCanonicalPath();
0084: } catch (IOException e) {
0085: canonicalPath = path;
0086: }
0087: }
0088: }
0089:
0090: private File(String host, String path, int protocol) {
0091: Debug.assertTrue(protocol != PROTOCOL_FTP);
0092: isRemote = host != null;
0093: hostName = host;
0094: canonicalPath = path;
0095: this .protocol = protocol;
0096: }
0097:
0098: public static File getInstance(String name) {
0099: if (name == null)
0100: return null;
0101: int length = name.length();
0102: if (length >= 2) {
0103: // Name may be enclosed in quotes.
0104: if (name.charAt(0) == '"' && name.charAt(length - 1) == '"') {
0105: name = name.substring(1, length - 1);
0106: length -= 2;
0107: }
0108: }
0109: if (length == 0)
0110: return null;
0111:
0112: if (name.startsWith(PREFIX_FTP))
0113: return FtpFile.getFtpFile(name);
0114: if (name.startsWith(PREFIX_HTTP)
0115: || name.startsWith(PREFIX_HTTPS))
0116: return HttpFile.getHttpFile(name);
0117: if (name.startsWith(PREFIX_SSH))
0118: return SshFile.getSshFile(name);
0119:
0120: // Local file.
0121: if (name.startsWith(PREFIX_FILE)) {
0122: name = name.substring(PREFIX_FILE.length());
0123: if (name.length() == 0)
0124: return null;
0125: } else if (name.startsWith(PREFIX_LOCAL_HOST)) {
0126: name = name.substring(PREFIX_LOCAL_HOST.length());
0127: if (name.length() == 0)
0128: return null;
0129: } else if (name.charAt(0) == ':') {
0130: name = name.substring(1);
0131: if (--length == 0)
0132: return null;
0133: }
0134: name = normalize(name);
0135:
0136: if (Platform.isPlatformWindows() && name.startsWith("\\")) {
0137: // Check for UNC path.
0138: String drive = getDrive(name);
0139: if (drive == null) {
0140: drive = getDrive(System.getProperty("user.dir"));
0141: if (drive != null)
0142: name = drive.concat(name);
0143: }
0144: }
0145:
0146: // This might return null.
0147: name = canonicalize(name, LocalFile.getSeparator());
0148:
0149: return name != null ? new File(name) : null;
0150: }
0151:
0152: protected boolean initRemote(String name, String prefix) {
0153: if (!name.startsWith(prefix))
0154: return false;
0155: name = name.substring(prefix.length());
0156: int index = name.indexOf('/');
0157:
0158: // "ftp:///", "ssh:///" are invalid.
0159: if (index == 0)
0160: return false;
0161:
0162: String s;
0163: if (index > 0) {
0164: s = name.substring(0, index);
0165: canonicalPath = canonicalize(name.substring(index), "/");
0166: } else {
0167: s = name;
0168: canonicalPath = "";
0169: }
0170:
0171: // Host name may be preceded by username and password ("user:password@host") and/or
0172: // followed by port number ("user:password@host:port").
0173: index = s.indexOf('@');
0174: if (index >= 0) {
0175: // String contains '@'.
0176: String before = s.substring(0, index);
0177:
0178: // Shorten s to what's left (host and port).
0179: s = s.substring(index + 1);
0180:
0181: index = before.indexOf(':');
0182: if (index >= 0) {
0183: userName = before.substring(0, index);
0184: password = before.substring(index + 1);
0185: } else {
0186: // No ':', no password.
0187: userName = before;
0188: }
0189: } else if (protocol != PROTOCOL_FTP) // Don't break anonymous FTP!
0190: userName = System.getProperty("user.name");
0191: index = s.indexOf(':');
0192: if (index >= 0) {
0193: // String contains ':', port specified.
0194: hostName = s.substring(0, index);
0195: try {
0196: port = Integer.parseInt(s.substring(index + 1));
0197: } catch (NumberFormatException e) {
0198: Log.error(e);
0199: }
0200: } else {
0201: // No ':', port not specified.
0202: hostName = s;
0203: }
0204: return true;
0205: }
0206:
0207: public static File getInstance(File directory, String name) {
0208: if (name == null)
0209: return null;
0210: int length = name.length();
0211: if (length >= 2) {
0212: // Name may be enclosed in quotes.
0213: if (name.charAt(0) == '"' && name.charAt(length - 1) == '"') {
0214: name = name.substring(1, length - 1);
0215: length -= 2;
0216: }
0217: }
0218: if (length == 0)
0219: return null;
0220:
0221: if (hasRemotePrefix(name)) {
0222: // Ignore directory.
0223: return getInstance(canonicalize(name, "/"));
0224: }
0225: if (hasLocalPrefix(name)) {
0226: // Fully qualified name.
0227: return getInstance(name);
0228: }
0229:
0230: if (directory == null)
0231: return null;
0232:
0233: if (directory instanceof HttpFile)
0234: return HttpFile.getHttpFile((HttpFile) directory, name);
0235: if (directory instanceof FtpFile)
0236: return FtpFile.getFtpFile((FtpFile) directory, name);
0237: if (directory instanceof SshFile)
0238: return SshFile.getSshFile((SshFile) directory, name);
0239: if (directory.isRemote) {
0240: Debug.assertTrue(false);
0241: File file = new File();
0242: file.isRemote = true;
0243: file.protocol = directory.protocol;
0244: file.hostName = directory.hostName;
0245: if (Utilities.isFilenameAbsolute(name))
0246: file.canonicalPath = canonicalize(name, "/");
0247: else
0248: file.canonicalPath = canonicalize(appendNameToPath(
0249: directory.canonicalPath(), name, '/'), "/");
0250: return file;
0251: }
0252:
0253: // Local file.
0254: name = normalize(name);
0255: if (Utilities.isFilenameAbsolute(name)) {
0256: // Name is absolute.
0257: if (Platform.isPlatformWindows() && name.startsWith("\\")) {
0258: String drive = getDrive(name);
0259: if (drive == null) {
0260: drive = directory.getDrive();
0261: if (drive != null)
0262: name = drive.concat(name);
0263: }
0264: }
0265: } else
0266: name = appendNameToPath(directory.canonicalPath(), name);
0267: name = canonicalize(name, LocalFile.getSeparator());
0268: if (name == null)
0269: return null;
0270: return new File(name);
0271: }
0272:
0273: public static File getInstance(String host, String path,
0274: int protocol) {
0275: if (host == null)
0276: return null;
0277: if (path == null)
0278: return null;
0279:
0280: if (protocol != PROTOCOL_HTTP && protocol != PROTOCOL_HTTPS
0281: && protocol != PROTOCOL_FTP)
0282: throw new NotSupportedException();
0283:
0284: if (protocol == PROTOCOL_FTP)
0285: return FtpFile.getFtpFile(host, path);
0286:
0287: return new File(host, path, protocol);
0288: }
0289:
0290: public File getRoot() {
0291: if (Platform.isPlatformWindows())
0292: return new File(getDrive() + "\\");
0293:
0294: // Unix.
0295: return new File("/");
0296: }
0297:
0298: public static File[] listRoots() {
0299: java.io.File[] files = (java.io.File[]) java.io.File
0300: .listRoots();
0301: File[] list = new File[files.length];
0302: for (int i = 0; i < files.length; i++) {
0303: list[i] = new File();
0304: list[i].canonicalPath = files[i].getPath();
0305: list[i].file = new java.io.File(list[i].canonicalPath);
0306: }
0307: return list;
0308: }
0309:
0310: public String getSeparator() {
0311: return java.io.File.separator;
0312: }
0313:
0314: public char getSeparatorChar() {
0315: return java.io.File.separatorChar;
0316: }
0317:
0318: public String getDrive() {
0319: if (Platform.isPlatformWindows())
0320: return getDrive(canonicalPath);
0321:
0322: return null;
0323: }
0324:
0325: private static String getDrive(String s) {
0326: if (s != null && s.length() >= 2) {
0327: if (s.charAt(0) == '\\' && s.charAt(1) == '\\') {
0328: // UNC path.
0329: int index = s.indexOf('\\', 2);
0330: if (index >= 0) {
0331: index = s.indexOf('\\', index + 1);
0332: if (index >= 0)
0333: return s.substring(0, index);
0334: }
0335: } else if (s.charAt(1) == ':') {
0336: String prefix = s.substring(0, 2).toUpperCase();
0337: char c = prefix.charAt(0);
0338: if (c >= 'A' && c <= 'Z')
0339: return prefix;
0340: }
0341: }
0342: return null;
0343: }
0344:
0345: protected static String canonicalize(String name, String sep) {
0346: String prefix = null;
0347: if (name.startsWith(PREFIX_HTTP)) {
0348: prefix = PREFIX_HTTP;
0349: sep = "/";
0350: } else if (name.startsWith(PREFIX_HTTPS)) {
0351: prefix = PREFIX_HTTPS;
0352: sep = "/";
0353: } else if (name.startsWith(PREFIX_FTP)) {
0354: prefix = PREFIX_FTP;
0355: sep = "/";
0356: } else if (name.startsWith(PREFIX_SSH)) {
0357: prefix = PREFIX_SSH;
0358: sep = "/";
0359: } else if (Platform.isPlatformWindows())
0360: prefix = getDrive(name);
0361:
0362: if (prefix != null)
0363: name = name.substring(prefix.length());
0364:
0365: if (sep == null)
0366: sep = LocalFile.getSeparator();
0367:
0368: StringTokenizer st = new StringTokenizer(name, sep);
0369: final int numTokens = st.countTokens();
0370: String[] array = new String[numTokens];
0371: int count = 0;
0372: for (int i = 0; i < numTokens; i++) {
0373: String token = st.nextToken();
0374: if (token.equals("..")) {
0375: if (count > 0)
0376: --count;
0377: else
0378: return null;
0379: } else if (!token.equals("."))
0380: array[count++] = token;
0381: }
0382:
0383: FastStringBuffer sb = new FastStringBuffer(256);
0384: if (prefix != null)
0385: sb.append(prefix);
0386: if (count == 0)
0387: sb.append(sep);
0388: else {
0389: for (int i = 0; i < count; i++) {
0390: if (!sb.toString().endsWith(sep))
0391: sb.append(sep);
0392: sb.append(array[i]);
0393: }
0394: }
0395: return sb.toString();
0396: }
0397:
0398: public static String normalize(String name) {
0399: if (hasRemotePrefix(name))
0400: return name;
0401:
0402: if (name.equals("~") || name.equals("~/"))
0403: name = Utilities.getUserHome();
0404: else if (name.startsWith("~/"))
0405: name = appendNameToPath(Utilities.getUserHome(), name
0406: .substring(2));
0407:
0408: if (Platform.isPlatformWindows()) {
0409: if (name.length() >= 4) {
0410: if (name.charAt(0) == '/' && name.charAt(1) == '/'
0411: && name.charAt(3) == '/') {
0412: // Convert Cygwin format to drive letter plus colon.
0413: char c = name.charAt(2);
0414: if (c >= 'a' && c <= 'z') {
0415: // e.g. "//d/"
0416: name = c + ":\\" + name.substring(4);
0417: }
0418: }
0419: }
0420: }
0421:
0422: char toBeReplaced = LocalFile.getSeparatorChar() == '/' ? '\\'
0423: : '/';
0424: return name.replace(toBeReplaced, LocalFile.getSeparatorChar());
0425: }
0426:
0427: public static boolean hasRemotePrefix(String name) {
0428: if (name.startsWith(PREFIX_HTTP))
0429: return true;
0430: if (name.startsWith(PREFIX_HTTPS))
0431: return true;
0432: if (name.startsWith(PREFIX_FTP))
0433: return true;
0434: if (name.startsWith(PREFIX_SSH))
0435: return true;
0436: return false;
0437: }
0438:
0439: public static boolean hasLocalPrefix(String name) {
0440: if (name.startsWith(PREFIX_FILE))
0441: return true;
0442: if (name.startsWith(PREFIX_LOCAL_HOST))
0443: return true;
0444: if (name.length() > 0 && name.charAt(0) == ':')
0445: return true;
0446: return false;
0447: }
0448:
0449: // Uses platform-specific separator char.
0450: public final static String appendNameToPath(String path, String name) {
0451: return appendNameToPath(path, name, LocalFile
0452: .getSeparatorChar());
0453: }
0454:
0455: public static String appendNameToPath(String path, String name,
0456: char separator) {
0457: int pathLength = path.length();
0458:
0459: if (pathLength > 0 && name.length() > 0) {
0460: // If path does not end with a separator and name does not begin
0461: // with a separator, add a separator when concatenating the strings.
0462: if (path.charAt(pathLength - 1) != separator)
0463: if (name.charAt(0) != separator)
0464: return path + separator + name;
0465:
0466: // If path ends with a separator (e.g. "/") and name begins with a
0467: // separator, remove one of the separators before concatenating the
0468: // strings.
0469: if (path.charAt(pathLength - 1) == separator)
0470: if (name.charAt(0) == separator)
0471: return path + name.substring(1);
0472: }
0473:
0474: return path + name;
0475: }
0476:
0477: public String getCanonicalPath() throws IOException {
0478: if (canonicalPath == null) {
0479: if (!isRemote) {
0480: if (file != null)
0481: canonicalPath = file.getCanonicalPath();
0482: }
0483: }
0484: return canonicalPath;
0485: }
0486:
0487: // Like getCanonicalPath(), but doesn't throw an exception.
0488: public final synchronized String canonicalPath() {
0489: if (canonicalPath == null) {
0490: if (file != null) {
0491: try {
0492: canonicalPath = file.getCanonicalPath();
0493: } catch (IOException e) {
0494: Log.error(e);
0495: }
0496: }
0497: }
0498: return canonicalPath;
0499: }
0500:
0501: public synchronized void setCanonicalPath(String s) {
0502: if (canonicalPath == null || canonicalPath.equals(""))
0503: canonicalPath = s;
0504: }
0505:
0506: public String netPath() {
0507: switch (protocol) {
0508: case PROTOCOL_FILE:
0509: return LocalFile.getLocalHostName() + ':' + canonicalPath();
0510: case PROTOCOL_HTTP:
0511: return PREFIX_HTTP + hostName + canonicalPath;
0512: case PROTOCOL_HTTPS:
0513: return PREFIX_HTTPS + hostName + canonicalPath;
0514: case PROTOCOL_FTP: {
0515: String s = PREFIX_FTP + hostName;
0516: if (canonicalPath != null)
0517: s += canonicalPath;
0518: return s;
0519: }
0520: case PROTOCOL_SSH: {
0521: String s = PREFIX_SSH + hostName;
0522: if (canonicalPath != null)
0523: s += canonicalPath;
0524: return s;
0525: }
0526: }
0527: Debug.assertTrue(false);
0528: return null;
0529: }
0530:
0531: public final String getHostName() {
0532: return hostName;
0533: }
0534:
0535: public final String getUserName() {
0536: return userName;
0537: }
0538:
0539: public final void setUserName(String userName) {
0540: this .userName = userName;
0541: }
0542:
0543: public final String getPassword() {
0544: return password;
0545: }
0546:
0547: public final void setPassword(String password) {
0548: this .password = password;
0549: }
0550:
0551: public final int getPort() {
0552: return port;
0553: }
0554:
0555: public int getProtocol() {
0556: return protocol;
0557: }
0558:
0559: public final boolean isLocal() {
0560: return !isRemote;
0561: }
0562:
0563: public final boolean isRemote() {
0564: return isRemote;
0565: }
0566:
0567: public String getName() {
0568: if (isRemote) {
0569: int index = canonicalPath.lastIndexOf('/');
0570: if (index >= 0)
0571: return canonicalPath.substring(index + 1);
0572: return canonicalPath;
0573: }
0574: if (file != null)
0575: return file.getName();
0576: return null;
0577: }
0578:
0579: public String getAbsolutePath() {
0580: if (isRemote)
0581: return canonicalPath();
0582: if (file != null) {
0583: String absPath = file.getAbsolutePath();
0584: if (Platform.isPlatformUnix() && absPath.startsWith("//")) {
0585: absPath = absPath.substring(1); // Workaround for Java 1.1.8.
0586: }
0587: return absPath;
0588: }
0589: return null;
0590: }
0591:
0592: public String getParent() {
0593: if (isRemote) {
0594: if (canonicalPath.equals("/"))
0595: return null;
0596: int index = canonicalPath.lastIndexOf('/');
0597: if (index < 0)
0598: return null;
0599: if (index == 0) // "/usr"
0600: return "/";
0601: return canonicalPath.substring(0, index);
0602: }
0603: if (file != null)
0604: return file.getParent();
0605: return null;
0606: }
0607:
0608: public File getParentFile() {
0609: if (canonicalPath() == null || canonicalPath.equals("/")) {
0610: // HTTP is a special case. We might really be looking at
0611: // "http://www.cnn.com/index.html", but it might appear to
0612: // be "http://www.cnn.com/".
0613: if (protocol == PROTOCOL_HTTP || protocol == PROTOCOL_HTTPS)
0614: return new File(hostName, "/", protocol);
0615:
0616: return null;
0617: }
0618: if (isRemote) {
0619: int index = canonicalPath.lastIndexOf('/');
0620: if (index < 0)
0621: return null;
0622: if (index == 0) // "/usr"
0623: return new File(hostName, "/", protocol);
0624: return new File(hostName,
0625: canonicalPath.substring(0, index), protocol);
0626: }
0627: if (file != null && file.getParent() != null)
0628: return new File(file.getParent());
0629: return null;
0630: }
0631:
0632: public boolean exists() {
0633: if (file == null)
0634: throw new NotSupportedException();
0635: return file.exists();
0636: }
0637:
0638: public boolean canWrite() {
0639: if (file == null)
0640: throw new NotSupportedException();
0641: return file.canWrite();
0642: }
0643:
0644: public boolean canRead() {
0645: if (file == null)
0646: throw new NotSupportedException();
0647: return file.canRead();
0648: }
0649:
0650: public boolean isFile() {
0651: if (file == null)
0652: throw new NotSupportedException();
0653: return file.isFile();
0654: }
0655:
0656: public boolean isDirectory() {
0657: if (file == null)
0658: throw new NotSupportedException();
0659: return file.isDirectory();
0660: }
0661:
0662: public boolean isLink() {
0663: if (file == null)
0664: throw new NotSupportedException();
0665: return !canonicalPath().equals(getAbsolutePath());
0666: }
0667:
0668: public boolean isAbsolute() {
0669: if (file == null)
0670: throw new NotSupportedException();
0671: return file.isAbsolute();
0672: }
0673:
0674: public long lastModified() {
0675: if (file == null)
0676: throw new NotSupportedException();
0677: return file.lastModified();
0678: }
0679:
0680: public boolean setLastModified(long time) {
0681: if (file == null)
0682: throw new NotSupportedException();
0683: return file.setLastModified(time);
0684: }
0685:
0686: public long length() {
0687: if (file == null)
0688: throw new NotSupportedException();
0689: return file.length();
0690: }
0691:
0692: public boolean mkdir() {
0693: if (file == null)
0694: throw new NotSupportedException();
0695: return file.mkdir();
0696: }
0697:
0698: public boolean mkdirs() {
0699: if (file == null)
0700: throw new NotSupportedException();
0701: return file.mkdirs();
0702: }
0703:
0704: public boolean renameTo(File f) {
0705: if (file == null || f.file == null)
0706: throw new NotSupportedException();
0707: return file.renameTo(f.file);
0708: }
0709:
0710: public String[] list() {
0711: if (this instanceof FtpFile || this instanceof SshFile) {
0712: String listing = getDirectoryListing();
0713: if (listing == null)
0714: return null;
0715: FastStringReader reader = new FastStringReader(listing);
0716: ArrayList list = new ArrayList();
0717: String s;
0718: while ((s = reader.readLine()) != null) {
0719: String name = DirectoryEntry.getName(s);
0720: if (name == null || name.equals(".")
0721: || name.equals(".."))
0722: continue;
0723: list.add(name);
0724: }
0725: if (list.size() == 0)
0726: return null;
0727: String[] names = new String[list.size()];
0728: list.toArray(names);
0729: return names;
0730: }
0731: if (isRemote)
0732: return null;
0733: if (file == null)
0734: throw new NotSupportedException();
0735: return file.list();
0736: }
0737:
0738: public File[] listFiles() {
0739: if (!isDirectory())
0740: return null;
0741: if (this instanceof FtpFile || this instanceof SshFile) {
0742: String listing = getDirectoryListing();
0743: if (listing == null)
0744: return null;
0745: long start = System.currentTimeMillis();
0746: FastStringReader reader = new FastStringReader(listing);
0747: ArrayList list = new ArrayList();
0748: int nameColumn = -1;
0749: String s;
0750: while ((s = reader.readLine()) != null) {
0751: if (nameColumn < 0)
0752: nameColumn = DirectoryEntry.getNameColumn(s);
0753: DirectoryEntry entry = DirectoryEntry
0754: .getDirectoryEntry(s, null);
0755: if (entry != null) {
0756: final String name = entry.extractName(nameColumn);
0757: if (name == null || name.equals(".")
0758: || name.equals(".."))
0759: continue;
0760: String path = appendNameToPath(canonicalPath(),
0761: name, '/');
0762: File file = null;
0763: if (protocol == PROTOCOL_FTP)
0764: file = new FtpFile(hostName, path, userName,
0765: password, port);
0766: else if (protocol == PROTOCOL_SSH)
0767: file = new SshFile(hostName, path, userName,
0768: password, port);
0769: else
0770: Debug.bug();
0771: if (file != null) {
0772: if (entry.isDirectory())
0773: file.type = TYPE_DIRECTORY;
0774: else if (entry.isLink())
0775: file.type = TYPE_LINK;
0776: else
0777: file.type = TYPE_FILE;
0778: list.add(file);
0779: }
0780: }
0781: }
0782: if (list.size() == 0)
0783: return null;
0784: File[] files = new File[list.size()];
0785: list.toArray(files);
0786: long elapsed = System.currentTimeMillis() - start;
0787: Log.debug("listFiles " + elapsed + " ms " + this );
0788: return files;
0789: }
0790: if (isRemote)
0791: return null;
0792: if (file == null)
0793: throw new NotSupportedException();
0794: String[] names = file.list();
0795: if (names == null)
0796: return null;
0797: final FastStringBuffer sb = new FastStringBuffer();
0798: final String cp = canonicalPath();
0799: File[] files = new File[names.length];
0800: for (int i = 0; i < names.length; i++) {
0801: sb.setText(cp);
0802: sb.append(LocalFile.getSeparator());
0803: sb.append(names[i]);
0804: files[i] = new File(sb.toString());
0805: }
0806: return files;
0807: }
0808:
0809: public String[] list(FilenameFilter filter) {
0810: if (isRemote)
0811: return null;
0812: if (file == null)
0813: throw new NotSupportedException();
0814: return file.list(filter);
0815: }
0816:
0817: public String getDirectoryListing() {
0818: return null;
0819: }
0820:
0821: public String getDirectoryListing(boolean forceRefresh) {
0822: return null;
0823: }
0824:
0825: public boolean delete() {
0826: if (file == null)
0827: throw new NotSupportedException();
0828: return file.delete();
0829: }
0830:
0831: public int hashCode() {
0832: if (file == null)
0833: throw new NotSupportedException();
0834: return file.hashCode();
0835: }
0836:
0837: public boolean equals(Object obj) {
0838: if (this == obj)
0839: return true;
0840: if (!(obj instanceof File))
0841: return false;
0842: File f = (File) obj;
0843: // Protocol.
0844: if (f.protocol != protocol)
0845: return false;
0846: // Host name.
0847: if (f.hostName == null) {
0848: if (hostName != null)
0849: return false;
0850: } else if (!f.hostName.equals(hostName))
0851: return false;
0852: // Handle pathological corner case where both canonical paths are null.
0853: if (f.canonicalPath() == canonicalPath())
0854: return true;
0855: // At this point the canonical paths are cached for both files. If
0856: // either one is null, they can't be equal.
0857: if (f.canonicalPath == null || canonicalPath == null)
0858: return false;
0859: // Never ignore case for remote files.
0860: if (ignoreCase && !isRemote)
0861: return f.canonicalPath.equalsIgnoreCase(canonicalPath);
0862: return f.canonicalPath.equals(canonicalPath);
0863: }
0864:
0865: public String toString() {
0866: return netPath();
0867: }
0868:
0869: public FileInputStream getInputStream()
0870: throws FileNotFoundException {
0871: if (isRemote)
0872: throw new NotSupportedException();
0873: if (file == null)
0874: throw new NotSupportedException();
0875: return new FileInputStream(file);
0876: }
0877:
0878: public FileOutputStream getOutputStream()
0879: throws FileNotFoundException {
0880: if (isRemote)
0881: throw new NotSupportedException();
0882: if (file == null)
0883: throw new NotSupportedException();
0884: return new FileOutputStream(file);
0885: }
0886:
0887: public FileOutputStream getOutputStream(boolean append)
0888: throws FileNotFoundException {
0889: if (isRemote)
0890: throw new NotSupportedException();
0891: if (file == null)
0892: throw new NotSupportedException();
0893: return new FileOutputStream(canonicalPath, append);
0894: }
0895:
0896: public RandomAccessFile getRandomAccessFile(String mode)
0897: throws FileNotFoundException {
0898: if (isRemote)
0899: throw new NotSupportedException();
0900: if (file == null)
0901: throw new NotSupportedException();
0902: return new RandomAccessFile(file, mode);
0903: }
0904:
0905: public final String getEncoding() {
0906: return encoding;
0907: }
0908:
0909: public final void setEncoding(String encoding) {
0910: this .encoding = encoding;
0911: }
0912:
0913: public int getPermissions() {
0914: int permissions = 0;
0915: if (isLocal() && Platform.isPlatformUnix()) {
0916: String[] cmdarray = { "ls", "-ld", canonicalPath() };
0917: try {
0918: Process process = Runtime.getRuntime().exec(cmdarray);
0919: BufferedReader reader = new BufferedReader(
0920: new InputStreamReader(process.getInputStream()));
0921: String output = reader.readLine();
0922: if (output != null) {
0923: String s = output.substring(1, 10);
0924: if (s.length() == 9) {
0925: if (s.charAt(0) == 'r')
0926: permissions += 0400;
0927: if (s.charAt(1) == 'w')
0928: permissions += 0200;
0929: if (s.charAt(2) == 'x')
0930: permissions += 0100;
0931: if (s.charAt(3) == 'r')
0932: permissions += 040;
0933: if (s.charAt(4) == 'w')
0934: permissions += 020;
0935: if (s.charAt(5) == 'x')
0936: permissions += 010;
0937: if (s.charAt(6) == 'r')
0938: permissions += 4;
0939: if (s.charAt(7) == 'w')
0940: permissions += 2;
0941: if (s.charAt(8) == 'x')
0942: permissions += 1;
0943: }
0944: reader.close();
0945: process.getInputStream().close();
0946: process.getOutputStream().close();
0947: process.getErrorStream().close();
0948: }
0949: }
0950: // Feb 4 2000 5:30 PM
0951: // Catch Throwable here rather than Exception.
0952: // Kaffe's implementation of Runtime.exec() throws
0953: // java.lang.InternalError.
0954: catch (Throwable t) {
0955: Log.error(t);
0956: }
0957: }
0958: return permissions;
0959: }
0960:
0961: public void setPermissions(int permissions) {
0962: if (permissions != 0 && isLocal() && Platform.isPlatformUnix()) {
0963: String[] cmdarray = { "chmod",
0964: Integer.toString(permissions, 8), canonicalPath() };
0965: try {
0966: Process process = Runtime.getRuntime().exec(cmdarray);
0967: process.getInputStream().close();
0968: process.getOutputStream().close();
0969: process.getErrorStream().close();
0970: int exitCode = process.waitFor();
0971: if (exitCode != 0)
0972: Log.error("setPermissions exitCode = " + exitCode);
0973: }
0974: // Feb 4 2000 5:30 PM
0975: // Catch Throwable here rather than Exception.
0976: // Kaffe's implementation of Runtime.exec() throws
0977: // java.lang.InternalError.
0978: catch (Throwable t) {
0979: Log.error(t);
0980: }
0981: }
0982: }
0983:
0984: public final int compareTo(Object o) {
0985: return getName().compareTo(((File) o).getName());
0986: }
0987:
0988: // private static void test(String dirname, String filename, String expected)
0989: // {
0990: // File dir = getInstance(dirname);
0991: // File file = getInstance(dir, filename);
0992:
0993: // String result;
0994:
0995: // if (file == null)
0996: // result = "null";
0997: // else
0998: // result = file.netPath();
0999:
1000: // if (Platform.isPlatformUnix() && result.equals(expected))
1001: // System.out.println(" " + dirname + " + " + filename + " => " + result);
1002: // else if (Platform.isPlatformWindows() && result.equalsIgnoreCase(expected))
1003: // System.out.println(" " + dirname + " + " + filename + " => " + result);
1004: // else
1005: // {
1006: // System.out.println("* " + dirname + " + " + filename + " => " + result);
1007: // System.out.println("*** expected " + expected + " ***");
1008: // }
1009: // }
1010:
1011: // public static void main(String args[])
1012: // {
1013: // if (Platform.isPlatformUnix())
1014: // {
1015: // test("/home/peter", ".", "/home/peter");
1016: // test("/home/peter", "./", "/home/peter");
1017: // test("/home/peter", "..", "/home");
1018: // test("/home/peter", "../", "/home");
1019: // test("/", "~/foo", "/home/peter/foo");
1020: // test("/", "~/../foo", "/home/foo");
1021: // test("/", "~/../../foo", "/foo");
1022: // test("/", "~/../../../foo", "null");
1023: // test("/", "~peter/foo", "/~peter/foo");
1024: // test("/home/peter", "./foo", "/home/peter/foo");
1025: // test("/home/peter", "../foo", "/home/foo");
1026: // test("/home/peter", "../../foo", "/foo");
1027: // test("/home/peter", "../../../foo", "null");
1028: // test("/home/peter", "..foo", "/home/peter/..foo");
1029: // test("/home/peter", "foo", "/home/peter/foo");
1030: // test("/home/peter", "/foo", "/foo");
1031: // }
1032: // else
1033: // {
1034: // test("\\", ".", "C:\\");
1035: // test("\\home", "\\home\\peter\\j", "C:\\home\\peter\\j");
1036: // test("d:\\home", "\\home\\peter\\j", "D:\\home\\peter\\j");
1037: // test("\\home", "d:\\home\\peter\\j", "d:\\home\\peter\\j");
1038: // test("c:\\home\\peter", ".", "C:\\home\\peter");
1039: // test("c:\\home\\peter", "..", "C:\\home");
1040: // test("c:\\home\\peter", "..\\..", "C:\\");
1041: // test("c:\\home\\peter", "..\\..\\..", "null");
1042: // test("c:\\home\\peter", "c:\\", "C:\\");
1043: // test("c:\\home\\peter", "c:\\windows", "C:\\windows");
1044: // test("c:\\home\\peter", "c:\\windows\\", "C:\\windows");
1045: // test("c:\\", ".", "C:\\");
1046: // test("c:\\", ".\\", "C:\\");
1047: // test("c:\\", "..", "null");
1048: // test("//c/", "foo", "C:\\foo");
1049: // }
1050:
1051: // test("http://www.cnn.com", "/virtual/1998/code/cnn.css", "http://www.cnn.com/virtual/1998/code/cnn.css");
1052: // test("http://www.cnn.com/", "/virtual/1998/code/cnn.css", "http://www.cnn.com/virtual/1998/code/cnn.css");
1053: // test("http://www.cnn.com", "http://www.swatch.com", "http://www.swatch.com/");
1054: // test("http://www.cnn.com/", "http://www.swatch.com", "http://www.swatch.com/");
1055: // test("http://www.swatch.com", "specials/live_timing/index.html", "http://www.swatch.com/specials/live_timing/index.html");
1056: // test("http://www.swatch.com/", "specials/live_timing/index.html", "http://www.swatch.com/specials/live_timing/index.html");
1057: // }
1058: }
|