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; }
/** 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); } }
@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; }
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); } }
@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); } } }
@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; }