KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > sp > jedit > io > VFS


1 /*
2  * VFS.java - Virtual filesystem implementation
3  * :tabSize=8:indentSize=8:noTabs=false:
4  * :folding=explicit:collapseFolds=1:
5  *
6  * Copyright (C) 2000, 2003 Slava Pestov
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */

22
23 package org.gjt.sp.jedit.io;
24
25 //{{{ Imports
26
import java.awt.Color JavaDoc;
27 import java.awt.Component JavaDoc;
28 import java.io.*;
29 import java.util.*;
30
31 import java.util.regex.Pattern JavaDoc;
32 import java.util.regex.PatternSyntaxException JavaDoc;
33
34 import org.gjt.sp.jedit.msg.PropertiesChanged;
35 import org.gjt.sp.jedit.*;
36 import org.gjt.sp.jedit.bufferio.BufferLoadRequest;
37 import org.gjt.sp.jedit.bufferio.BufferSaveRequest;
38 import org.gjt.sp.jedit.bufferio.BufferInsertRequest;
39 import org.gjt.sp.jedit.bufferio.BufferIORequest;
40 import org.gjt.sp.util.Log;
41 import org.gjt.sp.util.ProgressObserver;
42 import org.gjt.sp.util.IOUtilities;
43 import org.gjt.sp.util.StandardUtilities;
44 //}}}
45

46 /**
47  * A virtual filesystem implementation.<p>
48  *
49  * Plugins can provide virtual file systems by defining entries in their
50  * <code>services.xml</code> files like so:
51  *
52  * <pre>&lt;SERVICE CLASS="org.gjt.sp.jedit.io.VFS" NAME="<i>name</i>"&gt;
53  * new <i>MyVFS</i>();
54  *&lt;/SERVICE&gt;</pre>
55  *
56  * URLs of the form <code><i>name</i>:<i>path</i></code> will then be handled
57  * by the VFS named <code><i>name</i></code>.<p>
58  *
59  * See {@link org.gjt.sp.jedit.ServiceManager} for details.<p>
60  *
61  * <h3>Session objects:</h3>
62  *
63  * A session is used to persist things like login information, any network
64  * sockets, etc. File system implementations that do not need this kind of
65  * persistence return a dummy object as a session.<p>
66  *
67  * Methods whose names are prefixed with "_" expect to be given a
68  * previously-obtained session object. A session must be obtained from the AWT
69  * thread in one of two ways:
70  *
71  * <ul>
72  * <li>{@link #createVFSSession(String,Component)}</li>
73  * <li>{@link #showBrowseDialog(Object[],Component)}</li>
74  * </ul>
75  *
76  * When done, the session must be disposed of using
77  * {@link #_endVFSSession(Object,Component)}.<p>
78  *
79  * <h3>Thread safety:</h3>
80  *
81  * The following methods cannot be called from an I/O thread:
82  *
83  * <ul>
84  * <li>{@link #createVFSSession(String,Component)}</li>
85  * <li>{@link #insert(View,Buffer,String)}</li>
86  * <li>{@link #load(View,Buffer,String)}</li>
87  * <li>{@link #save(View,Buffer,String)}</li>
88  * <li>{@link #showBrowseDialog(Object[],Component)}</li>
89  * </ul>
90  *
91  * All remaining methods are required to be thread-safe in subclasses.
92  *
93  * <h3>Implementing a VFS</h3>
94  *
95  * You can override as many or as few methods as you want. Make sure
96  * {@link #getCapabilities()} returns a value reflecting the functionality
97  * implemented by your VFS.
98  *
99  * @see VFSManager#getVFSForPath(String)
100  * @see VFSManager#getVFSForProtocol(String)
101  *
102  * @author Slava Pestov
103  * @author $Id: VFS.java 8687 2007-01-20 10:07:37Z vampire0 $
104  */

