예제 #1
0
  public boolean storeFile(String name, Exchange exchange)
      throws GenericFileOperationFailedException {
    // must normalize name first
    name = endpoint.getConfiguration().normalizePath(name);

    LOG.trace("storeFile({})", name);

    boolean answer = false;
    String currentDir = null;
    String path = FileUtil.onlyPath(name);
    String targetName = name;

    try {
      if (path != null && endpoint.getConfiguration().isStepwise()) {
        // must remember current dir so we stay in that directory after the write
        currentDir = getCurrentDirectory();

        // change to path of name
        changeCurrentDirectory(path);

        // the target name should be without path, as we have changed directory
        targetName = FileUtil.stripPath(name);
      }

      // store the file
      answer = doStoreFile(name, targetName, exchange);
    } finally {
      // change back to current directory if we changed directory
      if (currentDir != null) {
        changeCurrentDirectory(currentDir);
      }
    }

    return answer;
  }
  public String createTempFileName(Exchange exchange, String fileName) {
    String answer = fileName;

    String tempName;
    if (exchange.getIn().getHeader(Exchange.FILE_NAME) == null) {
      // its a generated filename then add it to header so we can evaluate the expression
      exchange.getIn().setHeader(Exchange.FILE_NAME, FileUtil.stripPath(fileName));
      tempName = endpoint.getTempFileName().evaluate(exchange, String.class);
      // and remove it again after evaluation
      exchange.getIn().removeHeader(Exchange.FILE_NAME);
    } else {
      tempName = endpoint.getTempFileName().evaluate(exchange, String.class);
    }

    // check for both windows and unix separators
    int pos = Math.max(answer.lastIndexOf("/"), answer.lastIndexOf("\\"));
    if (pos == -1) {
      // no path so use temp name as calculated
      answer = tempName;
    } else {
      // path should be prefixed before the temp name
      StringBuilder sb = new StringBuilder(answer.substring(0, pos + 1));
      sb.append(tempName);
      answer = sb.toString();
    }

    if (endpoint.getConfiguration().needToNormalize()) {
      // must normalize path to cater for Windows and other OS
      answer = normalizePath(answer);
    }

    return answer;
  }
  /**
   * Creates the associated name of the done file based on the given file name.
   *
   * <p>This method should only be invoked if a done filename property has been set on this
   * endpoint.
   *
   * @param fileName the file name
   * @return name of the associated done file name
   */
  protected String createDoneFileName(String fileName) {
    String pattern = getDoneFileName();
    ObjectHelper.notEmpty(pattern, "doneFileName", pattern);

    // we only support ${file:name} or ${file:name.noext} as dynamic placeholders for done files
    String path = FileUtil.onlyPath(fileName);
    String onlyName = FileUtil.stripPath(fileName);

    pattern = pattern.replaceFirst("\\$\\{file:name\\}", onlyName);
    pattern = pattern.replaceFirst("\\$simple\\{file:name\\}", onlyName);
    pattern = pattern.replaceFirst("\\$\\{file:name.noext\\}", FileUtil.stripExt(onlyName));
    pattern = pattern.replaceFirst("\\$simple\\{file:name.noext\\}", FileUtil.stripExt(onlyName));

    // must be able to resolve all placeholders supported
    if (SimpleLanguage.hasStartToken(pattern)) {
      throw new ExpressionIllegalSyntaxException(
          fileName + ". Cannot resolve reminder: " + pattern);
    }

    String answer = pattern;
    if (ObjectHelper.isNotEmpty(path) && ObjectHelper.isNotEmpty(pattern)) {
      // done file must always be in same directory as the real file name
      answer = path + File.separator + pattern;
    }

    if (getConfiguration().needToNormalize()) {
      // must normalize path to cater for Windows and other OS
      answer = FileUtil.normalizePath(answer);
    }

    return answer;
  }
