products/Sources/formale Sprachen/Java/openjdk-20-36_src/test/jdk/sun/security/krb5/config image not shown  

Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: VFS.java   Sprache: Unknown

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


package org.gjt.sp.jedit.io;

//{{{ Imports
import java.awt.Color;
import java.awt.Component;
import java.io.*;
import java.io.Closeable;
import java.util.*;

import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.gjt.sp.jedit.msg.PropertiesChanged;
import org.gjt.sp.jedit.*;
import org.gjt.sp.jedit.bufferio.BufferLoadRequest;
import org.gjt.sp.jedit.bufferio.BufferSaveRequest;
import org.gjt.sp.jedit.bufferio.BufferInsertRequest;
import org.gjt.sp.util.Log;
import org.gjt.sp.util.ProgressObserver;
import org.gjt.sp.util.IOUtilities;
import org.gjt.sp.util.StandardUtilities;
import org.gjt.sp.util.Task;
import org.gjt.sp.util.ThreadUtilities;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
//}}}

/**
 * A virtual filesystem implementation.<p>
 *
 * Plugins can provide virtual file systems by defining entries in their
 * <code>services.xml</code> files like so:
 *
 * <pre><SERVICE CLASS="org.gjt.sp.jedit.io.VFS" NAME="<i>name</i>">
 *    new <i>MyVFS</i>();
 *</SERVICE></pre>
 *
 * URLs of the form <code><i>name</i>:<i>path</i></code> will then be handled
 * by the VFS named <code><i>name</i></code>.<p>
 *
 * See {@link org.gjt.sp.jedit.ServiceManager} for details.<p>
 *
 * <h3>Session objects:</h3>
 *
 * A session is used to persist things like login information, any network
 * sockets, etc. File system implementations that do not need this kind of
 * persistence return a dummy object as a session.<p>
 *
 * Methods whose names are prefixed with "_" expect to be given a
 * previously-obtained session object. A session must be obtained with
 * this method:
 *
 * <ul>
 * <li>{@link #createVFSSession(String,Component)}</li>
 * </ul>
 *
 * That method should be called from the AWT (EDT) thread, unless
 * the filesystem has <code>NON_AWT_SESSION_CAP</code> capability.<p>
 *
 * When done, the session must be disposed of using
 * {@link #_endVFSSession(Object,Component)}.<p>
 *
 * <h3>Thread safety:</h3>
 *
 * The following methods cannot be called from an I/O thread:
 *
 * <ul>
 * <li>{@link #createVFSSession(String,Component)} - unless
 *     <code>NON_AWT_SESSION_CAP</code> capability is set</li>
 * <li>{@link #insert(View,Buffer,String)}</li>
 * <li>{@link #load(View,Buffer,String,boolean)}</li>
 * <li>{@link #save(View,Buffer,String)}</li>
 * </ul>
 *
 * All remaining methods are required to be thread-safe in subclasses.
 *
 * <h3>Implementing a VFS</h3>
 *
 * You can override as many or as few methods as you want. Make sure
 * {@link #getCapabilities()} returns a value reflecting the functionality
 * implemented by your VFS.
 *
 * @see VFSManager#getVFSForPath(String)
 * @see VFSManager#getVFSForProtocol(String)
 *
 * @author Slava Pestov
 * @author $Id: VFS.java 25330 2020-05-09 14:21:52Z kpouer $
 */

public abstract class VFS
{
 //{{{ Capabilities
 /**
 * Read capability.
 * @since jEdit 2.6pre2
 */

 public static final int READ_CAP = 1 << 0;

 /**
 * Write capability.
 * @since jEdit 2.6pre2
 */

 public static final int WRITE_CAP = 1 << 1;

 /**
 * Browse capability
 * @since jEdit 4.3pre11
 *
 * This was the official API for adding items to a file
 * system browser's <b>Plugins</b> menu in jEdit 4.1 and earlier. In
 * jEdit 4.2, there is a different way of doing this, you must provide
 * a <code>browser.actions.xml</code> file in your plugin JAR, and
 * define <code>plugin.<i>class</i>.browser-menu-item</code>
 * or <code>plugin.<i>class</i>.browser-menu</code> properties.
 * See {@link org.gjt.sp.jedit.EditPlugin} for details.
 */

