/* (non-Javadoc)
  * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#changeFilePermissions(org.eclipse.core.runtime.IPath, long, org.eclipse.core.runtime.IProgressMonitor)
  */
 @Override
 protected void changeFilePermissions(IPath path, long permissions, IProgressMonitor monitor)
     throws CoreException, FileNotFoundException {
   if (chmodSupported == Boolean.FALSE) {
     return;
   }
   try {
     IPath dirPath = path.removeLastSegments(1);
     changeCurrentDir(dirPath);
     Policy.checkCanceled(monitor);
     chmodSupported =
         ftpClient.site(
             "CHMOD "
                 + Long.toOctalString(permissions)
                 + " "
                 + path.lastSegment()); // $NON-NLS-1$ //$NON-NLS-2$
   } catch (FileNotFoundException e) {
     throw e;
   } catch (OperationCanceledException e) {
     throw e;
   } catch (Exception e) {
     throw new CoreException(
         new Status(Status.ERROR, FTPPlugin.PLUGIN_ID, "Set permissions failed", e));
   } finally {
     monitor.done();
   }
 }
 /* (non-Javadoc)
  * @see com.aptana.ide.core.io.vfs.IConnectionFileManager#disconnect(org.eclipse.core.runtime.IProgressMonitor)
  */
 public synchronized void disconnect(IProgressMonitor monitor) throws CoreException {
   try {
     checkConnected();
   } catch (Exception ignore) {
   }
   if (!isConnected()) {
     return;
   }
   monitor = Policy.monitorFor(monitor);
   monitor.beginTask(
       Messages.FTPConnectionFileManager_closing_connection, IProgressMonitor.UNKNOWN);
   try {
     ftpClient.quit();
   } catch (Exception e) {
     try {
       ftpClient.quitImmediately();
     } catch (Exception ignore) {
     }
     throw new CoreException(
         new Status(
             Status.ERROR,
             FTPPlugin.PLUGIN_ID,
             Messages.FTPConnectionFileManager_disconnect_failed,
             e));
   } finally {
     cwd = null;
     pool.dispose();
     cleanup();
     monitor.done();
   }
 }
  protected static void setMessageLogger(FTPClient ftpClient, final PrintWriter writer) {
    FTPMessageListener listener = null;
    if (writer != null && ftpClient.getMessageListener() == null) {
      listener =
          new FTPMessageListener() {
            public void logCommand(String command) {
              if (command.startsWith("---> ")) {
                command = command.substring(5);
              }
              Matcher matcher = PASS_COMMAND_PATTERN.matcher(command);
              if (matcher.matches()) {
                command = matcher.replaceFirst("$1********");
              }
              writer.print("ftp> ");
              writer.println(command);
              writer.flush();
            }

            public void logReply(String reply) {
              writer.println(reply);
              writer.flush();
            }
          };
    }
    ftpClient.setMessageListener(listener);
  }
 private static void connectFTPClient(FTPClient ftpClient) throws IOException, FTPException {
   PerformanceStats stats =
       PerformanceStats.getStats(
           "com.aptana.ide.filesystem.ftp/perf/connect", //$NON-NLS-1$
           FTPConnectionFileManager.class.getName());
   stats.startRun(ftpClient.getRemoteHost());
   try {
     ftpClient.connect();
   } finally {
     stats.endRun();
   }
 }
 protected void safeQuit() {
   try {
     if (ftpClient.connected()) {
       ftpClient.quit();
     }
   } catch (Exception e) {
     try {
       ftpClient.quitImmediately();
     } catch (Exception ignore) {
     }
   }
 }
 private void recursiveDeleteTree(IPath path, IProgressMonitor monitor, MultiStatus status)
     throws IOException, ParseException {
   try {
     changeCurrentDir(path);
     FTPFile[] ftpFiles = listFiles(path, monitor);
     List<String> dirs = new ArrayList<String>();
     for (FTPFile ftpFile : ftpFiles) {
       String name = ftpFile.getName();
       if (".".equals(name) || "..".equals(name)) { // $NON-NLS-1$ //$NON-NLS-2$
         continue;
       }
       if (ftpFile.isDir()) {
         dirs.add(name);
         continue;
       }
       Policy.checkCanceled(monitor);
       monitor.subTask(path.append(name).toPortableString());
       try {
         ftpClient.delete(name);
       } catch (FTPException e) {
         status.add(
             new Status(
                 IStatus.ERROR,
                 FTPPlugin.PLUGIN_ID,
                 StringUtils.format(
                     Messages.FTPConnectionFileManager_deleting_failed,
                     path.append(name).toPortableString()),
                 e));
       }
       monitor.worked(1);
     }
     for (String name : dirs) {
       monitor.subTask(path.append(name).toPortableString());
       recursiveDeleteTree(path.append(name), monitor, status);
       Policy.checkCanceled(monitor);
       changeCurrentDir(path);
       Policy.checkCanceled(monitor);
       ftpClient.rmdir(name);
       monitor.worked(1);
     }
   } catch (IOException e) {
     throw e;
   } catch (Exception e) {
     status.add(
         new Status(
             IStatus.ERROR,
             FTPPlugin.PLUGIN_ID,
             StringUtils.format(
                 Messages.FTPConnectionFileManager_deleting_failed, path.toPortableString()),
             e));
   }
 }
 /* (non-Javadoc)
  * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#checkConnected()
  */
 @Override
 protected void checkConnected() throws Exception {
   if (ftpClient.connected()) {
     try {
       ftpClient.noOperation();
       return;
     } catch (FTPConnectionClosedException e) {
     } catch (FTPException ignore) {
       return;
     } catch (IOException e) {
     }
     ftpClient.quitImmediately();
   }
 }
 protected static void initFTPClient(FTPClient ftpClient, boolean passive, String encoding)
     throws IOException, FTPException {
   ftpClient.setTimeout(TIMEOUT);
   ftpClient.setControlEncoding(encoding);
   ftpClient.setMonitorInterval(1024);
   ftpClient.setConnectMode(passive ? FTPConnectMode.PASV : FTPConnectMode.ACTIVE);
   ftpClient.setRetryCount(RETRY);
   ftpClient.setRetryDelay(RETRY_DELAY);
   ftpClient.setServerWakeupInterval(KEEPALIVE_INTERVAL);
   ftpClient.setDeleteOnFailure(true);
   ftpClient.setTransferBufferSize(TRANSFER_BUFFER_SIZE);
 }
 /* (non-Javadoc)
  * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#setModificationTime(org.eclipse.core.runtime.IPath, long, org.eclipse.core.runtime.IProgressMonitor)
  */
 @Override
 protected void setModificationTime(IPath path, long modificationTime, IProgressMonitor monitor)
     throws CoreException, FileNotFoundException {
   if (!serverSupportsFeature("MFMT")
       && !serverSupportsFeature("SITE UTIME")) { // $NON-NLS-1$ //$NON-NLS-2$
     return;
   }
   try {
     IPath dirPath = path.removeLastSegments(1);
     changeCurrentDir(dirPath);
     Policy.checkCanceled(monitor);
     if (serverSupportsFeature("MFMT")) { // $NON-NLS-1$
       ftpClient.setModTime(path.lastSegment(), new Date(modificationTime));
     } else if (serverSupportsFeature("SITE UTIME")) { // $NON-NLS-1$
       Calendar cal = Calendar.getInstance();
       long localTimezoneShift = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
       Date date = new Date(modificationTime - localTimezoneShift);
       if (utimeFormat == -1) {
         for (utimeFormat = 0; utimeFormat < UTIME_FORMATS.length; ++utimeFormat) {
           String format = UTIME_FORMATS[utimeFormat].format(date);
           FTPReply reply =
               ftpClient.sendCommand(
                   "SITE " + MessageFormat.format(format, path.lastSegment())); // $NON-NLS-1$
           if (!"500".equals(reply.getReplyCode())
               && !"501".equals(reply.getReplyCode())) { // $NON-NLS-1$ //$NON-NLS-2$
             break;
           }
         }
       } else if (utimeFormat >= 0 && utimeFormat < UTIME_FORMATS.length) {
         String format = UTIME_FORMATS[utimeFormat].format(date);
         ftpClient.site(MessageFormat.format(format, path.lastSegment()));
       }
     }
   } catch (FileNotFoundException e) {
     throw e;
   } catch (OperationCanceledException e) {
     throw e;
   } catch (Exception e) {
     throw new CoreException(
         new Status(
             Status.ERROR,
             FTPPlugin.PLUGIN_ID,
             Messages.FTPConnectionFileManager_set_modification_time_failed,
             e));
   } finally {
     monitor.done();
   }
 }
 /* (non-Javadoc)
  * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#deleteFile(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor)
  */
 @Override
 protected void deleteFile(IPath path, IProgressMonitor monitor)
     throws CoreException, FileNotFoundException {
   try {
     IPath dirPath = path.removeLastSegments(1);
     changeCurrentDir(dirPath);
     Policy.checkCanceled(monitor);
     try {
       ftpClient.delete(path.lastSegment());
     } catch (FTPException e) {
       System.out.println(e);
       throw e;
     }
   } catch (FileNotFoundException e) {
     throw e;
   } catch (OperationCanceledException e) {
     throw e;
   } catch (Exception e) {
     throw new CoreException(
         new Status(
             Status.ERROR,
             FTPPlugin.PLUGIN_ID,
             StringUtils.format(Messages.FTPConnectionFileManager_deleting_failed, path),
             e));
   } finally {
     monitor.done();
   }
 }
 protected void changeCurrentDir(IPath path) throws FTPException, IOException {
   try {
     if (cwd == null) {
       cwd = new Path(ftpClient.pwd());
     }
     if (!cwd.equals(path)) {
       ftpClient.chdir(path.toPortableString());
       cwd = path;
     }
   } catch (FTPException e) {
     throwFileNotFound(e, path);
   } catch (IOException e) {
     cwd = null;
     throw e;
   }
 }
 /* (non-Javadoc)
  * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#renameFile(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor)
  */
 @Override
 protected void renameFile(IPath sourcePath, IPath destinationPath, IProgressMonitor monitor)
     throws CoreException, FileNotFoundException {
   try {
     changeCurrentDir(Path.ROOT);
     Policy.checkCanceled(monitor);
     try {
       ftpClient.rename(sourcePath.toPortableString(), destinationPath.toPortableString());
     } catch (FTPException e) {
       throwFileNotFound(e, sourcePath);
       System.out.println(e);
       throw e;
     }
   } catch (FileNotFoundException e) {
     throw e;
   } catch (OperationCanceledException e) {
     throw e;
   } catch (Exception e) {
     throw new CoreException(
         new Status(
             Status.ERROR,
             FTPPlugin.PLUGIN_ID,
             Messages.FTPConnectionFileManager_renaming_failed,
             e));
   } finally {
     monitor.done();
   }
 }
 /* (non-Javadoc)
  * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#createDirectory(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor)
  */
 @Override
 protected void createDirectory(IPath path, IProgressMonitor monitor)
     throws CoreException, FileNotFoundException {
   try {
     try {
       try {
         changeCurrentDir(path);
         return; // directory exists - return
       } catch (FileNotFoundException ignore) {
       }
       ftpClient.mkdir(path.toPortableString());
       changeFilePermissions(path, PreferenceUtils.getDirectoryPermissions(), monitor);
     } catch (FTPException e) {
       throwFileNotFound(e, path);
     }
   } catch (FileNotFoundException e) {
     throw e;
   } catch (Exception e) {
     throw new CoreException(
         new Status(
             Status.ERROR,
             FTPPlugin.PLUGIN_ID,
             Messages.FTPConnectionFileManager_creating_directory_failed,
             e));
   }
 }
  private FTPFile[] ftpSTAT(String dirname) throws IOException, FTPException, ParseException {
    if (fileFactory == null) {
      try {
        fileFactory = new FTPFileFactory(ftpClient.system());
      } catch (FTPException ex) {
        fileFactory = new FTPFileFactory(""); // $NON-NLS-1$
      }
      fileFactory.setLocales(FTPClient.DEFAULT_LISTING_LOCALES);
    }

    String[] validCodes = {"211", "212", "213"}; // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    FTPReply reply = ftpClient.sendCommand("STAT " + dirname); // $NON-NLS-1$
    ftpClient.validateReply(reply, validCodes);
    String[] data = reply.getReplyData();
    if (data == null) {
      return null;
    }
    for (int i = 0; i < data.length; ++i) {
      data[i] = data[i].trim();
    }
    return fileFactory.parse(data);
  }
 /* (non-Javadoc)
  * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#deleteDirectory(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor)
  */
 @Override
 protected void deleteDirectory(IPath path, IProgressMonitor monitor)
     throws CoreException, FileNotFoundException {
   MultiStatus status = new MultiStatus(FTPPlugin.PLUGIN_ID, 0, null, null);
   try {
     IPath dirPath = path.removeLastSegments(1);
     changeCurrentDir(dirPath);
     Policy.checkCanceled(monitor);
     recursiveDeleteTree(path, monitor, status);
     changeCurrentDir(dirPath);
     ftpClient.rmdir(path.lastSegment());
   } catch (FileNotFoundException e) {
     throw e;
   } catch (OperationCanceledException e) {
     throw e;
   } catch (Exception e) {
     if (!status.isOK()) {
       MultiStatus multiStatus =
           new MultiStatus(
               FTPPlugin.PLUGIN_ID,
               0,
               Messages.FTPConnectionFileManager_deleting_directory_failed,
               e);
       multiStatus.addAll(status);
     } else {
       throw new CoreException(
           new Status(
               Status.ERROR,
               FTPPlugin.PLUGIN_ID,
               Messages.FTPConnectionFileManager_deleting_directory_failed,
               e));
     }
   } finally {
     monitor.done();
   }
 }
 protected void initAndAuthFTPClient(
     FTPClientInterface clientInterface, IProgressMonitor monitor, boolean forceConnect)
     throws IOException, FTPException {
   if (!forceConnect && clientInterface.connected()) {
     return;
   }
   FTPClient newFtpClient = (FTPClient) clientInterface;
   initFTPClient(
       newFtpClient,
       ftpClient.getConnectMode() == FTPConnectMode.PASV,
       ftpClient.getControlEncoding());
   newFtpClient.setRemoteHost(host);
   newFtpClient.setRemotePort(port);
   Policy.checkCanceled(monitor);
   connectFTPClient(newFtpClient);
   monitor.worked(1);
   Policy.checkCanceled(monitor);
   newFtpClient.login(login, String.copyValueOf(password));
   monitor.worked(1);
 }
  /* (non-Javadoc)
   * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#writeFile(org.eclipse.core.runtime.IPath, long, org.eclipse.core.runtime.IProgressMonitor)
   */
  @Override
  protected OutputStream writeFile(IPath path, long permissions, IProgressMonitor monitor)
      throws CoreException, FileNotFoundException {
    monitor.beginTask(Messages.FTPConnectionFileManager_initiating_file_upload, 4);
    FTPClient uploadFtpClient = (FTPClient) pool.checkOut();
    try {
      initAndAuthFTPClient(uploadFtpClient, monitor, false);
      Policy.checkCanceled(monitor);
      setMessageLogger(uploadFtpClient, messageLogWriter);
      uploadFtpClient.setType(
          IFTPConstants.TRANSFER_TYPE_ASCII.equals(transferType)
              ? FTPTransferType.ASCII
              : FTPTransferType.BINARY);
      IPath dirPath = path.removeLastSegments(1);
      try {
        uploadFtpClient.chdir(dirPath.toPortableString());
      } catch (FTPException e) {
        throwFileNotFound(e, dirPath);
      }
      monitor.worked(1);
      Policy.checkCanceled(monitor);
      return new FTPFileUploadOutputStream(
          pool,
          uploadFtpClient,
          new FTPOutputStream(uploadFtpClient, generateTempFileName(path.lastSegment())),
          path.lastSegment(),
          null,
          permissions);
    } catch (Exception e) {
      setMessageLogger(uploadFtpClient, null);
      pool.checkIn(uploadFtpClient);

      if (e instanceof OperationCanceledException) {
        throw (OperationCanceledException) e;
      } else if (e instanceof FileNotFoundException) {
        throw (FileNotFoundException) e;
      } else if (e instanceof FTPException) {
        if (((FTPException) e).getReplyCode() == 553) {
          throw (FileNotFoundException)
              new FileNotFoundException(path.toPortableString()).initCause(e);
        }
      }
      if (connectionRetryCount < 1) {
        connectionRetryCount++;
        try {
          initAndAuthFTPClient(uploadFtpClient, monitor, true);
        } catch (IOException e1) {
          // ignores
        } catch (FTPException e1) {
          // ignores
        }
        try {
          return writeFile(path, permissions, monitor);
        } finally {
          connectionRetryCount = 0;
        }
      } else {
        connectionRetryCount = 0;
        throw new CoreException(
            new Status(
                Status.ERROR,
                FTPPlugin.PLUGIN_ID,
                Messages.FTPConnectionFileManager_opening_file_failed,
                e));
      }
    } finally {
      monitor.done();
    }
  }
  /* (non-Javadoc)
   * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#readFile(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor)
   */
  @Override
  protected InputStream readFile(IPath path, IProgressMonitor monitor)
      throws CoreException, FileNotFoundException {
    monitor.beginTask(Messages.FTPConnectionFileManager_initiating_download, 4);
    FTPClient downloadFtpClient = (FTPClient) pool.checkOut();
    try {
      initAndAuthFTPClient(downloadFtpClient, monitor, false);
      Policy.checkCanceled(monitor);
      setMessageLogger(downloadFtpClient, messageLogWriter);
      downloadFtpClient.setType(
          IFTPConstants.TRANSFER_TYPE_ASCII.equals(transferType)
              ? FTPTransferType.ASCII
              : FTPTransferType.BINARY);
      try {
        downloadFtpClient.chdir(path.removeLastSegments(1).toPortableString());
      } catch (FTPException e) {
        throwFileNotFound(e, path.removeLastSegments(1));
      }
      monitor.worked(1);
      Policy.checkCanceled(monitor);
      try {
        return new FTPFileDownloadInputStream(
            pool, downloadFtpClient, new FTPInputStream(downloadFtpClient, path.lastSegment()));
      } catch (FTPException e) {
        throwFileNotFound(e, path);
        return null;
      }
    } catch (Exception e) {
      setMessageLogger(downloadFtpClient, null);
      pool.checkIn(downloadFtpClient);

      if (e instanceof OperationCanceledException) {
        throw (OperationCanceledException) e;
      } else if (e instanceof FileNotFoundException) {
        throw (FileNotFoundException) e;
      }
      // does one retry
      if (connectionRetryCount < 1) {
        connectionRetryCount++;
        try {
          initAndAuthFTPClient(downloadFtpClient, monitor, true);
        } catch (IOException e1) {
          // ignores
        } catch (FTPException e1) {
          // ignores
        }
        try {
          return readFile(path, monitor);
        } finally {
          connectionRetryCount = 0;
        }
      } else {
        connectionRetryCount = 0;
        throw new CoreException(
            new Status(
                Status.ERROR,
                FTPPlugin.PLUGIN_ID,
                Messages.FTPConnectionFileManager_opening_file_failed,
                e));
      }
    } finally {
      monitor.done();
    }
  }
  /* (non-Javadoc)
   * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#fetchFiles(org.eclipse.core.runtime.IPath, int, org.eclipse.core.runtime.IProgressMonitor)
   */
  @SuppressWarnings("deprecation")
  @Override
  protected ExtendedFileInfo[] fetchFiles(IPath path, int options, IProgressMonitor monitor)
      throws CoreException, FileNotFoundException {
    monitor = Policy.subMonitorFor(monitor, 1);
    try {
      FTPFile[] ftpFiles = listFiles(path, monitor);
      monitor.beginTask(Messages.FTPConnectionFileManager_gethering_file_details, ftpFiles.length);
      List<ExtendedFileInfo> list = new ArrayList<ExtendedFileInfo>();
      for (FTPFile ftpFile : ftpFiles) {
        if (".".equals(ftpFile.getName())
            || "..".equals(ftpFile.getName())) { // $NON-NLS-1$ //$NON-NLS-2$
          monitor.worked(1);
          continue;
        }
        Date lastModifiedServerInLocalTZ = ftpFile.lastModified();
        if (serverTimeZoneShift != 0 && lastModifiedServerInLocalTZ != null) {
          ftpFile.setLastModified(
              new Date(lastModifiedServerInLocalTZ.getTime() + serverTimeZoneShift));
        }
        if ((options & IExtendedFileStore.DETAILED) != 0) {
          if (!ftpFile.isDir() && ftpFile.lastModified().getSeconds() == 0) {
            if (serverSupportsFeature("MDTM")) { // $NON-NLS-1$
              changeCurrentDir(path);
              Policy.checkCanceled(monitor);
              try {
                Date lastModifiedLocalTZ = ftpClient.modtime(ftpFile.getName());
                if (lastModifiedLocalTZ != null) {
                  ftpFile.setLastModified(lastModifiedLocalTZ);
                }
              } catch (FTPException e) {
              }
            }
          }
        }
        IPath filePath = path.append(ftpFile.getName());
        ftpFileCache.put(filePath, ftpFile);

        ExtendedFileInfo fileInfo = createFileInfo(ftpFile);
        list.add(fileInfo);
        monitor.worked(1);
      }
      return list.toArray(new ExtendedFileInfo[list.size()]);
    } catch (FileNotFoundException e) {
      throw e;
    } catch (OperationCanceledException e) {
      throw e;
    } catch (Exception e) {
      // forces one connection retry
      if (connectionRetryCount < 1) {
        connectionRetryCount++;
        testOrConnect(monitor);
        try {
          return fetchFiles(path, options, monitor);
        } finally {
          connectionRetryCount = 0;
        }
      } else {
        connectionRetryCount = 0;
        throw new CoreException(
            new Status(
                Status.ERROR,
                FTPPlugin.PLUGIN_ID,
                Messages.FTPConnectionFileManager_fetching_directory_failed,
                e));
      }
    } finally {
      monitor.done();
    }
  }
 /* (non-Javadoc)
  * @see com.aptana.ide.core.ftp.BaseFTPConnectionFileManager#fetchFile(org.eclipse.core.runtime.IPath, int, org.eclipse.core.runtime.IProgressMonitor)
  */
 @SuppressWarnings("deprecation")
 @Override
 protected ExtendedFileInfo fetchFile(IPath path, int options, IProgressMonitor monitor)
     throws CoreException, FileNotFoundException {
   try {
     IPath dirPath = path.removeLastSegments(1);
     String name = path.lastSegment();
     FTPFile result = ftpFileCache.get(path);
     if (result == null) {
       FTPFile[] ftpFiles = listFiles(dirPath, monitor);
       for (FTPFile ftpFile : ftpFiles) {
         Date lastModifiedServerInLocalTZ = ftpFile.lastModified();
         if (serverTimeZoneShift != 0 && lastModifiedServerInLocalTZ != null) {
           ftpFile.setLastModified(
               new Date(lastModifiedServerInLocalTZ.getTime() + serverTimeZoneShift));
         }
         if (".".equals(ftpFile.getName())
             || "..".equals(ftpFile.getName())) { // $NON-NLS-1$ //$NON-NLS-2$
           if (Path.ROOT.equals(path) && ".".equals(ftpFile.getName())) { // $NON-NLS-1$
             ftpFile.setName(path.toPortableString());
             ftpFileCache.put(path, ftpFile);
             result = ftpFile;
           }
           continue;
         }
         ftpFileCache.put(dirPath.append(ftpFile.getName()), ftpFile);
         if (name != null && name.equalsIgnoreCase(ftpFile.getName())) {
           result = ftpFile;
         }
       }
     }
     if ((options & IExtendedFileStore.DETAILED) != 0) {
       if (result != null
           && !result.isDir()
           && name != null
           && result.lastModified().getSeconds() == 0) {
         if (serverSupportsFeature("MDTM")) { // $NON-NLS-1$
           changeCurrentDir(dirPath);
           Policy.checkCanceled(monitor);
           try {
             Date lastModifiedLocalTZ = ftpClient.modtime(name);
             if (lastModifiedLocalTZ != null) {
               result.setLastModified(lastModifiedLocalTZ);
             }
           } catch (FTPException e) {
           }
         }
       }
     }
     if (result == null && Path.ROOT.equals(path)) {
       result = new FTPFile(StringUtils.EMPTY, path.toPortableString(), 0, true, new Date(0));
     }
     if (result != null) {
       return createFileInfo(result);
     }
   } catch (FileNotFoundException e) {
     throw e;
   } catch (OperationCanceledException e) {
     throw e;
   } catch (Exception e) {
     // forces one connection retry
     if (connectionRetryCount < 1) {
       connectionRetryCount++;
       testOrConnect(monitor);
       try {
         return fetchFile(path, options, monitor);
       } finally {
         connectionRetryCount = 0;
       }
     } else {
       connectionRetryCount = 0;
       throw new CoreException(
           new Status(
               Status.ERROR,
               FTPPlugin.PLUGIN_ID,
               Messages.FTPConnectionFileManager_fetch_failed,
               e));
     }
   }
   ExtendedFileInfo fileInfo = new ExtendedFileInfo(path.lastSegment());
   fileInfo.setExists(false);
   return fileInfo;
 }
 private FTPFile[] ftpLIST(IPath dirPath, IProgressMonitor monitor)
     throws IOException, ParseException, FTPException {
   changeCurrentDir(dirPath);
   Policy.checkCanceled(monitor);
   return ftpClient.dirDetails("-a"); // $NON-NLS-1$
 }
  /* (non-Javadoc)
   * @see com.aptana.ide.core.io.vfs.IConnectionFileManager#connect(org.eclipse.core.runtime.IProgressMonitor)
   */
  public void connect(IProgressMonitor monitor) throws CoreException {
    Assert.isTrue(ftpClient != null, Messages.FTPConnectionFileManager_not_initialized);
    monitor = Policy.monitorFor(monitor);
    try {
      cwd = null;
      cleanup();

      ConnectionContext context = CoreIOPlugin.getConnectionContext(this);

      if (messageLogWriter == null) {
        if (context != null) {
          Object object = context.get(ConnectionContext.COMMAND_LOG);
          if (object instanceof PrintWriter) {
            messageLogWriter = (PrintWriter) object;
          } else if (object instanceof OutputStream) {
            messageLogWriter = new PrintWriter((OutputStream) object);
          }
        }
        if (messageLogWriter == null) {
          messageLogWriter = FTPPlugin.getDefault().getFTPLogWriter();
        }
        if (messageLogWriter != null) {
          messageLogWriter.println(StringUtils.format("---------- FTP {0} ----------", host));
          setMessageLogger(ftpClient, messageLogWriter);
        }
      } else {
        messageLogWriter.println(
            StringUtils.format("---------- RECONNECTING - FTP {0} ----------", host));
      }

      monitor.beginTask(
          Messages.FTPConnectionFileManager_establishing_connection, IProgressMonitor.UNKNOWN);
      ftpClient.setRemoteHost(host);
      ftpClient.setRemotePort(port);
      while (true) {
        monitor.subTask(Messages.FTPConnectionFileManager_connecting);
        ftpClient.connect();
        if (password.length == 0
            && !IFTPConstants.LOGIN_ANONYMOUS.equals(login)
            && (context == null || !context.getBoolean(ConnectionContext.NO_PASSWORD_PROMPT))) {
          getOrPromptPassword(
              StringUtils.format(Messages.FTPConnectionFileManager_ftp_auth, host),
              Messages.FTPConnectionFileManager_specify_password);
        }
        Policy.checkCanceled(monitor);
        monitor.subTask(Messages.FTPConnectionFileManager_authenticating);
        try {
          ftpClient.login(login, String.copyValueOf(password));
        } catch (FTPException e) {
          Policy.checkCanceled(monitor);
          if (ftpClient.getLastValidReply() == null
              || "331".equals(ftpClient.getLastValidReply().getReplyCode())) { // $NON-NLS-1$
            if (context != null && context.getBoolean(ConnectionContext.NO_PASSWORD_PROMPT)) {
              throw new CoreException(
                  new Status(
                      Status.ERROR,
                      FTPPlugin.PLUGIN_ID,
                      StringUtils.format("Authentication failed: {0}", e.getLocalizedMessage()),
                      e));
            }
            promptPassword(
                StringUtils.format(Messages.FTPConnectionFileManager_ftp_auth, host),
                Messages.FTPConnectionFileManager_invalid_password);
            safeQuit();
            continue;
          }
          throw e;
        }
        break;
      }

      Policy.checkCanceled(monitor);
      changeCurrentDir(basePath);

      ftpClient.setType(
          IFTPConstants.TRANSFER_TYPE_ASCII.equals(transferType)
              ? FTPTransferType.ASCII
              : FTPTransferType.BINARY);

      if ((hasServerInfo
              || (context != null && context.getBoolean(ConnectionContext.QUICK_CONNECT)))
          && !(context != null && context.getBoolean(ConnectionContext.DETECT_TIMEZONE))) {
        return;
      }
      getherServerInfo(context, monitor);

    } catch (OperationCanceledException e) {
      safeQuit();
      throw e;
    } catch (CoreException e) {
      safeQuit();
      throw e;
    } catch (UnknownHostException e) {
      safeQuit();
      throw new CoreException(
          new Status(
              Status.ERROR,
              FTPPlugin.PLUGIN_ID,
              "Host name not found: " + e.getLocalizedMessage(),
              e));
    } catch (FileNotFoundException e) {
      safeQuit();
      throw new CoreException(
          new Status(
              Status.ERROR,
              FTPPlugin.PLUGIN_ID,
              "Remote folder not found: " + e.getLocalizedMessage(),
              e));
    } catch (Exception e) {
      safeQuit();
      throw new CoreException(
          new Status(
              Status.ERROR,
              FTPPlugin.PLUGIN_ID,
              Messages.FTPConnectionFileManager_connection_failed + e.getLocalizedMessage(),
              e));
    } finally {
      monitor.done();
    }
  }
 /* (non-Javadoc)
  * @see com.aptana.ide.core.io.vfs.IConnectionFileManager#isConnected()
  */
 public boolean isConnected() {
   return ftpClient != null && ftpClient.connected();
 }
  @SuppressWarnings("deprecation")
  protected void getherServerInfo(ConnectionContext context, IProgressMonitor monitor) {
    Policy.checkCanceled(monitor);
    monitor.subTask(Messages.FTPConnectionFileManager_gethering_server_info);
    serverFeatures = null;
    try {
      String[] features = ftpClient.features();
      if (features != null && features.length > 0) {
        serverFeatures = new ArrayList<String>();
        for (int i = 0; i < features.length; ++i) {
          String feature = features[i].trim();
          if (feature.indexOf(' ') > 0) {
            feature = feature.substring(0, feature.indexOf(' '));
          }
          serverFeatures.add(feature);
        }
      }
    } catch (Exception e) {
    }
    try {
      String[] validCodes = {"214"}; // $NON-NLS-1$
      FTPReply reply = ftpClient.sendCommand("SITE HELP"); // $NON-NLS-1$
      ftpClient.validateReply(reply, validCodes);
      if (serverFeatures == null) {
        serverFeatures = new ArrayList<String>();
      }
      String[] data = reply.getReplyData();
      for (int i = 0; i < data.length; ++i) {
        String cmd = data[i].trim();
        if (cmd.startsWith("214")) { // $NON-NLS-1$
          continue;
        }
        serverFeatures.add(MessageFormat.format("SITE {0}", cmd)); // $NON-NLS-1$
      }
    } catch (Exception e) {
      e.getCause();
    }

    Policy.checkCanceled(monitor);
    FTPFile[] rootFiles = null;
    try {
      rootFiles = listFiles(Path.ROOT, monitor);
    } catch (Exception e) {
    }

    if (context != null && context.getBoolean(ConnectionContext.DETECT_TIMEZONE)) {
      serverTimeZoneShift = Integer.MIN_VALUE;
    } else if (timezone != null) {
      TimeZone tz = TimeZone.getTimeZone(timezone);
      if (tz != null) {
        long time = new Date().getTime();
        serverTimeZoneShift = TimeZone.getDefault().getOffset(time) - tz.getOffset(time);
      }
    }
    if (serverTimeZoneShift == Integer.MIN_VALUE) {
      Policy.checkCanceled(monitor);
      try {
        changeCurrentDir(Path.ROOT);
        FTPFile file = null;
        if (rootFiles != null) {
          for (FTPFile ftpFile : rootFiles) {
            if (ftpFile.isFile()
                && !ftpFile.getName().startsWith(".ht")
                && !(ftpFile.lastModified().getHours() == 0
                    && ftpFile.lastModified().getMinutes() == 0
                    && ftpFile.lastModified().getSeconds() == 0)) {
              file = ftpFile;
              break;
            }
          }
        }
        if (file == null && !Path.ROOT.equals(basePath)) {
          FTPFile[] ftpFiles = listFiles(basePath, monitor);
          for (FTPFile ftpFile : ftpFiles) {
            if (ftpFile.isFile()
                && !ftpFile.getName().startsWith(".ht")
                && !(ftpFile.lastModified().getHours() == 0
                    && ftpFile.lastModified().getMinutes() == 0
                    && ftpFile.lastModified().getSeconds() == 0)) {
              file = ftpFile;
              break;
            }
          }
        }
        Date lastModifiedLocal = null;
        if (file == null) {
          changeCurrentDir(basePath);
          lastModifiedLocal = new Date();
          ftpClient.put(new ByteArrayInputStream(new byte[] {}), TMP_TIMEZONE_CHECK);
          for (FTPFile ftpFile : listFiles(basePath, monitor)) {
            if (TMP_TIMEZONE_CHECK.equals(ftpFile.getName())) {
              file = ftpFile;
              break;
            }
          }
        }
        if (file != null) {
          Date lastModifiedServerInLocalTZ = file.lastModified();
          if (serverSupportsFeature("MDTM")) { // $NON-NLS-1$
            Date lastModifiedLocalTZ = ftpClient.modtime(file.getName());
            if (lastModifiedLocalTZ != null) {
              // align to minutes
              serverTimeZoneShift =
                  (lastModifiedLocalTZ.getTime() - lastModifiedLocalTZ.getTime() % 60000)
                      - (lastModifiedServerInLocalTZ.getTime()
                          - lastModifiedServerInLocalTZ.getTime() % 60000);
            }
          }
          if (serverTimeZoneShift == Integer.MIN_VALUE) {
            serverTimeZoneShift =
                (lastModifiedLocal.getTime() - lastModifiedLocal.getTime() % 60000)
                    - (lastModifiedServerInLocalTZ.getTime()
                        - lastModifiedServerInLocalTZ.getTime() % 60000);
            // align to 1/4 hour
            long rem = serverTimeZoneShift % 900000;
            if (rem < 450000) {
              serverTimeZoneShift -= rem;
            } else {
              serverTimeZoneShift += (900000 - rem);
            }
          }
          if (TMP_TIMEZONE_CHECK.equals(file.getName())) {
            ftpClient.delete(file.getName());
          }
          if (context != null) {
            Calendar cal = Calendar.getInstance();
            int rawOffset =
                (int)
                    (cal.get(Calendar.ZONE_OFFSET)
                        + cal.get(Calendar.DST_OFFSET)
                        - serverTimeZoneShift);
            context.put(ConnectionContext.SERVER_TIMEZONE, TimeZone.getAvailableIDs(rawOffset));
          }
        }
      } catch (OperationCanceledException e) {
        throw e;
      } catch (Exception e) {
        IdeLog.logImportant(
            FTPPlugin.getDefault(), Messages.FTPConnectionFileManager_server_tz_check, e);
      }
      if (serverTimeZoneShift == Integer.MIN_VALUE) {
        Calendar cal = Calendar.getInstance();
        serverTimeZoneShift = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
      }
    }

    hasServerInfo = true;
  }