예제 #4
0
  /** Moves any existing file due fileExists=Move is in use. */
  private void doMoveExistingFile(String name, String targetName)
      throws GenericFileOperationFailedException {
    // need to evaluate using a dummy and simulate the file first, to have access to all the file
    // attributes
    // create a dummy exchange as Exchange is needed for expression evaluation
    // we support only the following 3 tokens.
    Exchange dummy = endpoint.createExchange();
    // we only support relative paths for the ftp component, so dont provide any parent
    String parent = null;
    String onlyName = FileUtil.stripPath(targetName);
    dummy.getIn().setHeader(Exchange.FILE_NAME, targetName);
    dummy.getIn().setHeader(Exchange.FILE_NAME_ONLY, onlyName);
    dummy.getIn().setHeader(Exchange.FILE_PARENT, parent);

    String to = endpoint.getMoveExisting().evaluate(dummy, String.class);
    // we only support relative paths for the ftp component, so strip any leading paths
    to = FileUtil.stripLeadingSeparator(to);
    // normalize accordingly to configuration
    to = endpoint.getConfiguration().normalizePath(to);
    if (ObjectHelper.isEmpty(to)) {
      throw new GenericFileOperationFailedException(
          "moveExisting evaluated as empty String, cannot move existing file: " + name);
    }

    // do we have a sub directory
    String dir = FileUtil.onlyPath(to);
    if (dir != null) {
      // ensure directory exists
      buildDirectory(dir, false);
    }

    // deal if there already exists a file
    if (existsFile(to)) {
      if (endpoint.isEagerDeleteTargetFile()) {
        LOG.trace("Deleting existing file: {}", to);
        deleteFile(to);
      } else {
        throw new GenericFileOperationFailedException(
            "Cannot moved existing file from: "
                + name
                + " to: "
                + to
                + " as there already exists a file: "
                + to);
      }
    }

    LOG.trace("Moving existing file: {} to: {}", name, to);
    if (!renameFile(targetName, to)) {
      throw new GenericFileOperationFailedException(
          "Cannot rename file from: " + name + " to: " + to);
    }
  }
예제 #5
0
  @Override
  protected boolean isMatched(GenericFile<FTPFile> file, String doneFileName, List<FTPFile> files) {
    String onlyName = FileUtil.stripPath(doneFileName);

    for (FTPFile f : files) {
      if (f.getName().equals(onlyName)) {
        return true;
      }
    }

    log.trace("Done file: {} does not exist", doneFileName);
    return false;
  }
예제 #6
0
  public boolean existsFile(String name) throws GenericFileOperationFailedException {
    LOG.trace("existsFile({})", name);
    if (endpoint.isFastExistsCheck()) {
      return fastExistsFile(name);
    }
    // check whether a file already exists
    String directory = FileUtil.onlyPath(name);
    if (directory == null) {
      // assume current dir if no path could be extracted
      directory = ".";
    }
    String onlyName = FileUtil.stripPath(name);

    try {
      @SuppressWarnings("rawtypes")
      Vector files = channel.ls(directory);
      // can return either null or an empty list depending on FTP servers
      if (files == null) {
        return false;
      }
      for (Object file : files) {
        ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) file;
        String existing = entry.getFilename();
        LOG.trace("Existing file: {}, target file: {}", existing, name);
        existing = FileUtil.stripPath(existing);
        if (existing != null && existing.equals(onlyName)) {
          return true;
        }
      }
      return false;
    } catch (SftpException e) {
      // or an exception can be thrown with id 2 which means file does not exists
      if (ChannelSftp.SSH_FX_NO_SUCH_FILE == e.id) {
        return false;
      }
      // otherwise its a more serious error so rethrow
      throw new GenericFileOperationFailedException(e.getMessage(), e);
    }
  }
예제 #7
0
  @SuppressWarnings("unchecked")
  private boolean retrieveFileToStreamInBody(String name, Exchange exchange)
      throws GenericFileOperationFailedException {
    OutputStream os = null;
    String currentDir = null;
    try {
      GenericFile<ChannelSftp.LsEntry> target =
          (GenericFile<ChannelSftp.LsEntry>) exchange.getProperty(FileComponent.FILE_EXCHANGE_FILE);
      ObjectHelper.notNull(
          target, "Exchange should have the " + FileComponent.FILE_EXCHANGE_FILE + " set");

      String remoteName = name;
      if (endpoint.getConfiguration().isStepwise()) {
        // remember current directory
        currentDir = getCurrentDirectory();

        // change directory to path where the file is to be retrieved
        // (must do this as some FTP servers cannot retrieve using absolute path)
        String path = FileUtil.onlyPath(name);
        if (path != null) {
          changeCurrentDirectory(path);
        }
        // remote name is now only the file name as we just changed directory
        remoteName = FileUtil.stripPath(name);
      }

      // use input stream which works with Apache SSHD used for testing
      InputStream is = channel.get(remoteName);

      if (endpoint.getConfiguration().isStreamDownload()) {
        target.setBody(is);
        exchange.getIn().setHeader(RemoteFileComponent.REMOTE_FILE_INPUT_STREAM, is);
      } else {
        os = new ByteArrayOutputStream();
        target.setBody(os);
        IOHelper.copyAndCloseInput(is, os);
      }

      return true;
    } catch (IOException e) {
      throw new GenericFileOperationFailedException("Cannot retrieve file: " + name, e);
    } catch (SftpException e) {
      throw new GenericFileOperationFailedException("Cannot retrieve file: " + name, e);
    } finally {
      IOHelper.close(os, "retrieve: " + name, LOG);
      // change back to current directory if we changed directory
      if (currentDir != null) {
        changeCurrentDirectory(currentDir);
      }
    }
  }