 public static final int BROWSE_CAP = 1 << 2;

 /**
 * Delete file capability.
 * @since jEdit 2.6pre2
 */

 public static final int DELETE_CAP = 1 << 3;

 /**
 * Rename file capability.
 * @since jEdit 2.6pre2
 */

 public static final int RENAME_CAP = 1 << 4;

 /**
 * Make directory capability.
 * @since jEdit 2.6pre2
 */

 public static final int MKDIR_CAP = 1 << 5;

 /**
 * Low latency capability. If this is not set, then a confirm dialog
 * will be shown before doing a directory search in this VFS.
 * @since jEdit 4.1pre1
 */

 public static final int LOW_LATENCY_CAP = 1 << 6;

 /**
 * Case insensitive file system capability.
 * @since jEdit 4.1pre1
 */

 public static final int CASE_INSENSITIVE_CAP = 1 << 7;

 /**
 * Sessions created outside Event Dispatching Thread -
 * file system capability. Set for the file system that does not
 * require that <code>createVFSSession</code> is called on edt.
 * All systems that do not implement <code>createVFSSession</code>
 * should set it, but others may too.
 * @since jEdit 5.0pre1
 */

 public static final int NON_AWT_SESSION_CAP = 1 << 8;
 //}}}

 //{{{ Extended attributes
 /**
 * File type.
 * @since jEdit 4.2pre1
 */

 public static final String EA_TYPE = "type";

 /**
 * File status (read only, read write, etc).
 * @since jEdit 4.2pre1
 */

 public static final String EA_STATUS = "status";

 /**
 * File size.
 * @since jEdit 4.2pre1
 */

 public static final String EA_SIZE = "size";

 /**
 * File last modified date.
 * @since jEdit 4.2pre1
 */

 public static final String EA_MODIFIED = "modified";
 //}}}

 public static final int IOBUFSIZE = 32678;

 //{{{ VFS constructors
 /**
 * Creates a new virtual filesystem.
 * @param name The name
 * @param caps The capabilities
 */

 protected VFS(String name, int caps)
 {
  this.name = name;
  this.caps = caps;
  // reasonable defaults (?)
  extAttrs = new String[] { EA_SIZE, EA_TYPE };
 }

 /**
 * Creates a new virtual filesystem.
 * @param name The name
 * @param caps The capabilities
 * @param extAttrs The extended attributes
 * @since jEdit 4.2pre1
 */

 protected VFS(String name, int caps, String[] extAttrs)
 {
  this.name = name;
  this.caps = caps;
  this.extAttrs = extAttrs;
 } //}}}

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

 public String getName()
 {
  return name;
 } //}}}

 //{{{ getCapabilities() method
 /**
 * Returns the capabilities of this VFS.
 * @since jEdit 2.6pre2
 */

 public int getCapabilities()
 {
  return caps;
 } //}}}

 //{{{ isMarkersFileSupported() method
 /**
 * Returns if an additional markers file can be saved by this VFS.
 * Default is {@code true}.
 *
 * @since jEdit 4.3pre10
 */

 public boolean isMarkersFileSupported()
 {
  return true;
 } //}}}

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

 public String[] getExtendedAttributes()
 {
  return extAttrs;
 } //}}}

 //{{{ getFileName() method
 /**
 * Returns the file name component of the specified path.
 * @param path The path
 * @since jEdit 3.1pre4
 */

 public String getFileName(String path)
 {
  if(path.equals("/"))
   return path;

  while(path.endsWith("/") || path.endsWith(File.separator))
   path = path.substring(0,path.length() - 1);

  int index = Math.max(path.lastIndexOf('/'),
   path.lastIndexOf(File.separatorChar));
  if(index == -1)
   index = path.indexOf(':');

  // don't want getFileName("roots:") to return ""
  if(index == -1 || index == path.length() - 1)
   return path;

  return path.substring(index + 1);
 } //}}}

