001: /*
002: * VFSFile.java - A file residing on a virtual file system
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 1998, 2005 Slava Pestov
007: * Portions copyright (C) 2007 Matthieu Casanova
008: *
009: * This program is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; either version 2
012: * of the License, or any later version.
013: *
014: * This program is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
017: * GNU General Public License for more details.
018: *
019: * You should have received a copy of the GNU General Public License
020: * along with this program; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
022: */
023:
024: package org.gjt.sp.jedit.io;
025:
026: //{{{ Imports
027: import java.awt.Color;
028: import java.io.*;
029: import org.gjt.sp.jedit.*;
030: import org.gjt.sp.jedit.browser.VFSBrowser;
031: import org.gjt.sp.jedit.browser.FileCellRenderer;
032: import org.gjt.sp.util.Log;
033: import org.gjt.sp.util.IOUtilities;
034:
035: import javax.swing.*;
036:
037: //}}}
038:
039: /**
040: * A directory entry returned from a file listing.
041: * @since jEdit 4.3pre2
042: */
043: public class VFSFile implements Serializable {
044: //{{{ findCompletion() method
045: /**
046: * Return the index of a file whose name matches the given string,
047: * in a case-insensitive manner. Exact matches are preferred.
048: * @param files The list of files
049: * @param start The start index, inclusive
050: * @param end The end index, exclusive
051: * @param str The string to match
052: * @param dirsOnly Only match directories?
053: * @since jEdit 4.3pre3
054: */
055: public static int findCompletion(VFSFile[] files, int start,
056: int end, String str, boolean dirsOnly) {
057: for (int i = start; i < end; i++) {
058: VFSFile file = files[i];
059: String matchAgainst = (MiscUtilities.isAbsolutePath(str) ? file
060: .getPath()
061: : file.getName());
062:
063: if (dirsOnly && file.getType() == FILE)
064: continue;
065: /* try exact match first */
066: else if (matchAgainst.equals(str))
067: return i;
068: else if (matchAgainst.regionMatches(true, 0, str, 0, str
069: .length()))
070: return i;
071: }
072:
073: return -1;
074: } //}}}
075:
076: //{{{ findCompletion() method
077: public static String findCompletion(String path, String complete,
078: VFSBrowser browser, boolean dirsOnly) {
079: Log.log(Log.DEBUG, VFSFile.class, "findCompletion(" + path
080: + ',' + complete + ',' + dirsOnly + ')');
081:
082: if (complete.equals("~"))
083: return System.getProperty("user.home");
084: else if (complete.equals("-"))
085: return browser.getView().getBuffer().getDirectory();
086: else if (complete.equals(".."))
087: return MiscUtilities.getParentOfPath(path);
088:
089: if (MiscUtilities.isAbsolutePath(complete)) {
090: if (MiscUtilities.isURL(complete))
091: return complete;
092: else
093: path = "roots:";
094: }
095:
096: VFS vfs = VFSManager.getVFSForPath(path);
097: if ((vfs.getCapabilities() & VFS.LOW_LATENCY_CAP) == 0)
098: return null;
099: Object session = vfs.createVFSSession(path, browser);
100: if (session == null)
101: return null;
102:
103: try {
104: VFSFile[] files = vfs._listFiles(session, path, browser);
105: int index = findCompletion(files, 0, files.length,
106: complete, dirsOnly);
107: if (index != -1)
108: return files[index].path;
109: } catch (IOException e) {
110: VFSManager.error(e, path, browser);
111: } finally {
112: try {
113: vfs._endVFSSession(session, browser);
114: } catch (IOException e) {
115: VFSManager.error(e, path, browser);
116: }
117: }
118:
119: return null;
120: } //}}}
121:
122: //{{{ getIcon() method
123: /**
124: * Returns the icon for the file.
125: *
126: * @since jEdit 4.3pre9
127: */
128: public final Icon getIcon(boolean expanded) {
129: return getIcon(expanded,
130: jEdit._getBuffer(getSymlinkPath()) != null);
131: } //}}}
132:
133: //{{{ getIcon() method
134: /**
135: * Returns the icon for the file.
136: * Implementations of File system browsers can override this method
137: *
138: * @since jEdit 4.3pre9
139: */
140: public Icon getIcon(boolean expanded, boolean openBuffer) {
141: return getDefaultIcon(expanded, openBuffer);
142: } //}}}
143:
144: //{{{ getDefaultIcon() method
145: /**
146: * Returns the default icon for the file.
147: *
148: * @since jEdit 4.3pre9
149: */
150: public final Icon getDefaultIcon(boolean expanded,
151: boolean openBuffer) {
152: if (getType() == DIRECTORY)
153: return expanded ? FileCellRenderer.openDirIcon
154: : FileCellRenderer.dirIcon;
155: else if (getType() == FILESYSTEM)
156: return FileCellRenderer.filesystemIcon;
157: else if (openBuffer)
158: return FileCellRenderer.openFileIcon;
159: else
160: return FileCellRenderer.fileIcon;
161: } //}}}
162:
163: //{{{ getDefaultIcon() method
164: /**
165: * Returns the default icon of the file.
166: *
167: * @return the default icon of the file
168: * @since jEdit 4.3pre9
169: */
170: public final Icon getDefaultIcon(boolean expanded) {
171: return getDefaultIcon(expanded, jEdit
172: ._getBuffer(getSymlinkPath()) != null);
173: } //}}}
174:
175: //{{{ File types
176: public static final int FILE = 0;
177: public static final int DIRECTORY = 1;
178: public static final int FILESYSTEM = 2;
179: //}}}
180:
181: //{{{ Instance variables
182: /**
183: * @deprecated Use the accessor/mutator methods instead.
184: */
185: public String name;
186: /**
187: * @deprecated Use the accessor/mutator methods instead.
188: */
189: public String path;
190: /**
191: * @deprecated Use the accessor/mutator methods instead.
192: */
193: public String symlinkPath;
194: /**
195: * @deprecated Use the accessor/mutator methods instead.
196: */
197: public String deletePath;
198: /**
199: * @deprecated Use the accessor/mutator methods instead.
200: */
201: public int type;
202: /**
203: * @deprecated Use the accessor/mutator methods instead.
204: */
205: public long length;
206: /**
207: * @deprecated Use the accessor/mutator methods instead.
208: */
209: public boolean hidden;
210: /**
211: * @deprecated Use the accessor/mutator methods instead.
212: */
213: public boolean canRead;
214: /**
215: * @deprecated Use the accessor/mutator methods instead.
216: */
217: public boolean canWrite;
218:
219: //}}}
220:
221: //{{{ VFSFile constructor
222: /**
223: * @since jEdit 4.3pre2
224: */
225: public VFSFile() {
226: } //}}}
227:
228: //{{{ VFSFile constructor
229: public VFSFile(String name, String path, String deletePath,
230: int type, long length, boolean hidden) {
231: this .name = name;
232: this .path = path;
233: this .deletePath = deletePath;
234: this .symlinkPath = path;
235: this .type = type;
236: this .length = length;
237: this .hidden = hidden;
238: if (path != null) {
239: // maintain backwards compatibility
240: VFS vfs = VFSManager.getVFSForPath(path);
241: canRead = ((vfs.getCapabilities() & VFS.READ_CAP) != 0);
242: canWrite = ((vfs.getCapabilities() & VFS.WRITE_CAP) != 0);
243: }
244: } //}}}
245:
246: //{{{ getVFS() method
247: /**
248: * @return The originating virtual file system of this file.
249: */
250: public VFS getVFS() {
251: return VFSManager.getVFSForPath(path);
252: } //}}}
253:
254: //{{{ getName() method
255: public String getName() {
256: return name;
257: } //}}}
258:
259: //{{{ setName() method
260: public void setName(String name) {
261: this .name = name;
262: } //}}}
263:
264: //{{{ isBinary() method
265: /**
266: * Check if a file is binary file.
267: *
268: * @param session the VFS session
269: * @return <code>true</code> if the file was detected as binary
270: * @throws IOException IOException If an I/O error occurs
271: * @since jEdit 4.3pre5
272: */
273: public boolean isBinary(Object session) throws IOException {
274: InputStream in = getVFS()._createInputStream(session,
275: getPath(), false, jEdit.getActiveView());
276: if (in == null)
277: throw new IOException(
278: "Unable to get a Stream for this file " + this );
279:
280: try {
281: return MiscUtilities.isBinary(in);
282: } finally {
283: IOUtilities.closeQuietly(in);
284: }
285: } //}}}
286:
287: //{{{ getPath() method
288: public String getPath() {
289: return path;
290: } //}}}
291:
292: //{{{ setPath() method
293: public void setPath(String path) {
294: this .path = path;
295: } //}}}
296:
297: //{{{ getSymlinkPath() method
298: public String getSymlinkPath() {
299: return symlinkPath;
300: } //}}}
301:
302: //{{{ setSymlinkPath() method
303: public void setSymlinkPath(String symlinkPath) {
304: this .symlinkPath = symlinkPath;
305: } //}}}
306:
307: //{{{ getDeletePath() method
308: public String getDeletePath() {
309: return deletePath;
310: } //}}}
311:
312: //{{{ setDeletePath() method
313: public void setDeletePath(String deletePath) {
314: this .deletePath = deletePath;
315: } //}}}
316:
317: //{{{ getType() method
318: public int getType() {
319: return type;
320: } //}}}
321:
322: //{{{ setType() method
323: public void setType(int type) {
324: this .type = type;
325: } //}}}
326:
327: //{{{ getLength() method
328: public long getLength() {
329: return length;
330: } //}}}
331:
332: //{{{ setLength() method
333: public void setLength(long length) {
334: this .length = length;
335: } //}}}
336:
337: //{{{ isHidden() method
338: public boolean isHidden() {
339: return hidden;
340: } //}}}
341:
342: //{{{ setHidden() method
343: public void setHidden(boolean hidden) {
344: this .hidden = hidden;
345: } //}}}
346:
347: //{{{ isReadable() method
348: public boolean isReadable() {
349: return canRead;
350: } //}}}
351:
352: //{{{ setReadable() method
353: public void setReadable(boolean canRead) {
354: this .canRead = canRead;
355: } //}}}
356:
357: //{{{ isWriteable() method
358: public boolean isWriteable() {
359: return canWrite;
360: } //}}}
361:
362: //{{{ setWriteable() method
363: public void setWriteable(boolean canWrite) {
364: this .canWrite = canWrite;
365: } //}}}
366:
367: protected boolean colorCalculated;
368: protected Color color;
369:
370: //{{{ getExtendedAttribute() method
371: /**
372: * Returns the value of an extended attribute. Note that this
373: * returns formatted strings (eg, "10 Mb" for a file size of
374: * 1048576 bytes). If you need access to the raw data, access
375: * fields and methods of this class.
376: * @param name The extended attribute name
377: * @since jEdit 4.2pre1
378: */
379: public String getExtendedAttribute(String name) {
380: if (name.equals(VFS.EA_TYPE)) {
381: switch (getType()) {
382: case FILE:
383: return jEdit.getProperty("vfs.browser.type.file");
384: case DIRECTORY:
385: return jEdit.getProperty("vfs.browser.type.directory");
386: case FILESYSTEM:
387: return jEdit.getProperty("vfs.browser.type.filesystem");
388: default:
389: throw new IllegalArgumentException();
390: }
391: } else if (name.equals(VFS.EA_STATUS)) {
392: if (isReadable()) {
393: if (isWriteable())
394: return jEdit.getProperty("vfs.browser.status.rw");
395: else
396: return jEdit.getProperty("vfs.browser.status.ro");
397: } else {
398: if (isWriteable())
399: return jEdit
400: .getProperty("vfs.browser.status.append");
401: else
402: return jEdit.getProperty("vfs.browser.status.no");
403: }
404: } else if (name.equals(VFS.EA_SIZE)) {
405: if (getType() != FILE)
406: return null;
407: else
408: return MiscUtilities.formatFileSize(getLength());
409: } else
410: return null;
411: } //}}}
412:
413: //{{{ getColor() method
414: /**
415: * Returns the color that will be used to display the file.
416: *
417: * @return the color of the file
418: */
419: public Color getColor() {
420: if (!colorCalculated) {
421: colorCalculated = true;
422: color = VFS.getDefaultColorFor(name);
423: }
424:
425: return color;
426: } //}}}
427:
428: //{{{ toString() method
429: public String toString() {
430: return name;
431: } //}}}
432:
433: //{{{ fetchedAttrs() method
434: /**
435: * Returns true if the attributes are already fetched.
436: *
437: * @see #fetchAttrs()
438: * @return <code>true</code> if the attributes are already fetched
439: */
440: protected boolean fetchedAttrs() {
441: return fetchedAttrs;
442: } //}}}
443:
444: //{{{ fetchAttrs() method
445: /**
446: * Fetch some attributes of the file.
447: * Some attributes are not fetched during
448: * file initialization because it takes time.
449: * They are fetched here.
450: * VFS implementation should overwrite this
451: */
452: protected void fetchAttrs() {
453: fetchedAttrs = true;
454: } //}}}
455:
456: /** This is true if the attributes are already fetched. */
457: private boolean fetchedAttrs;
458: }
|