105 public abstract class VFS
106 {
107     //{{{ Capabilities
108

109     /**
110      * Read capability.
111      * @since jEdit 2.6pre2
112      */

113     public static final int READ_CAP = 1 << 0;
114
115     /**
116      * Write capability.
117      * @since jEdit 2.6pre2
118      */

119     public static final int WRITE_CAP = 1 << 1;
120
121     /**
122      * @deprecated Do not define this capability.<p>
123      *
124      * This was the official API for adding items to a file
125      * system browser's <b>Plugins</b> menu in jEdit 4.1 and earlier. In
126      * jEdit 4.2, there is a different way of doing this, you must provide
127      * a <code>browser.actions.xml</code> file in your plugin JAR, and
128      * define <code>plugin.<i>class</i>.browser-menu-item</code>
129      * or <code>plugin.<i>class</i>.browser-menu</code> properties.
130      * See {@link org.gjt.sp.jedit.EditPlugin} for details.
131      */

132     public static final int BROWSE_CAP = 1 << 2;
133
134     /**
135      * Delete file capability.
136      * @since jEdit 2.6pre2
137      */

138     public static final int DELETE_CAP = 1 << 3;
139
140     /**
141      * Rename file capability.
142      * @since jEdit 2.6pre2
143      */

144     public static final int RENAME_CAP = 1 << 4;
145
146     /**
147      * Make directory capability.
148      * @since jEdit 2.6pre2
149      */

150     public static final int MKDIR_CAP = 1 << 5;
151
152     /**
153      * Low latency capability. If this is not set, then a confirm dialog
154      * will be shown before doing a directory search in this VFS.
155      * @since jEdit 4.1pre1
156      */

157     public static final int LOW_LATENCY_CAP = 1 << 6;
158
159     /**
160      * Case insensitive file system capability.
161      * @since jEdit 4.1pre1
162      */

163     public static final int CASE_INSENSITIVE_CAP = 1 << 7;
164
165     //}}}
166

167     //{{{ Extended attributes
168
/**
169      * File type.
170      * @since jEdit 4.2pre1
171      */

172     public static final String JavaDoc EA_TYPE = "type";
173
174     /**
175      * File status (read only, read write, etc).
176      * @since jEdit 4.2pre1
177      */

178     public static final String JavaDoc EA_STATUS = "status";
179
180     /**
181      * File size.
182      * @since jEdit 4.2pre1
183      */

184     public static final String JavaDoc EA_SIZE = "size";
185
186     /**
187      * File last modified date.
188      * @since jEdit 4.2pre1
189      */

190     public static final String JavaDoc EA_MODIFIED = "modified";
191     //}}}
192

193     public static int IOBUFSIZE = 32678;
194
195     //{{{ VFS constructor
196
/**
197      * @deprecated Use the form where the constructor takes a capability
198      * list.
199      */

200     public VFS(String JavaDoc name)
201     {
202         this(name,0);
203     } //}}}
204

205     //{{{ VFS constructor
206
/**
207      * Creates a new virtual filesystem.
208      * @param name The name
209      * @param caps The capabilities
210      */

211     public VFS(String JavaDoc name, int caps)
212     {
213         this.name = name;
214         this.caps = caps;
215         // reasonable defaults (?)
216
this.extAttrs = new String JavaDoc[] { EA_SIZE, EA_TYPE };
217     } //}}}
218

219     //{{{ VFS constructor
220
/**
221      * Creates a new virtual filesystem.
222      * @param name The name
223      * @param caps The capabilities
224      * @param extAttrs The extended attributes
225      * @since jEdit 4.2pre1
226      */

227     public VFS(String JavaDoc name, int caps, String JavaDoc[] extAttrs)
228     {
229         this.name = name;
230         this.caps = caps;
231         this.extAttrs = extAttrs;
232     } //}}}
233

234     //{{{ getName() method
235
/**
236      * Returns this VFS's name. The name is used to obtain the
237      * label stored in the <code>vfs.<i>name</i>.label</code>
238      * property.
239      */

240     public String JavaDoc getName()
241     {
242         return name;
243     } //}}}
244

245     //{{{ getCapabilities() method
246
/**
247      * Returns the capabilities of this VFS.
248      * @since jEdit 2.6pre2
249      */

250     public int getCapabilities()
251     {
252         return caps;
253     } //}}}
254

255     //{{{ getExtendedAttributes() method
256
/**
257      * Returns the extended attributes supported by this VFS.
258      * @since jEdit 4.2pre1
259      */

260     public String JavaDoc[] getExtendedAttributes()
261     {
262         return extAttrs;
263     } //}}}
264

265     //{{{ showBrowseDialog() method
266
/**
267      * Displays a dialog box that should set up a session and return
268      * the initial URL to browse.
269      * @param session Where the VFS session will be stored
270      * @param comp The component that will parent error dialog boxes
271      * @return The URL
272      * @since jEdit 2.7pre1
273      */

274     public String JavaDoc showBrowseDialog(Object JavaDoc[] session, Component JavaDoc comp)
275     {
276         return null;
277     } //}}}
278

279     //{{{ getFileName() method
280
/**
281      * Returns the file name component of the specified path.
282      * @param path The path
283      * @since jEdit 3.1pre4
284      */

285     public String JavaDoc getFileName(String JavaDoc path)
286     {
287         if(path.equals("/"))
288             return path;
289
290         while(path.endsWith("/") || path.endsWith(File.separator))
291             path = path.substring(0,path.length() - 1);
292
293         int index = Math.max(path.lastIndexOf('/'),
294             path.lastIndexOf(File.separatorChar));
295         if(index == -1)
296             index = path.indexOf(':');
297
298         // don't want getFileName("roots:") to return ""
299
if(index == -1 || index == path.length() - 1)
300             return path;
301
302         return path.substring(index + 1);
303     } //}}}
304

305     //{{{ getParentOfPath() method
306
/**
307      * Returns the parent of the specified path. This must be
308      * overridden to return a non-null value for browsing of this
309      * filesystem to work.
310      * @param path The path
311      * @since jEdit 2.6pre5
312      */

313     public String JavaDoc getParentOfPath(String JavaDoc path)
314     {
315         // ignore last character of path to properly handle
316
// paths like /foo/bar/
317
int lastIndex = path.length() - 1;
318         while(lastIndex > 0
319             && (path.charAt(lastIndex) == File.separatorChar
320             || path.charAt(lastIndex) == '/'))
321         {
322             lastIndex--;
323         }
324
325         int count = Math.max(0,lastIndex);
326         int index = path.lastIndexOf(File.separatorChar,count);
327         if(index == -1)
328             index = path.lastIndexOf('/',count);
329         if(index == -1)
330         {
331             // this ensures that getFileParent("protocol:"), for
332
// example, is "protocol:" and not "".
333
index = path.lastIndexOf(':');
334         }
335
336         return path.substring(0,index + 1);
337     } //}}}
338

339     //{{{ constructPath() method
340
/**
341      * Constructs a path from the specified directory and
342      * file name component. This must be overridden to return a
343      * non-null value, otherwise browsing this filesystem will
344      * not work.<p>
345      *
346      * Unless you are writing a VFS, this method should not be called
347      * directly. To ensure correct behavior, you <b>must</b> call
348      * {@link org.gjt.sp.jedit.MiscUtilities#constructPath(String,String)}
349      * instead.
350      *
351      * @param parent The parent directory
352      * @param path The path
353      * @since jEdit 2.6pre2
354      */

355     public String JavaDoc constructPath(String JavaDoc parent, String JavaDoc path)
356     {
357         return parent + path;
358     } //}}}
359

360     //{{{ getFileSeparator() method
361
/**
362      * Returns the file separator used by this VFS.
363      * @since jEdit 2.6pre9
364      */

365     public char getFileSeparator()
366     {
367         return '/';
368     } //}}}
369

370     //{{{ getTwoStageSaveName() method
371
/**
372      * Returns a temporary file name based on the given path.
373      *
374      * By default jEdit first saves a file to <code>#<i>name</i>#save#</code>
375      * and then renames it to the original file. However some virtual file
376      * systems might not support the <code>#</code> character in filenames,
377      * so this method permits the VFS to override this behavior.
378      *
379      * If this method returns <code>null</code>, two stage save will not
380      * be used for that particular file (introduced in jEdit 4.3pre1).
381      *
382      * @param path The path name
383      * @since jEdit 4.1pre7
384      */

385     public String JavaDoc getTwoStageSaveName(String JavaDoc path)
386     {
387         return MiscUtilities.constructPath(getParentOfPath(path),
388             '#' + getFileName(path) + "#save#");
389     } //}}}
390

391     //{{{ reloadDirectory() method
392
/**
393      * Called before a directory is reloaded by the file system browser.
394      * Can be used to flush a cache, etc.
395      * @since jEdit 4.0pre3
396      */

397     public void reloadDirectory(String JavaDoc path) {} //}}}
398

399     //{{{ createVFSSession() method
400
/**
401      * Creates a VFS session. This method is called from the AWT thread,
402      * so it should not do any I/O. It could, however, prompt for
403      * a login name and password, for example.
404      * @param path The path in question
405      * @param comp The component that will parent any dialog boxes shown
406      * @return The session. The session can be null if there were errors
407      * @since jEdit 2.6pre3
408      */

409     public Object JavaDoc createVFSSession(String JavaDoc path, Component JavaDoc comp)
410     {
411         return new Object JavaDoc();
412     } //}}}
413

414     //{{{ load() method
415
/**
416      * Loads the specified buffer. The default implementation posts
417      * an I/O request to the I/O thread.
418      * @param view The view
419      * @param buffer The buffer
420      * @param path The path
421      */

422     public boolean load(View view, Buffer buffer, String JavaDoc path)
423     {
424         if((getCapabilities() & READ_CAP) == 0)
425         {
426             VFSManager.error(view,path,"vfs.not-supported.load",new String JavaDoc[] { name });
427             return false;
428         }
429
430         Object JavaDoc session = createVFSSession(path,view);
431         if(session == null)
432             return false;
433
434         if((getCapabilities() & WRITE_CAP) == 0)
435             buffer.setReadOnly(true);
436
437         BufferIORequest request = new BufferLoadRequest(
438             view,buffer,session,this,path);
439         if(buffer.isTemporary())
440             // this makes HyperSearch much faster
441
request.run();
442         else
443             VFSManager.runInWorkThread(request);
444
445         return true;
446     } //}}}
447

448     //{{{ save() method
449
/**
450      * Saves the specifies buffer. The default implementation posts
451      * an I/O request to the I/O thread.
452      * @param view The view
453      * @param buffer The buffer
454      * @param path The path
455      */

456     public boolean save(View view, Buffer buffer, String JavaDoc path)
457     {
458         if((getCapabilities() & WRITE_CAP) == 0)
459         {
460             VFSManager.error(view,path,"vfs.not-supported.save",new String JavaDoc[] { name });
461             return false;
462         }
463
464         Object JavaDoc session = createVFSSession(path,view);
465         if(session == null)
466             return false;
467
468         /* When doing a 'save as', the path to save to (path)
469          * will not be the same as the buffer's previous path
470          * (buffer.getPath()). In that case, we want to create
471          * a backup of the new path, even if the old path was
472          * backed up as well (BACKED_UP property set) */

473         if(!path.equals(buffer.getPath()))
474             buffer.unsetProperty(Buffer.BACKED_UP);
475
476         VFSManager.runInWorkThread(new BufferSaveRequest(
477             view,buffer,session,this,path));
478         return true;
479     } //}}}
480

481     //{{{ copy() method
482
/**
483      * Copy a file to another using VFS.
484      *
485      * @param progress the progress observer. It could be null if you don't want to monitor progress. If not null
486      * you should probably launch this command in a WorkThread
487      * @param sourceVFS the source VFS
488      * @param sourceSession the VFS session
489      * @param sourcePath the source path
490      * @param targetVFS the target VFS
491      * @param targetSession the target session
492      * @param targetPath the target path
493      * @param comp comp The component that will parent error dialog boxes
494      * @return true if the copy was successful
495      * @throws IOException IOException If an I/O error occurs
496      * @since jEdit 4.3pre3
497      */

498     public static boolean copy(ProgressObserver progress, VFS sourceVFS, Object JavaDoc sourceSession,String JavaDoc sourcePath,
499         VFS targetVFS, Object JavaDoc targetSession,String JavaDoc targetPath, Component JavaDoc comp, boolean canStop)
500     throws IOException
501     {
502         if (progress != null)
503             progress.setStatus("Initializing");
504
505         InputStream in = null;
506         OutputStream out = null;
507         try
508         {
509             if (progress != null)
510             {
511                 VFSFile sourceVFSFile = sourceVFS._getFile(sourceSession, sourcePath, comp);
512                 if (sourceVFSFile == null)
513                     throw new FileNotFoundException(sourcePath);
514
515                 progress.setMaximum(sourceVFSFile.getLength());
516             }
517             in = new BufferedInputStream(sourceVFS._createInputStream(sourceSession, sourcePath, false, comp));
518             out = new BufferedOutputStream(targetVFS._createOutputStream(targetSession, targetPath, comp));
519             boolean copyResult = IOUtilities.copyStream(IOBUFSIZE, progress, in, out, canStop);
520             VFSManager.sendVFSUpdate(targetVFS, targetPath, true);
521             return copyResult;
522         }
523         finally
524         {
525             IOUtilities.closeQuietly(in);
526             IOUtilities.closeQuietly(out);
527         }
528     } //}}}
529

530     //{{{ copy() method
531
/**
532      * Copy a file to another using VFS.
533      *
534      * @param progress the progress observer. It could be null if you don't want to monitor progress. If not null
535      * you should probably launch this command in a WorkThread
536      * @param sourcePath the source path
537      * @param targetPath the target path
538      * @param comp comp The component that will parent error dialog boxes
539      * @param canStop if true the copy can be stopped
540      * @return true if the copy was successful
541      * @throws IOException IOException If an I/O error occurs
542      * @since jEdit 4.3pre3
543      */

544     public static boolean copy(ProgressObserver progress, String JavaDoc sourcePath,String JavaDoc targetPath, Component JavaDoc comp, boolean canStop)
545     throws IOException
546     {
547         VFS sourceVFS = VFSManager.getVFSForPath(sourcePath);
548         Object JavaDoc sourceSession = sourceVFS.createVFSSession(sourcePath, comp);
549         if (sourceSession == null)
550         {
551             Log.log(Log.WARNING, VFS.class, "Unable to get a valid session from " + sourceVFS + " for path " + sourcePath);
552             return false;
553         }
554         VFS targetVFS = VFSManager.getVFSForPath(targetPath);
555         Object JavaDoc targetSession = targetVFS.createVFSSession(targetPath, comp);
556         if (targetSession == null)
557         {
558             Log.log(Log.WARNING, VFS.class, "Unable to get a valid session from " + targetVFS + " for path " + targetPath);
559             return false;
560         }
561         return copy(progress, sourceVFS, sourceSession, sourcePath, targetVFS, targetSession, targetPath, comp,canStop);
562     } //}}}
563

564     //{{{ insert() method
565
/**
566      * Inserts a file into the specified buffer. The default implementation
567      * posts an I/O request to the I/O thread.
568      * @param view The view
569      * @param buffer The buffer
570      * @param path The path
571      */

572     public boolean insert(View view, Buffer buffer, String JavaDoc path)
573     {
574         if((getCapabilities() & READ_CAP) == 0)
575         {
576             VFSManager.error(view,path,"vfs.not-supported.load",new String JavaDoc[] { name });
577             return false;
578         }
579
580         Object JavaDoc session = createVFSSession(path,view);
581         if(session == null)
582             return false;
583
584         VFSManager.runInWorkThread(new BufferInsertRequest(
585             view,buffer,session,this,path));
586         return true;
587     } //}}}
588

589     // A method name that starts with _ requires a session object
590

591     //{{{ _canonPath() method
592
/**
593      * Returns the canonical form of the specified path name. For example,
594      * <code>~</code> might be expanded to the user's home directory.
595      * @param session The session
596      * @param path The path
597      * @param comp The component that will parent error dialog boxes
598      * @exception IOException if an I/O error occurred
599      * @since jEdit 4.0pre2
600      */

601     public String JavaDoc _canonPath(Object JavaDoc session, String JavaDoc path, Component JavaDoc comp)
602         throws IOException
603     {
604         return path;
605     } //}}}
606

607     //{{{ _listDirectory() method
608
/**
609      * A convinience method that matches file names against globs, and can
610      * optionally list the directory recursively.
611      * @param session The session
612      * @param directory The directory. Note that this must be a full
613      * URL, including the host name, path name, and so on. The
614      * username and password (if needed by the VFS) is obtained from the
615      * session instance.
616      * @param glob Only file names matching this glob will be returned
617      * @param recursive If true, subdirectories will also be listed.
618      * @param comp The component that will parent error dialog boxes
619      * @exception IOException if an I/O error occurred
620      * @since jEdit 4.1pre1
621      */

622     public String JavaDoc[] _listDirectory(Object JavaDoc session, String JavaDoc directory,
623         String JavaDoc glob, boolean recursive, Component JavaDoc comp )
624         throws IOException
625     {
626         String JavaDoc[] retval = null;
627         retval = _listDirectory(session, directory, glob, recursive, comp, true, false);
628         return retval;
629     }
630
631
632     //{{{ _listDirectory() method
633
/**
634      * A convinience method that matches file names against globs, and can
635      * optionally list the directory recursively.
636      * @param session The session
637      * @param directory The directory. Note that this must be a full
638      * URL, including the host name, path name, and so on. The
639      * username and password (if needed by the VFS) is obtained from the
640      * session instance.
641      * @param glob Only file names matching this glob will be returned
642      * @param recursive If true, subdirectories will also be listed.
643      * @param comp The component that will parent error dialog boxes
644      * @exception IOException if an I/O error occurred
645      * @param skipBinary ignore binary files (do not return them).
646      * This will slow down the process since it will open the files
647      * @param skipHidden skips hidden files, directories, and
648      * backup files. Ignores any file beginning with . or #, or ending with ~
649      * or .bak
650      *
651      *
652      * @since jEdit 4.3pre5
653      */

654     public String JavaDoc[] _listDirectory(Object JavaDoc session, String JavaDoc directory,
655         String JavaDoc glob, boolean recursive, Component JavaDoc comp,
656         boolean skipBinary, boolean skipHidden)
657         throws IOException
658     {
659         VFSFileFilter filter = new GlobVFSFileFilter(glob);
660         return _listDirectory(session, directory, filter,
661                       recursive, comp, skipBinary,
662                       skipHidden);
663     } //}}}
664

665     //{{{ _listDirectory() method
666
/**
667      * A convinience method that filters the directory listing
668      * according to a filter, and can optionally list the directory
669      * recursively.
670      * @param session The session
671      * @param directory The directory. Note that this must be a full
672      * URL, including the host name, path name, and so on. The
673      * username and password (if needed by the VFS) is obtained from the
674      * session instance.
675      * @param filter The {@link VFSFileFilter} to use for filtering.
676      * @param recursive If true, subdirectories will also be listed.
677      * @param comp The component that will parent error dialog boxes
678      * @exception IOException if an I/O error occurred
679      * @param skipBinary ignore binary files (do not return them).
680      * This will slow down the process since it will open the files
681      * @param skipHidden skips hidden files, directories, and
682      * backup files. Ignores any file beginning with . or #, or ending with ~
683      * or .bak
684      *
685      * @since jEdit 4.3pre7
686      */

687     public String JavaDoc[] _listDirectory(Object JavaDoc session, String JavaDoc directory,
688         VFSFileFilter filter, boolean recursive, Component JavaDoc comp,
689         boolean skipBinary, boolean skipHidden)
690         throws IOException
691     {
692         Log.log(Log.DEBUG,this,"Listing " + directory);
693         List files = new ArrayList(100);
694
695         listFiles(session,new ArrayList(),files,directory,filter,
696             recursive, comp, skipBinary, skipHidden);
697
698         String JavaDoc[] retVal = (String JavaDoc[])files.toArray(new String JavaDoc[files.size()]);
699
700         Arrays.sort(retVal,new MiscUtilities.StringICaseCompare());
701
702         return retVal;
703     } //}}}
704

705     //{{{ _listFiles() method
706
/**
707      * Lists the specified directory.
708      * @param session The session
709      * @param directory The directory. Note that this must be a full
710      * URL, including the host name, path name, and so on. The
711      * username and password (if needed by the VFS) is obtained from the
712      * session instance.
713      * @param comp The component that will parent error dialog boxes
714      * @exception IOException if an I/O error occurred
715      * @since jEdit 4.3pre2
716      */

717     public VFSFile[] _listFiles(Object JavaDoc session, String JavaDoc directory,
718         Component JavaDoc comp)
719         throws IOException
720     {
721         return _listDirectory(session,directory,comp);
722     } //}}}
723

724     //{{{ _listDirectory() method
725
/**
726      * @deprecated Use <code>_listFiles()</code> instead.
727      */

728     public DirectoryEntry[] _listDirectory(Object JavaDoc session, String JavaDoc directory,
729         Component JavaDoc comp)
730         throws IOException
731     {
732         VFSManager.error(comp,directory,"vfs.not-supported.list",new String JavaDoc[] { name });
733         return null;
734     } //}}}
735

736     //{{{ _getFile() method
737
/**
738      * Returns the specified directory entry.
739      * @param session The session
740      * @param path The path
741      * @param comp The component that will parent error dialog boxes
742      * @exception IOException if an I/O error occurred
743      * @return The specified directory entry, or null if it doesn't exist.
744      * @since jEdit 4.3pre2
745      */

746     public VFSFile _getFile(Object JavaDoc session, String JavaDoc path,
747         Component JavaDoc comp)
748         throws IOException
749     {
750         return _getDirectoryEntry(session,path,comp);
751     } //}}}
752

753     //{{{ _getDirectoryEntry() method
754
/**
755      * Returns the specified directory entry.
756      * @param session The session
757      * @param path The path
758      * @param comp The component that will parent error dialog boxes
759      * @exception IOException if an I/O error occurred
760      * @return The specified directory entry, or null if it doesn't exist.
761      * @since jEdit 2.7pre1
762      * @deprecated Use <code>_getFile()</code> instead.
763      */

764     public DirectoryEntry _getDirectoryEntry(Object JavaDoc session, String JavaDoc path,
765         Component JavaDoc comp)
766         throws IOException
767     {
768         return null;
769     } //}}}
770

771     //{{{ DirectoryEntry class
772
/**
773      * @deprecated Use <code>VFSFile</code> instead.
774      */

775     public static class DirectoryEntry extends VFSFile
776     {
777         //{{{ DirectoryEntry constructor
778
/**
779          * @since jEdit 4.2pre2
780          */

781         public DirectoryEntry()
782         {
783         } //}}}
784

785         //{{{ DirectoryEntry constructor
786
public DirectoryEntry(String JavaDoc name, String JavaDoc path, String JavaDoc deletePath,
787             int type, long length, boolean hidden)
788         {
789             this.name = name;
790             this.path = path;
791             this.deletePath = deletePath;
792             this.symlinkPath = path;
793             this.type = type;
794             this.length = length;
795             this.hidden = hidden;
796             if(path != null)
797             {
798                 // maintain backwards compatibility
799
VFS vfs = VFSManager.getVFSForPath(path);
800                 canRead = ((vfs.getCapabilities() & READ_CAP) != 0);
801                 canWrite = ((vfs.getCapabilities() & WRITE_CAP) != 0);
802             }
803         } //}}}
804
} //}}}
805

806     //{{{ _delete() method
807
/**
808      * Deletes the specified URL.
809      * @param session The VFS session
810      * @param path The path
811      * @param comp The component that will parent error dialog boxes
812      * @exception IOException if an I/O error occurs
813      * @since jEdit 2.7pre1
814      */

815     public boolean _delete(Object JavaDoc session, String JavaDoc path, Component JavaDoc comp)
816         throws IOException
817     {
818         return false;
819     } //}}}
820

821     //{{{ _rename() method
822
/**
823      * Renames the specified URL. Some filesystems might support moving
824      * URLs between directories, however others may not. Do not rely on
825      * this behavior.
826      * @param session The VFS session
827      * @param from The old path
828      * @param to The new path
829      * @param comp The component that will parent error dialog boxes
830      * @exception IOException if an I/O error occurs
831      * @since jEdit 2.7pre1
832      */

833     public boolean _rename(Object JavaDoc session, String JavaDoc from, String JavaDoc to,
834         Component JavaDoc comp) throws IOException
835     {
836         return false;
837     } //}}}
838

839     //{{{ _mkdir() method
840
/**
841      * Creates a new directory with the specified URL.
842      * @param session The VFS session
843      * @param directory The directory
844      * @param comp The component that will parent error dialog boxes
845      * @exception IOException if an I/O error occurs
846      * @since jEdit 2.7pre1
847      */

848     public boolean _mkdir(Object JavaDoc session, String JavaDoc directory, Component JavaDoc comp)
849         throws IOException
850     {
851         return false;
852     } //}}}
853

854     //{{{ _backup() method
855
/**
856      * Backs up the specified file. This should only be overriden by
857      * the local filesystem VFS.
858      * @param session The VFS session
859      * @param path The path
860      * @param comp The component that will parent error dialog boxes
861      * @exception IOException if an I/O error occurs
862      * @since jEdit 3.2pre2
863      */

864     public void _backup(Object JavaDoc session, String JavaDoc path, Component JavaDoc comp)
865         throws IOException
866     {
867     } //}}}
868

869     //{{{ _createInputStream() method
870
/**
871      * Creates an input stream. This method is called from the I/O
872      * thread.
873      * @param session the VFS session
874      * @param path The path
875      * @param ignoreErrors If true, file not found errors should be
876      * ignored
877      * @param comp The component that will parent error dialog boxes
878      * @return an inputstream or <code>null</code> if there was a problem
879      * @exception IOException If an I/O error occurs
880      * @since jEdit 2.7pre1
881      */

882     public InputStream _createInputStream(Object JavaDoc session,
883         String JavaDoc path, boolean ignoreErrors, Component JavaDoc comp)
884         throws IOException
885     {
886         VFSManager.error(comp,path,"vfs.not-supported.load",new String JavaDoc[] { name });
887         return null;
888     } //}}}
889

890     //{{{ _createOutputStream() method
891
/**
892      * Creates an output stream. This method is called from the I/O
893      * thread.
894      * @param session the VFS session
895      * @param path The path
896      * @param comp The component that will parent error dialog boxes
897      * @exception IOException If an I/O error occurs
898      * @since jEdit 2.7pre1
899      */

900     public OutputStream _createOutputStream(Object JavaDoc session,
901         String JavaDoc path, Component JavaDoc comp)
902         throws IOException
903     {
904         VFSManager.error(comp,path,"vfs.not-supported.save",new String JavaDoc[] { name });
905         return null;
906     } //}}}
907

908     //{{{ _saveComplete() method
909
/**
910      * Called after a file has been saved.
911      * @param session The VFS session
912      * @param buffer The buffer
913      * @param path The path the buffer was saved to (can be different from
914      * {@link org.gjt.sp.jedit.Buffer#getPath()} if the user invoked the
915      * <b>Save a Copy As</b> command, for example).
916      * @param comp The component that will parent error dialog boxes
917      * @exception IOException If an I/O error occurs
918      * @since jEdit 4.1pre9
919      */

920     public void _saveComplete(Object JavaDoc session, Buffer buffer, String JavaDoc path,
921         Component JavaDoc comp) throws IOException {} //}}}
922

923     //{{{ _finishTwoStageSave() method
924
/**
925      * Called after a file has been saved and we use twoStageSave (first saving to
926      * another file). This should re-apply permissions for example.
927
928      * @param session The VFS session
929      * @param buffer The buffer
930      * @param path The path the buffer was saved to (can be different from
931      * {@link org.gjt.sp.jedit.Buffer#getPath()} if the user invoked the
932      * <b>Save a Copy As</b> command, for example).
933      * @param comp The component that will parent error dialog boxes
934      * @exception IOException If an I/O error occurs
935      * @since jEdit 4.3pre4
936      */

937     public void _finishTwoStageSave(Object JavaDoc session, Buffer buffer, String JavaDoc path,
938         Component JavaDoc comp) throws IOException
939     {
940     } //}}}
941

942     //{{{ _endVFSSession() method
943
/**
944      * Finishes the specified VFS session. This must be called
945      * after all I/O with this VFS is complete, to avoid leaving
946      * stale network connections and such.
947      * @param session The VFS session
948      * @param comp The component that will parent error dialog boxes
949      * @exception IOException if an I/O error occurred
950      * @since jEdit 2.7pre1
951      */

952     public void _endVFSSession(Object JavaDoc session, Component JavaDoc comp)
953         throws IOException
954     {
955     } //}}}
956

957     //{{{ getDefaultColorFor() method
958
/**
959      * Returns color of the specified file name, by matching it against
960      * user-specified regular expressions.
961      * @since jEdit 4.0pre1
962      */

963     public static Color JavaDoc getDefaultColorFor(String JavaDoc name)
964     {
965         synchronized(lock)
966         {
967             if(colors == null)
968                 loadColors();
969
970             for(int i = 0; i < colors.size(); i++)
971             {
972                 ColorEntry entry = (ColorEntry)colors.elementAt(i);
973                 if(entry.re.matcher(name).matches())
974                     return entry.color;
975             }
976
977             return null;
978         }
979     } //}}}
980

981     //{{{ DirectoryEntryCompare class
982
/**
983      * Implementation of {@link Comparator}
984      * interface that compares {@link VFS.DirectoryEntry} instances.
985      * @since jEdit 4.2pre1
986      */

987     public static class DirectoryEntryCompare implements Comparator
988     {
989         private boolean sortIgnoreCase, sortMixFilesAndDirs;
990
991         /**
992          * Creates a new <code>DirectoryEntryCompare</code>.
993          * @param sortMixFilesAndDirs If false, directories are
994          * put at the top of the listing.
995          * @param sortIgnoreCase If false, upper case comes before
996          * lower case.
997          */

998         public DirectoryEntryCompare(boolean sortMixFilesAndDirs,
999             boolean sortIgnoreCase)
1000        {
1001            this.sortMixFilesAndDirs = sortMixFilesAndDirs;
1002            this.sortIgnoreCase = sortIgnoreCase;
1003        }
1004
1005        public int compare(Object JavaDoc obj1, Object JavaDoc obj2)
1006        {
1007            VFSFile file1 = (VFSFile)obj1;
1008            VFSFile file2 = (VFSFile)obj2;
1009
1010            if(!sortMixFilesAndDirs)
1011            {
1012                if(file1.getType() != file2.getType())
1013                    return file2.getType() - file1.getType();
1014            }
1015
1016            return StandardUtilities.compareStrings(file1.getName(),
1017                file2.getName(),sortIgnoreCase);
1018        }
1019    } //}}}
1020

1021    //{{{ Private members
1022
private String JavaDoc name;
1023    private int caps;
1024    private String JavaDoc[] extAttrs;
1025    private static Vector colors;
1026    private static Object JavaDoc lock = new Object JavaDoc();
1027
1028    //{{{ Class initializer
1029
static
1030    {
1031        EditBus.addToBus(new EBComponent()
1032        {
1033            public void handleMessage(EBMessage msg)
1034            {
1035                if(msg instanceof PropertiesChanged)
1036                {
1037                    synchronized(lock)
1038                    {
1039                        colors = null;
1040                    }
1041                }
1042            }
1043        });
1044    } //}}}
1045

1046    //{{{ recursive listFiles() method
1047
private void listFiles(Object JavaDoc session, List stack,
1048        List files, String JavaDoc directory, VFSFileFilter filter, boolean recursive,
1049        Component JavaDoc comp, boolean skipBinary, boolean skipHidden) throws IOException
1050    {
1051        if(stack.contains(directory))
1052        {
1053            Log.log(Log.ERROR,this,
1054                "Recursion in _listDirectory(): "
1055                + directory);
1056            return;
1057        }
1058
1059        stack.add(directory);
1060
1061        VFSFile[] _files = _listFiles(session,directory,
1062            comp);
1063        if(_files == null || _files.length == 0)
1064            return;
1065
1066        for(int i = 0; i < _files.length; i++)
1067        {
1068            VFSFile file = _files[i];
1069            if (skipHidden && (file.isHidden() || MiscUtilities.isBackup(file.getName())))
1070                continue;
1071            if(!filter.accept(file))
1072                continue;
1073            if(file.getType() == VFSFile.DIRECTORY
1074                || file.getType() == VFSFile.FILESYSTEM)
1075            {
1076                if(recursive)
1077                {
1078                    // resolve symlinks to avoid loops
1079
String JavaDoc canonPath = _canonPath(session,
1080                        file.getPath(),comp);
1081                    if(!MiscUtilities.isURL(canonPath))
1082                        canonPath = MiscUtilities.resolveSymlinks(canonPath);
1083
1084                    listFiles(session,stack,files,
1085                        canonPath,filter,recursive,
1086                        comp, skipBinary, skipHidden);
1087                }
1088
1089            }
1090            else // It's a regular file
1091
{
1092                if (skipBinary && file.isBinary(session))
1093                    continue;
1094
1095                Log.log(Log.DEBUG,this,file.getPath());
1096                files.add(file.getPath());
1097            }
1098        }
1099    } //}}}
1100

1101    //{{{ loadColors() method
1102
private static void loadColors()
1103    {
1104        synchronized(lock)
1105        {
1106            colors = new Vector();
1107
1108            if(!jEdit.getBooleanProperty("vfs.browser.colorize"))
1109                return;
1110
1111            String JavaDoc glob;
1112            int i = 0;
1113            while((glob = jEdit.getProperty("vfs.browser.colors." + i + ".glob")) != null)
1114            {
1115                try
1116                {
1117                    colors.addElement(new ColorEntry(
1118                        Pattern.compile(StandardUtilities.globToRE(glob)),
1119                        jEdit.getColorProperty(
1120                        "vfs.browser.colors." + i + ".color",
1121                        Color.black)));
1122                }
1123                catch(PatternSyntaxException JavaDoc e)
1124                {
1125                    Log.log(Log.ERROR,VFS.class,"Invalid regular expression: "
1126                        + glob);
1127                    Log.log(Log.ERROR,VFS.class,e);
1128                }
1129
1130                i++;
1131            }
1132        }
1133    } //}}}
1134

1135    //{{{ ColorEntry class
1136
static class ColorEntry
1137    {
1138        Pattern JavaDoc re;
1139        Color JavaDoc color;
1140
1141        ColorEntry(Pattern JavaDoc re, Color JavaDoc color)
1142        {
1143            this.re = re;
1144            this.color = color;
1145        }
1146    } //}}}
1147

1148    //}}}
1149
}
1150
Popular Tags