 //{{{ getFilePath() method
 /**
 * Returns the path component of the specified VFS path.
 * The standard implementation cuts off the protocol
 * and the protocol separator character and then delegates
 * to eventually present sub-VFS-paths present in the VFS path
 * like "jode:archive:/test.zip!/test.txt".
 * <p>
 * If a VFS implementation can have additional
 * information in the VFS path like username / password / host / port
 * for FTP VFS or archive filename for archive VFS, this
 * method should be overridden to remove those information also.
 * The easiest would be to remove those additional information
 * and then delegate to {@code super.getFilePath()}.
 *
 * @param vfsPath The VFS path
 * @since jEdit 4.5pre1
 */

 public String getFilePath(String vfsPath)
 {
  if (!MiscUtilities.isURL(vfsPath))
   return vfsPath;

  String filePath = vfsPath.substring(MiscUtilities.getProtocolOfURL(vfsPath).length() + 1);

  return VFSManager.getVFSForPath(filePath).getFilePath(filePath);
 } //}}}

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

 @Nonnull
 public String getParentOfPath(String path)
 {
  // ignore last character of path to properly handle
  // paths like /foo/bar/
  int lastIndex = path.length() - 1;
  while(lastIndex > 0
   && (path.charAt(lastIndex) == File.separatorChar
   || path.charAt(lastIndex) == '/'))
  {
   lastIndex--;
  }

  int count = Math.max(0,lastIndex);
  int index = path.lastIndexOf(File.separatorChar,count);
  if(index == -1)
   index = path.lastIndexOf('/',count);
  if(index == -1)
  {
   // this ensures that getFileParent("protocol:"), for
   // example, is "protocol:" and not "".
   index = path.lastIndexOf(':');
  }

  return path.substring(0,index + 1);
 } //}}}

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

 public String constructPath(String parent, String path)
 {
  return parent + path;
 } //}}}

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

 public char getFileSeparator()
 {
  return '/';
 } //}}}

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

 @Nullable
 public String getTwoStageSaveName(String path)
 {
  return MiscUtilities.constructPath(getParentOfPath(path),
   '#' + getFileName(path) + "#save#");
 } //}}}

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

 public void reloadDirectory(String path) {} //}}}

 //{{{ createVFSSession() methods
 /**
 * Creates a VFS session. This method is called from the AWT thread,
 * so it should not do any I/O. It could, however, prompt for
 * a login name and password, for example. A simpler filesystem
 * may set the <code>NON_AWT_SESSION_CAP</code> capability. When set,
 * sessions may be obtained from any thread.
 * @param path The path in question
 * @param comp The component that will parent any dialog boxes shown
 * @return The session. The session can be null if there were errors
 * @since jEdit 2.6pre3
 */

 public Object createVFSSession(String path, Component comp)
 {
  return new Object();
 }

 /**
* Same as {@link #createVFSSession}, but may be called from any
* thread. It first checks the <code>NON_AWT_SESSION_CAP</code>
* capability and enters EDT thread if necessary.
*/

 public Object createVFSSessionSafe(final String path,
                                    final Component comp)
 {
  Object session;
  if ((getCapabilities() & NON_AWT_SESSION_CAP) != 0)
  {
   session = createVFSSession(path, comp);
  }
  else
  {
   SessionGetter getter = new SessionGetter(path, comp);
   ThreadUtilities.runInDispatchThreadAndWait(getter);
   session = getter.get();
  }
  return session;
 }
 //}}}

 //{{{ load() method
 /**
 * Loads the specified buffer. The default implementation posts
 * an I/O request to the I/O thread.
 * @param view The view
 * @param buffer The buffer
 * @param path The path
 * @param untitled is the buffer untitled
 */

 public boolean load(View view, Buffer buffer, String path, boolean untitled)
 {
  if((getCapabilities() & READ_CAP) == 0)
  {
   VFSManager.error(view,path,"vfs.not-supported.load",new String[] { name });
   return false;
  }

  Object session = createVFSSession(path,view);
  if(session == null)
   return false;

  if((getCapabilities() & WRITE_CAP) == 0)
   buffer.setReadOnly(true);

  Task request = new BufferLoadRequest(view, buffer, session, this, path, untitled);
  if(buffer.isTemporary())
   // this makes HyperSearch much faster
   request.run();
  else
   // BufferLoadRequest can cause UI interations (for example FTP connection dialog),
   // so it should be runned in Dispatch thread
   //ThreadUtilities.runInDispatchThread(request);
   ThreadUtilities.runInBackground(request);

  return true;
 } //}}}