예제 #8
0
  @SuppressWarnings("unchecked")
  private boolean retrieveFileToFileInLocalWorkDirectory(String name, Exchange exchange)
      throws GenericFileOperationFailedException {
    File temp;
    File local = new File(endpoint.getLocalWorkDirectory());
    OutputStream os;
    GenericFile<ChannelSftp.LsEntry> file =
        (GenericFile<ChannelSftp.LsEntry>) exchange.getProperty(FileComponent.FILE_EXCHANGE_FILE);
    ObjectHelper.notNull(
        file, "Exchange should have the " + FileComponent.FILE_EXCHANGE_FILE + " set");
    try {
      // use relative filename in local work directory
      String relativeName = file.getRelativeFilePath();

      temp = new File(local, relativeName + ".inprogress");
      local = new File(local, relativeName);

      // create directory to local work file
      local.mkdirs();

      // delete any existing files
      if (temp.exists()) {
        if (!FileUtil.deleteFile(temp)) {
          throw new GenericFileOperationFailedException(
              "Cannot delete existing local work file: " + temp);
        }
      }
      if (local.exists()) {
        if (!FileUtil.deleteFile(local)) {
          throw new GenericFileOperationFailedException(
              "Cannot delete existing local work file: " + local);
        }
      }

      // create new temp local work file
      if (!temp.createNewFile()) {
        throw new GenericFileOperationFailedException("Cannot create new local work file: " + temp);
      }

      // store content as a file in the local work directory in the temp handle
      os = new FileOutputStream(temp);

      // set header with the path to the local work file
      exchange.getIn().setHeader(Exchange.FILE_LOCAL_WORK_PATH, local.getPath());
    } catch (Exception e) {
      throw new GenericFileOperationFailedException("Cannot create new local work file: " + local);
    }
    String currentDir = null;
    try {
      // store the java.io.File handle as the body
      file.setBody(local);

      String remoteName = name;
      if (endpoint.getConfiguration().isStepwise()) {
        // remember current directory
        currentDir = getCurrentDirectory();

        // change directory to path where the file is to be retrieved
        // (must do this as some FTP servers cannot retrieve using absolute path)
        String path = FileUtil.onlyPath(name);
        if (path != null) {
          changeCurrentDirectory(path);
        }
        // remote name is now only the file name as we just changed directory
        remoteName = FileUtil.stripPath(name);
      }

      channel.get(remoteName, os);

    } catch (SftpException e) {
      LOG.trace(
          "Error occurred during retrieving file: {} to local directory. Deleting local work file: {}",
          name,
          temp);
      // failed to retrieve the file so we need to close streams and delete in progress file
      // must close stream before deleting file
      IOHelper.close(os, "retrieve: " + name, LOG);
      boolean deleted = FileUtil.deleteFile(temp);
      if (!deleted) {
        LOG.warn(
            "Error occurred during retrieving file: "
                + name
                + " to local directory. Cannot delete local work file: "
                + temp);
      }
      throw new GenericFileOperationFailedException("Cannot retrieve file: " + name, e);
    } finally {
      IOHelper.close(os, "retrieve: " + name, LOG);

      // change back to current directory if we changed directory
      if (currentDir != null) {
        changeCurrentDirectory(currentDir);
      }
    }

    LOG.debug("Retrieve file to local work file result: true");

    // operation went okay so rename temp to local after we have retrieved the data
    LOG.trace("Renaming local in progress file from: {} to: {}", temp, local);
    try {
      if (!FileUtil.renameFile(temp, local, false)) {
        throw new GenericFileOperationFailedException(
            "Cannot rename local work file from: " + temp + " to: " + local);
      }
    } catch (IOException e) {
      throw new GenericFileOperationFailedException(
          "Cannot rename local work file from: " + temp + " to: " + local, e);
    }

    return true;
  }