 //{{{ save() method
 /**
 * Saves the specifies buffer. The default implementation posts
 * an I/O request to the I/O thread.
 * @param view The view
 * @param buffer The buffer
 * @param path The path
 */

 public boolean save(View view, Buffer buffer, String path)
 {
  if((getCapabilities() & WRITE_CAP) == 0)
  {
   VFSManager.error(view,path,"vfs.not-supported.save",new String[] { name });
   return false;
  }

  Object session = createVFSSession(path,view);
  if(session == null)
   return false;

  /* When doing a 'save as', the path to save to (path)
 * will not be the same as the buffer's previous path
 * (buffer.getPath()). In that case, we want to create
 * a backup of the new path, even if the old path was
 * backed up as well (BACKED_UP property set) */

  if(!path.equals(buffer.getPath()))
   buffer.unsetProperty(Buffer.BACKED_UP);

  ThreadUtilities.runInBackground(new BufferSaveRequest(
   view,buffer,session,this,path));
  return true;
 } //}}}

 //{{{ copy() methods
 /**
 * Copy a file to another using VFS.
 *
 * @param progress the progress observer. It could be null if you don't want to monitor progress. If not null
 *                  you should probably launch this command in a WorkThread
 * @param sourceVFS the source VFS
 * @param sourceSession the VFS session
 * @param sourcePath the source path. It must be a file and must exists
 * @param targetVFS the target VFS
 * @param targetSession the target session
 * @param targetPath the target path.
 * If it is a path, it must exists, if it is a file, the parent must
 * exists
 * @param comp The component that will parent error dialog boxes
 * @param canStop could this copy be stopped ?
 * @return true if the copy was successful
 * @throws IOException  IOException If an I/O error occurs
 * @since jEdit 4.3pre3
 */

 public static boolean copy(ProgressObserver progress, VFS sourceVFS, Object sourceSession,String sourcePath,
       VFS targetVFS, Object targetSession,String targetPath, Component comp, boolean canStop)
  throws IOException
 {
  return copy(progress, sourceVFS, sourceSession, sourcePath, targetVFS, targetSession, targetPath,
       comp, canStop, true);
 }

 /**
 * Copy a file to another using VFS.
 *
 * @param progress the progress observer. It could be null if you don't want to monitor progress. If not null
 *                  you should probably launch this command in a WorkThread
 * @param sourceVFS the source VFS
 * @param sourceSession the VFS session
 * @param sourcePath the source path. It must be a file and must exists
 * @param targetVFS the target VFS
 * @param targetSession the target session
 * @param targetPath the target path.
 * If it is a path, it must exists, if it is a file, the parent must
 * exists
 * @param comp The component that will parent error dialog boxes
 * @param canStop could this copy be stopped ?
 * @param sendVFSUpdate true if you want to send a VFS update after the copy. False otherwise (if you do a lot
 *                      of copy)
 * @return true if the copy was successful
 * @throws IOException  IOException If an I/O error occurs
 * @since jEdit 5.0
 */

 public static boolean copy(ProgressObserver progress, VFS sourceVFS, Object sourceSession,String sourcePath,
  VFS targetVFS, Object targetSession,String targetPath, Component comp, boolean canStop,
  boolean sendVFSUpdate)
 throws IOException
 {
  if (sourcePath.equals(targetPath))
  {
   Log.log(Log.WARNING, VFS.class,
    jEdit.getProperty("ioerror.copy-self",
     new Object[] { sourcePath }));
   return false;
  }
  if (progress != null)
   progress.setStatus("Initializing");

  InputStream in = null;
  OutputStream out = null;
  try
  {
   VFSFile sourceVFSFile = sourceVFS._getFile(sourceSession, sourcePath, comp);
   if (sourceVFSFile == null)
    throw new FileNotFoundException("source path " + sourcePath + " doesn't exists");
   if (progress != null)
   {
    progress.setMaximum(sourceVFSFile.getLength());
   }
   VFSFile targetVFSFile = targetVFS._getFile(targetSession, targetPath, comp);
   if (targetVFSFile == null)
   {
    String parentTargetPath = MiscUtilities.getParentOfPath(targetPath);
    VFSFile parentTargetVFSFile = targetVFS._getFile(targetSession, parentTargetPath, comp);
    if (parentTargetVFSFile == null)
     throw new FileNotFoundException("target path " + parentTargetPath +
      " doesn't exists");
    if (parentTargetVFSFile.getType() == VFSFile.DIRECTORY)
    {
     String targetFilename = MiscUtilities.getFileName(targetPath);
     targetPath = MiscUtilities.constructPath(parentTargetPath, targetFilename);
    }
    else
    {
     throw new IOException("The parent of target path is a file");
    }
   }
   else if (targetVFSFile.getType() == VFSFile.DIRECTORY)
   {
    if (targetVFSFile.getPath().equals(sourceVFSFile.getPath()))
     return false;
    targetPath = MiscUtilities.constructPath(targetPath, sourceVFSFile.getName());
   }
   in = new BufferedInputStream(sourceVFS._createInputStream(sourceSession, sourcePath, false, comp));
   out = new BufferedOutputStream(targetVFS._createOutputStream(targetSession, targetPath, comp));
   boolean copyResult = IOUtilities.copyStream(IOBUFSIZE, progress, in, out, canStop);
   if (sendVFSUpdate)
    VFSManager.sendVFSUpdate(targetVFS, targetPath, true);
   return copyResult;
  }
  finally
  {
   IOUtilities.closeQuietly((Closeable)in);
   IOUtilities.closeQuietly((Closeable)out);
  }
 }

 /**
 * Copy a file to another using VFS.
 *
 * @param progress the progress observer. It could be null if you don't want to monitor progress. If not null
 *                  you should probably launch this command in a WorkThread
 * @param sourcePath the source path
 * @param targetPath the target path
 * @param comp The component that will parent error dialog boxes
 * @param canStop if true the copy can be stopped
 * @param sendVFSUpdate true if you want to send a VFS update after the copy. False otherwise (if you do a lot
 *                      of copy)
 * @return true if the copy was successful
 * @throws IOException IOException If an I/O error occurs
 * @since jEdit 5.0
 */

 public static boolean copy(ProgressObserver progress, String sourcePath,String targetPath, Component comp,
       boolean canStop, boolean sendVFSUpdate)
  throws IOException
 {
  VFS sourceVFS = VFSManager.getVFSForPath(sourcePath);
  VFS targetVFS = VFSManager.getVFSForPath(targetPath);
  Object sourceSession = null;
  Object targetSession = null;
  try
  {
   sourceSession = sourceVFS.createVFSSession(sourcePath, comp);
   if (sourceSession == null)
   {
    Log.log(Log.WARNING, VFS.class"Unable to get a valid session from " + sourceVFS +
            " for path " + sourcePath);
    return false;
   }
   targetSession = targetVFS.createVFSSession(targetPath, comp);
   if (targetSession == null)
   {
    Log.log(Log.WARNING, VFS.class"Unable to get a valid session from " + targetVFS +
            " for path " + targetPath);
    return false;
   }
   return copy(progress, sourceVFS, sourceSession, sourcePath, targetVFS, targetSession, targetPath,
      comp,canStop, sendVFSUpdate);
  }
  finally
  {
   if (sourceSession != null)
    sourceVFS._endVFSSession(sourceSession, comp);
   if (targetSession != null)
    targetVFS._endVFSSession(targetSession, comp);
  }
 }

 /**
 * Copy a file to another using VFS.
 *
 * @param progress the progress observer. It could be null if you don't want to monitor progress. If not null
 *                  you should probably launch this command in a WorkThread
 * @param sourcePath the source path
 * @param targetPath the target path
 * @param comp The component that will parent error dialog boxes
 * @param canStop if true the copy can be stopped
 * @return true if the copy was successful
 * @throws IOException IOException If an I/O error occurs
 * @since jEdit 4.3pre3
 */

 public static boolean copy(ProgressObserver progress, String sourcePath,String targetPath, Component comp, boolean canStop)
 throws IOException
 {
  return copy(progress, sourcePath, targetPath, comp, canStop, true);
 } //}}}

 //{{{ insert() method
 /**
 * Inserts a file into the specified buffer. The default implementation
 * posts an I/O request to the I/O thread.
 * @param view The view
 * @param buffer The buffer
 * @param path The path
 */

 public boolean insert(View view, Buffer buffer, String path)
 {
  if((getCapabilities() & READ_CAP) == 0)
  {
   VFSManager.error(view,path,"vfs.not-supported.load",new String[] { name });
   return false;
  }

  Object session = createVFSSession(path,view);
  if(session == null)
   return false;

  ThreadUtilities.runInBackground(new BufferInsertRequest(
   view,buffer,session,this,path));
  return true;
 } //}}}

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

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

 public String _canonPath(Object session, String path, Component comp)
  throws IOException
 {
  return path;
 } //}}}

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

 public String[] _listDirectory(Object session, String directory,
  String glob, boolean recursive, Component comp )
  throws IOException
 {
  String[] retval = _listDirectory(session, directory, glob, recursive, comp, truefalse);
  return retval;
 } //}}}


 //{{{ _listDirectory() method
 /**
 * A convenience method that matches file names against globs, and can
 * optionally list the directory recursively.
 * @param session The session
 * @param directory The directory. Note that this must be a full
 * URL, including the host name, path name, and so on. The
 * username and password (if needed by the VFS) is obtained from the
 * session instance.
 * @param glob Only file names matching this glob will be returned
 * @param recursive If true, subdirectories will also be listed.
 * @param comp The component that will parent error dialog boxes
 * @exception IOException if an I/O error occurred
 * @param skipBinary ignore binary files (do not return them).
 *    This will slow down the process since it will open the files
 * @param skipHidden skips hidden files, directories, and
 *        backup files. Ignores any file beginning with . or #, or ending with ~
 *        or .bak
 *
 *
 * @since jEdit 4.3pre5
 */

 public String[] _listDirectory(Object session, String directory,
  String glob, boolean recursive, Component comp,
  boolean skipBinary, boolean skipHidden)
  throws IOException
 {
  VFSFileFilter filter = new GlobVFSFileFilter(glob);
  return _listDirectory(session, directory, filter,
          recursive, comp, skipBinary,
          skipHidden);
 } //}}}

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

 public String[] _listDirectory(Object session, String directory,
  VFSFileFilter filter, boolean recursive, Component comp,
  boolean skipBinary, boolean skipHidden)
  throws IOException
 {
  List<String> files = new ArrayList<>(100);

  listFiles(session,new HashSet<>(), files,directory,filter,
   recursive, comp, skipBinary, skipHidden);

  String[] retVal = files.toArray(StandardUtilities.EMPTY_STRING_ARRAY);

  Arrays.sort(retVal,new StandardUtilities.StringCompare<>(true));

  return retVal;
 } //}}}

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

 public VFSFile[] _listFiles(Object session, String directory,
  Component comp)
  throws IOException
 {
  VFSManager.error(comp,directory,"vfs.not-supported.list",new String[] { name });
  return null;
 } //}}}

 //{{{ _getFile() method
 /**
 * Returns the specified directory entry.
 * @param session The session get it with {@link VFS#createVFSSession(String, Component)}
 * @param path The path
 * @param comp The component that will parent error dialog boxes
 * @exception IOException if an I/O error occurred
 * @return The specified directory entry, or null if it doesn't exist.
 * @since jEdit 4.3pre2
 */

 @Nullable
 public VFSFile _getFile(Object session, String path, Component comp) throws IOException
 {
  return null;
 } //}}}

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

 public boolean _delete(Object session, String path, Component comp)
  throws IOException
 {
  return false;
 } //}}}

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

 public boolean _rename(Object session, String from, String to,
  Component comp) throws IOException
 {
  return false;
 } //}}}

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

 public boolean _mkdir(Object session, String directory, Component comp)
  throws IOException
 {
  return false;
 } //}}}

 //{{{ _backup() method
 /**
 * Backs up the specified file. Default implementation in 5.0pre1
 * copies the file to the backup directory. Before 5.0pre1 it was
 * empty.
 * @param session The VFS session
 * @param path The path
 * @param comp The component that will parent error dialog boxes
 * @exception IOException if an I/O error occurs
 * @since jEdit 3.2pre2
 */

 public void _backup(Object session, String path, Component comp)
  throws IOException
 {
  VFS vfsSrc = VFSManager.getVFSForPath(path);
  if (null == vfsSrc._getFile(session, path, comp))
   // file to backup does not exist
   return;

  // maybe the file is not applicable to local filesystem
  // but don't worry - for backup purposes it may be out
  // of a real filesystem
  File backupDir = MiscUtilities.prepareBackupDirectory(path);
  if (backupDir == null)
  {
   Log.log(Log.WARNING, VFS.class"Backup of remote file "
    + path + " failed, because there is no backup directory.");
   return;
  }
  if (!backupDir.exists())
  {
   // Usually that means there is no specified backup
   // directory.
   Log.log(Log.WARNING, VFS.class"Backup of file " +
    path + " failed. Directory " + backupDir +
    " does not exist.");
   return;
  }

  File backupFile = MiscUtilities.prepareBackupFile(path, backupDir);
  if (backupFile == null)
  {
   return;
  }

  // do copy using VFS.copy
  VFS vfsDst = VFSManager.getVFSForPath(backupFile.getPath());
  Object sessionDst = vfsDst.createVFSSessionSafe(
    backupFile.getPath(), comp);
  if (sessionDst == null)
   {
   return;
   }
  try
  {
   if (!copy(null, vfsSrc, session, path,
    vfsDst, sessionDst, backupFile.getPath(),
    comp, true))
   {
    Log.log(Log.WARNING, VFS.class"Backup of file " +
     path + " failed. Copy to " + backupFile +
     " failed.");
   }
  }
  finally
  {
   vfsDst._endVFSSession(sessionDst, comp);
  }

 } //}}}

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

 public InputStream _createInputStream(Object session,
  String path, boolean ignoreErrors, Component comp)
  throws IOException
 {
  VFSManager.error(comp,path,"vfs.not-supported.load",new String[] { name });
  return null;
 } //}}}

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

 public OutputStream _createOutputStream(Object session,
  String path, Component comp)
  throws IOException
 {
  VFSManager.error(comp,path,"vfs.not-supported.save",new String[] { name });
  return null;
 } //}}}

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

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

 //{{{ _finishTwoStageSave() method
 /**
 * Called after a file has been saved and we use twoStageSave (first saving to
 * another file). This should re-apply permissions for example.

 * @param session The VFS session
 * @param buffer The buffer
 * @param path The path the buffer was saved to (can be different from
 * {@link org.gjt.sp.jedit.Buffer#getPath()} if the user invoked the
 * <b>Save a Copy As</b> command, for example).
 * @param comp The component that will parent error dialog boxes
 * @exception IOException If an I/O error occurs
 * @since jEdit 4.3pre4
 */

 public void _finishTwoStageSave(Object session, Buffer buffer, String path,
  Component comp) throws IOException
 {
 } //}}}

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

 public void _endVFSSession(Object session, Component comp)
  throws IOException
 {
 } //}}}

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

 public static Color getDefaultColorFor(String name)
 {
  synchronized(lock)
  {
   if(colors == null)
    loadColors();

   for (ColorEntry entry : colors)
   {
    if (entry.getRe().matcher(name).matches())
     return entry.getColor();
   }

   return null;
  }
 } //}}}

 //{{{ DirectoryEntryCompare class
 /**
 * Implementation of {@link Comparator}
 * interface that compares {@link VFSFile} instances.
 * @since jEdit 4.2pre1
 */

 public static class DirectoryEntryCompare implements Comparator<VFSFile>
 {
  private final boolean sortIgnoreCase;
  private final boolean sortMixFilesAndDirs;

  /**
 * Creates a new <code>DirectoryEntryCompare</code>.
 * @param sortMixFilesAndDirs If false, directories are
 * put at the top of the listing.
 * @param sortIgnoreCase If false, upper case comes before
 * lower case.
 */

  public DirectoryEntryCompare(boolean sortMixFilesAndDirs,
   boolean sortIgnoreCase)
  {
   this.sortMixFilesAndDirs = sortMixFilesAndDirs;
   this.sortIgnoreCase = sortIgnoreCase;
  }

  @Override
  public int compare(VFSFile file1, VFSFile file2)
  {
   if(!sortMixFilesAndDirs)
   {
    if(file1.getType() != file2.getType())
     return file2.getType() - file1.getType();
   }

   return StandardUtilities.compareStrings(file1.getName(),
    file2.getName(),sortIgnoreCase);
  }
 } //}}}

 //{{{ Private members
 private final String name;
 private final int caps;
 private final String[] extAttrs;
 private static List<ColorEntry> colors;
 private static final Object lock = new Object();

 //{{{ Class initializer
 static
 {
  EditBus.addToBus(new EBComponent()
  {
   @Override
   public void handleMessage(EBMessage msg)
   {
    if(msg instanceof PropertiesChanged)
    {
     synchronized(lock)
     {
      colors = null;
     }
    }
   }
  });
 } //}}}

 //{{{ recursive listFiles() method
 private void listFiles(Object session, Collection<String> stack,
  List<String> files, String directory, VFSFileFilter filter, boolean recursive,
  Component comp, boolean skipBinary, boolean skipHidden) throws IOException
 {
  if (recursive && !MiscUtilities.isURL(directory))
  {
   String resolvedPath = MiscUtilities.resolveSymlinks(directory);
   /*
 * If looking at a symlink, do not traverse the
 * resolved path more than once.
 */

   if (!directory.equals(resolvedPath))
   {
    if (stack.contains(resolvedPath))
    {
     Log.log(Log.ERROR,this,
      "Recursion in listFiles(): "
      + directory);
     return;
    }
    stack.add(resolvedPath);
   }
  }

  VFSFile[] _files = _listFiles(session,directory,
   comp);
  if(_files == null || _files.length == 0)
   return;

  for(int i = 0; i < _files.length; i++)
  {
   if (Thread.currentThread().isInterrupted())
    break;
   VFSFile file = _files[i];
   if (skipHidden && (file.isHidden() || MiscUtilities.isBackup(file.getName())))
    continue;
   if(!filter.accept(file))
    continue;
   if(file.getType() == VFSFile.DIRECTORY
    || file.getType() == VFSFile.FILESYSTEM)
   {
    if(recursive)
    {
     String canonPath = _canonPath(session,
      file.getPath(),comp);
     listFiles(session,stack,files,
      canonPath,filter,recursive,
      comp, skipBinary, skipHidden);
    }
   }
   else // It's a regular file
   {
    if (skipBinary)
    {
     try
     {
      if (file.isBinary(session))
      {
       Log.log(Log.NOTICE,this
        ,file.getPath() + ": skipped as a binary file");
       continue;
      }
     }
     catch(IOException e)
     {
      Log.log(Log.ERROR,this,e);
      // may be not binary...
     }
    }
    files.add(file.getPath());
   }
  }
 } //}}}

 //{{{ loadColors() method
 private static void loadColors()
 {
  synchronized(lock)
  {
   colors = new ArrayList<>();

   if(!jEdit.getBooleanProperty("vfs.browser.colorize"))
    return;

   String glob;
   int i = 0;
   while((glob = jEdit.getProperty("vfs.browser.colors." + i + ".glob")) != null)
   {
    try
    {
     colors.add(new ColorEntry(
      Pattern.compile(StandardUtilities.globToRE(glob)),
      jEdit.getColorProperty(
      "vfs.browser.colors." + i + ".color",
      Color.black)));
    }
    catch(PatternSyntaxException e)
    {
     Log.log(Log.ERROR,VFS.class,"Invalid regular expression: " + glob);
     Log.log(Log.ERROR,VFS.class,e);
    }

    i++;
   }
  }
 } //}}}

 //{{{ ColorEntry class
 private static class ColorEntry
 {
  private final Pattern re;
  private final Color color;

  ColorEntry(Pattern re, Color color)
  {
   this.re = re;
   this.color = color;
  }

  public Pattern getRe()
  {
   return re;
  }

  public Color getColor()
  {
   return color;
  }
 } //}}}

 //{{{ SessionGetter class
 private class SessionGetter implements Runnable
 {
  SessionGetter(String path, Component comp)
  {
   this.path = path;
   this.comp = comp;
  }

  private Object session;
  private final String path;
  private final Component comp;

  @Override
  public void run()
  {
   session = createVFSSession(path, comp);
  }

  public Object get() { return session; }
 } //}}}

 //}}}
}

[ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet)  ]