You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2012/08/22 19:00:24 UTC
svn commit: r1376140 - in /camel/trunk:
camel-core/src/main/java/org/apache/camel/component/file/
camel-core/src/test/java/org/apache/camel/component/file/
components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/
components/camel-ftp/...
Author: davsclaus
Date: Wed Aug 22 17:00:24 2012
New Revision: 1376140
URL: http://svn.apache.org/viewvc?rev=1376140&view=rev
Log:
CAMEL-5521: Added fileExists=Move to file/ftp producer.
Added:
camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerMoveExistingTest.java (with props)
camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerMoveExistingTest.java (with props)
camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpProducerMoveExistingTest.java (with props)
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileEndpoint.java
camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileOperations.java
camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileExist.java
camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpOperations.java
camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java
camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileEndpoint.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileEndpoint.java?rev=1376140&r1=1376139&r2=1376140&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileEndpoint.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileEndpoint.java Wed Aug 22 17:00:24 2012
@@ -98,6 +98,13 @@ public class FileEndpoint extends Generi
throw new IllegalArgumentException("You cannot set both fileExist=Append and tempPrefix options");
}
+ // ensure fileExist and moveExisting is configured correctly if in use
+ if (getFileExist() == GenericFileExist.Move && getMoveExisting() == null) {
+ throw new IllegalArgumentException("You must configure moveExisting option when fileExist=Move");
+ } else if (getMoveExisting() != null && getFileExist() != GenericFileExist.Move) {
+ throw new IllegalArgumentException("You must configure fileExist=Move when moveExisting has been set");
+ }
+
return new GenericFileProducer<File>(this, operations);
}
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileOperations.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileOperations.java?rev=1376140&r1=1376139&r2=1376140&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileOperations.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/FileOperations.java Wed Aug 22 17:00:24 2012
@@ -169,7 +169,10 @@ public class FileOperations implements G
return true;
} else if (endpoint.getFileExist() == GenericFileExist.Fail) {
throw new GenericFileOperationFailedException("File already exist: " + file + ". Cannot write new file.");
- }
+ } else if (endpoint.getFileExist() == GenericFileExist.Move) {
+ // move any existing file first
+ doMoveExistingFile(fileName);
+ }
}
// Do an explicit test for a null body and decide what to do
@@ -262,6 +265,56 @@ public class FileOperations implements G
}
}
+ /**
+ * Moves any existing file due fileExists=Move is in use.
+ */
+ private void doMoveExistingFile(String fileName) 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();
+ String parent = FileUtil.onlyPath(fileName);
+ String onlyName = FileUtil.stripPath(fileName);
+ dummy.getIn().setHeader(Exchange.FILE_NAME, fileName);
+ dummy.getIn().setHeader(Exchange.FILE_NAME_ONLY, onlyName);
+ dummy.getIn().setHeader(Exchange.FILE_PARENT, parent);
+
+ String to = endpoint.getMoveExisting().evaluate(dummy, String.class);
+ // we must normalize it (to avoid having both \ and / in the name which confuses java.io.File)
+ to = FileUtil.normalizePath(to);
+ if (ObjectHelper.isEmpty(to)) {
+ throw new GenericFileOperationFailedException("moveExisting evaluated as empty String, cannot move existing file: " + fileName);
+ }
+
+ // ensure any paths is created before we rename as the renamed file may be in a different path (which may be non exiting)
+ // use java.io.File to compute the file path
+ File toFile = new File(to);
+ String directory = toFile.getParent();
+ boolean absolute = FileUtil.isAbsolute(toFile);
+ if (directory != null) {
+ if (!buildDirectory(directory, absolute)) {
+ LOG.debug("Cannot build directory [{}] (could be because of denied permissions)", directory);
+ }
+ }
+
+ // deal if there already exists a file
+ if (existsFile(to)) {
+ if (endpoint.isEagerDeleteTargetFile()) {
+ LOG.trace("Deleting existing file: {}", to);
+ if (!deleteFile(to)) {
+ throw new GenericFileOperationFailedException("Cannot delete file: " + to);
+ }
+ } else {
+ throw new GenericFileOperationFailedException("Cannot moved existing file from: " + fileName + " to: " + to + " as there already exists a file: " + to);
+ }
+ }
+
+ LOG.trace("Moving existing file: {} to: {}", fileName, to);
+ if (!renameFile(fileName, to)) {
+ throw new GenericFileOperationFailedException("Cannot rename file from: " + fileName + " to: " + to);
+ }
+ }
+
private void keepLastModified(Exchange exchange, File file) {
if (endpoint.isKeepLastModified()) {
Long last;
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java?rev=1376140&r1=1376139&r2=1376140&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java Wed Aug 22 17:00:24 2012
@@ -84,6 +84,7 @@ public abstract class GenericFileEndpoin
protected Expression move;
protected Expression moveFailed;
protected Expression preMove;
+ protected Expression moveExisting;
protected Boolean idempotent;
protected IdempotentRepository<String> idempotentRepository;
protected GenericFileFilter<T> filter;
@@ -344,6 +345,23 @@ public abstract class GenericFileEndpoin
this.preMove = createFileLanguageExpression(expression);
}
+ public Expression getMoveExisting() {
+ return moveExisting;
+ }
+
+ public void setMoveExisting(Expression moveExisting) {
+ this.moveExisting = moveExisting;
+ }
+
+ /**
+ * Sets the move existing expression based on
+ * {@link org.apache.camel.language.simple.SimpleLanguage}
+ */
+ public void setMoveExisting(String fileLanguageExpression) {
+ String expression = configureMoveOrPreMoveExpression(fileLanguageExpression);
+ this.moveExisting = createFileLanguageExpression(expression);
+ }
+
public Expression getFileName() {
return fileName;
}
@@ -661,8 +679,6 @@ public abstract class GenericFileEndpoin
/**
* Set up the exchange properties with the options of the file endpoint
- *
- * @param exchange
*/
public void configureExchange(Exchange exchange) {
// Now we just set the charset property here
@@ -672,8 +688,7 @@ public abstract class GenericFileEndpoin
}
/**
- * Strategy to configure the move or premove option based on a String input.
- * <p/>
+ * Strategy to configure the move, preMove, or moveExisting option based on a String input.
*
* @param expression the original string input
* @return configured string or the original if no modifications is needed
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileExist.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileExist.java?rev=1376140&r1=1376139&r2=1376140&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileExist.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileExist.java Wed Aug 22 17:00:24 2012
@@ -23,5 +23,5 @@ package org.apache.camel.component.file;
*/
public enum GenericFileExist {
- Override, Append, Fail, Ignore
+ Override, Append, Fail, Ignore, Move
}
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerMoveExistingTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerMoveExistingTest.java?rev=1376140&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerMoveExistingTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerMoveExistingTest.java Wed Aug 22 17:00:24 2012
@@ -0,0 +1,114 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.file;
+
+import java.io.File;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+
+/**
+ *
+ */
+public class FileProducerMoveExistingTest extends ContextTestSupport {
+
+ @Override
+ protected void setUp() throws Exception {
+ deleteDirectory("target/file");
+ super.setUp();
+ }
+
+ public void testExistingFileDoesNotExists() throws Exception {
+ template.sendBodyAndHeader("file://target/file?fileExist=Move&moveExisting=${file:parent}/renamed-${file:onlyname}",
+ "Hello World", Exchange.FILE_NAME, "hello.txt");
+
+ assertFileExists("target/file/hello.txt");
+ assertFileNotExists("target/file/renamed-hello.txt");
+ }
+
+ public void testExistingFileExists() throws Exception {
+ template.sendBodyAndHeader("file://target/file?fileExist=Move&moveExisting=${file:parent}/renamed-${file:onlyname}",
+ "Hello World", Exchange.FILE_NAME, "hello.txt");
+ template.sendBodyAndHeader("file://target/file?fileExist=Move&moveExisting=${file:parent}/renamed-${file:onlyname}",
+ "Bye World", Exchange.FILE_NAME, "hello.txt");
+
+ assertFileExists("target/file/hello.txt");
+ assertEquals("Bye World", context.getTypeConverter().convertTo(String.class, new File("target/file/hello.txt")));
+
+ assertFileExists("target/file/renamed-hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File("target/file/renamed-hello.txt")));
+ }
+
+ public void testExistingFileExistsMoveSubDir() throws Exception {
+ template.sendBodyAndHeader("file://target/file?fileExist=Move&moveExisting=backup", "Hello World", Exchange.FILE_NAME, "hello.txt");
+ template.sendBodyAndHeader("file://target/file?fileExist=Move&moveExisting=backup", "Bye World", Exchange.FILE_NAME, "hello.txt");
+
+ assertFileExists("target/file/hello.txt");
+ assertEquals("Bye World", context.getTypeConverter().convertTo(String.class, new File("target/file/hello.txt")));
+
+ // would move into sub directory and keep existing name as is
+ assertFileExists("target/file/backup/hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File("target/file/backup/hello.txt")));
+ }
+
+ public void testFailOnMoveExistingFileExistsEagerDeleteTrue() throws Exception {
+ template.sendBodyAndHeader("file://target/file", "Old file", Exchange.FILE_NAME, "renamed-hello.txt");
+
+ template.sendBodyAndHeader("file://target/file?fileExist=Move&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=true",
+ "Hello World", Exchange.FILE_NAME, "hello.txt");
+ // we should be okay as we will just delete any existing file
+ template.sendBodyAndHeader("file://target/file?fileExist=Move&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=true",
+ "Bye World", Exchange.FILE_NAME, "hello.txt");
+
+ // we could write the new file so the old context should be there
+ assertFileExists("target/file/hello.txt");
+ assertEquals("Bye World", context.getTypeConverter().convertTo(String.class, new File("target/file/hello.txt")));
+
+ // and the renamed file should be overridden
+ assertFileExists("target/file/renamed-hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File("target/file/renamed-hello.txt")));
+ }
+
+ public void testFailOnMoveExistingFileExistsEagerDeleteFalse() throws Exception {
+ template.sendBodyAndHeader("file://target/file", "Old file", Exchange.FILE_NAME, "renamed-hello.txt");
+
+ template.sendBodyAndHeader("file://target/file?fileExist=Move&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=false",
+ "Hello World", Exchange.FILE_NAME, "hello.txt");
+ try {
+ template.sendBodyAndHeader("file://target/file?fileExist=Move&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=false",
+ "Bye World", Exchange.FILE_NAME, "hello.txt");
+ fail("Should have thrown an exception");
+ } catch (CamelExecutionException e) {
+ GenericFileOperationFailedException cause = assertIsInstanceOf(GenericFileOperationFailedException.class, e.getCause());
+ assertTrue(cause.getMessage().startsWith("Cannot moved existing file"));
+ }
+
+ // we could not write the new file so the previous context should be there
+ assertFileExists("target/file/hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File("target/file/hello.txt")));
+
+ // and the renamed file should be untouched
+ assertFileExists("target/file/renamed-hello.txt");
+ assertEquals("Old file", context.getTypeConverter().convertTo(String.class, new File("target/file/renamed-hello.txt")));
+ }
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+}
Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerMoveExistingTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerMoveExistingTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpOperations.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpOperations.java?rev=1376140&r1=1376139&r2=1376140&view=diff
==============================================================================
--- camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpOperations.java (original)
+++ camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpOperations.java Wed Aug 22 17:00:24 2012
@@ -34,6 +34,7 @@ import org.apache.camel.component.file.F
import org.apache.camel.component.file.GenericFile;
import org.apache.camel.component.file.GenericFileEndpoint;
import org.apache.camel.component.file.GenericFileExist;
+import org.apache.camel.component.file.GenericFileMessage;
import org.apache.camel.component.file.GenericFileOperationFailedException;
import org.apache.camel.util.FileUtil;
import org.apache.camel.util.IOHelper;
@@ -138,7 +139,7 @@ public class FtpOperations implements Re
// must set soTimeout after connect
if (endpoint instanceof FtpEndpoint) {
- FtpEndpoint<?> ftpEndpoint = (FtpEndpoint<?>) endpoint;
+ FtpEndpoint ftpEndpoint = (FtpEndpoint) endpoint;
if (ftpEndpoint.getSoTimeout() > 0) {
log.trace("Using SoTimeout=" + ftpEndpoint.getSoTimeout());
try {
@@ -487,7 +488,9 @@ public class FtpOperations implements Re
log.trace("doStoreFile({})", targetName);
// if an existing file already exists what should we do?
- if (endpoint.getFileExist() == GenericFileExist.Ignore || endpoint.getFileExist() == GenericFileExist.Fail) {
+ if (endpoint.getFileExist() == GenericFileExist.Ignore
+ || endpoint.getFileExist() == GenericFileExist.Fail
+ || endpoint.getFileExist() == GenericFileExist.Move) {
boolean existFile = existsFile(targetName);
if (existFile && endpoint.getFileExist() == GenericFileExist.Ignore) {
// ignore but indicate that the file was written
@@ -495,6 +498,9 @@ public class FtpOperations implements Re
return true;
} else if (existFile && endpoint.getFileExist() == GenericFileExist.Fail) {
throw new GenericFileOperationFailedException("File already exist: " + name + ". Cannot write new file.");
+ } else if (existFile && endpoint.getFileExist() == GenericFileExist.Move) {
+ // move any existing file first
+ doMoveExistingFile(name, targetName);
}
}
@@ -529,6 +535,61 @@ public class FtpOperations implements Re
}
}
+ /**
+ * 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);
+ boolean result;
+ try {
+ result = client.deleteFile(to);
+ if (!result) {
+ throw new GenericFileOperationFailedException("Cannot delete file: " + to);
+ }
+ } catch (IOException e) {
+ throw new GenericFileOperationFailedException(client.getReplyCode(), client.getReplyString(), "Cannot delete file: " + to, e);
+ }
+ } 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);
+ }
+ }
+
public boolean existsFile(String name) throws GenericFileOperationFailedException {
log.trace("existsFile({})", name);
if (endpoint.isFastExistsCheck()) {
Modified: camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java?rev=1376140&r1=1376139&r2=1376140&view=diff
==============================================================================
--- camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java (original)
+++ camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java Wed Aug 22 17:00:24 2012
@@ -22,6 +22,7 @@ import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.component.file.GenericFile;
import org.apache.camel.component.file.GenericFileEndpoint;
+import org.apache.camel.component.file.GenericFileExist;
import org.apache.camel.component.file.GenericFileProducer;
import org.apache.camel.impl.DefaultExchange;
import org.apache.camel.processor.idempotent.MemoryIdempotentRepository;
@@ -69,6 +70,14 @@ public abstract class RemoteFileEndpoint
@Override
public GenericFileProducer<T> createProducer() throws Exception {
afterPropertiesSet();
+
+ // ensure fileExist and moveExisting is configured correctly if in use
+ if (getFileExist() == GenericFileExist.Move && getMoveExisting() == null) {
+ throw new IllegalArgumentException("You must configure moveExisting option when fileExist=Move");
+ } else if (getMoveExisting() != null && getFileExist() != GenericFileExist.Move) {
+ throw new IllegalArgumentException("You must configure fileExist=Move when moveExisting has been set");
+ }
+
return buildProducer();
}
Modified: camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java?rev=1376140&r1=1376139&r2=1376140&view=diff
==============================================================================
--- camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java (original)
+++ camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java Wed Aug 22 17:00:24 2012
@@ -661,7 +661,9 @@ public class SftpOperations implements R
LOG.trace("doStoreFile({})", targetName);
// if an existing file already exists what should we do?
- if (endpoint.getFileExist() == GenericFileExist.Ignore || endpoint.getFileExist() == GenericFileExist.Fail) {
+ if (endpoint.getFileExist() == GenericFileExist.Ignore
+ || endpoint.getFileExist() == GenericFileExist.Fail
+ || endpoint.getFileExist() == GenericFileExist.Move) {
boolean existFile = existsFile(targetName);
if (existFile && endpoint.getFileExist() == GenericFileExist.Ignore) {
// ignore but indicate that the file was written
@@ -669,6 +671,9 @@ public class SftpOperations implements R
return true;
} else if (existFile && endpoint.getFileExist() == GenericFileExist.Fail) {
throw new GenericFileOperationFailedException("File already exist: " + name + ". Cannot write new file.");
+ } else if (existFile && endpoint.getFileExist() == GenericFileExist.Move) {
+ // move any existing file first
+ doMoveExistingFile(name, targetName);
}
}
@@ -716,6 +721,53 @@ public class SftpOperations implements R
}
}
+ /**
+ * 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);
+ }
+ }
+
public boolean existsFile(String name) throws GenericFileOperationFailedException {
LOG.trace("existsFile({})", name);
if (endpoint.isFastExistsCheck()) {
Added: camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerMoveExistingTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerMoveExistingTest.java?rev=1376140&view=auto
==============================================================================
--- camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerMoveExistingTest.java (added)
+++ camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerMoveExistingTest.java Wed Aug 22 17:00:24 2012
@@ -0,0 +1,111 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.file.remote;
+
+import java.io.File;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.file.GenericFileOperationFailedException;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class FtpProducerMoveExistingTest extends FtpServerTestSupport {
+
+ private String getFtpUrl() {
+ return "ftp://admin@localhost:" + getPort() + "/move?password=admin&fileExist=Move";
+ }
+
+ @Test
+ public void testExistingFileDoesNotExists() throws Exception {
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}", "Hello World", Exchange.FILE_NAME, "hello.txt");
+
+ assertFileExists(FTP_ROOT_DIR + "/move/hello.txt");
+ assertFileNotExists(FTP_ROOT_DIR + "/move/renamed-hello.txt");
+ }
+
+ @Test
+ public void testExistingFileExists() throws Exception {
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}", "Hello World", Exchange.FILE_NAME, "hello.txt");
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}", "Bye World", Exchange.FILE_NAME, "hello.txt");
+
+ assertFileExists(FTP_ROOT_DIR + "/move/hello.txt");
+ assertEquals("Bye World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/hello.txt")));
+
+ assertFileExists(FTP_ROOT_DIR + "/move/renamed-hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/renamed-hello.txt")));
+ }
+
+ @Test
+ public void testExistingFileExistsMoveSubDir() throws Exception {
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=backup", "Hello World", Exchange.FILE_NAME, "hello.txt");
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=backup", "Bye World", Exchange.FILE_NAME, "hello.txt");
+
+ assertFileExists(FTP_ROOT_DIR + "/move/hello.txt");
+ assertEquals("Bye World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/hello.txt")));
+
+ // would move into sub directory and keep existing name as is
+ assertFileExists(FTP_ROOT_DIR + "/move/backup/hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/backup/hello.txt")));
+ }
+
+ @Test
+ public void testFailOnMoveExistingFileExistsEagerDeleteTrue() throws Exception {
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=true", "Old file", Exchange.FILE_NAME, "renamed-hello.txt");
+
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=true", "Hello World", Exchange.FILE_NAME, "hello.txt");
+ // we should be okay as we will just delete any existing file
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=true", "Bye World", Exchange.FILE_NAME, "hello.txt");
+
+ // we could write the new file so the old context should be there
+ assertFileExists(FTP_ROOT_DIR + "/move/hello.txt");
+ assertEquals("Bye World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/hello.txt")));
+
+ // and the renamed file should be overridden
+ assertFileExists(FTP_ROOT_DIR + "/move/renamed-hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/renamed-hello.txt")));
+ }
+
+ @Test
+ public void testFailOnMoveExistingFileExistsEagerDeleteFalse() throws Exception {
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=true", "Old file", Exchange.FILE_NAME, "renamed-hello.txt");
+
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=false", "Hello World", Exchange.FILE_NAME, "hello.txt");
+ try {
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=false", "Bye World", Exchange.FILE_NAME, "hello.txt");
+ fail("Should have thrown an exception");
+ } catch (CamelExecutionException e) {
+ GenericFileOperationFailedException cause = assertIsInstanceOf(GenericFileOperationFailedException.class, e.getCause());
+ assertTrue(cause.getMessage().startsWith("Cannot moved existing file"));
+ }
+
+ // we could not write the new file so the previous context should be there
+ assertFileExists(FTP_ROOT_DIR + "/move/hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/hello.txt")));
+
+ // and the renamed file should be untouched
+ assertFileExists(FTP_ROOT_DIR + "/move/renamed-hello.txt");
+ assertEquals("Old file", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/renamed-hello.txt")));
+ }
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+}
Propchange: camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerMoveExistingTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerMoveExistingTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpProducerMoveExistingTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpProducerMoveExistingTest.java?rev=1376140&view=auto
==============================================================================
--- camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpProducerMoveExistingTest.java (added)
+++ camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpProducerMoveExistingTest.java Wed Aug 22 17:00:24 2012
@@ -0,0 +1,131 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.file.remote.sftp;
+
+import java.io.File;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.file.GenericFileOperationFailedException;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class SftpProducerMoveExistingTest extends SftpServerTestSupport {
+
+ private String getFtpUrl() {
+ return "sftp://admin@localhost:" + getPort() + "/" + FTP_ROOT_DIR + "/move?password=admin&fileExist=Move";
+ }
+
+ @Test
+ public void testExistingFileDoesNotExists() throws Exception {
+ if (!canTest()) {
+ return;
+ }
+
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}", "Hello World", Exchange.FILE_NAME, "hello.txt");
+
+ assertFileExists(FTP_ROOT_DIR + "/move/hello.txt");
+ assertFileNotExists(FTP_ROOT_DIR + "/move/renamed-hello.txt");
+ }
+
+ @Test
+ public void testExistingFileExists() throws Exception {
+ if (!canTest()) {
+ return;
+ }
+
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}", "Hello World", Exchange.FILE_NAME, "hello.txt");
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}", "Bye World", Exchange.FILE_NAME, "hello.txt");
+
+ assertFileExists(FTP_ROOT_DIR + "/move/hello.txt");
+ assertEquals("Bye World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/hello.txt")));
+
+ assertFileExists(FTP_ROOT_DIR + "/move/renamed-hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/renamed-hello.txt")));
+ }
+
+ @Test
+ public void testExistingFileExistsMoveSubDir() throws Exception {
+ if (!canTest()) {
+ return;
+ }
+
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=backup", "Hello World", Exchange.FILE_NAME, "hello.txt");
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=backup", "Bye World", Exchange.FILE_NAME, "hello.txt");
+
+ assertFileExists(FTP_ROOT_DIR + "/move/hello.txt");
+ assertEquals("Bye World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/hello.txt")));
+
+ // would move into sub directory and keep existing name as is
+ assertFileExists(FTP_ROOT_DIR + "/move/backup/hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/backup/hello.txt")));
+ }
+
+ @Test
+ public void testFailOnMoveExistingFileExistsEagerDeleteTrue() throws Exception {
+ if (!canTest()) {
+ return;
+ }
+
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=true", "Old file", Exchange.FILE_NAME, "renamed-hello.txt");
+
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=true", "Hello World", Exchange.FILE_NAME, "hello.txt");
+ // we should be okay as we will just delete any existing file
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=true", "Bye World", Exchange.FILE_NAME, "hello.txt");
+
+ // we could write the new file so the old context should be there
+ assertFileExists(FTP_ROOT_DIR + "/move/hello.txt");
+ assertEquals("Bye World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/hello.txt")));
+
+ // and the renamed file should be overridden
+ assertFileExists(FTP_ROOT_DIR + "/move/renamed-hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/renamed-hello.txt")));
+ }
+
+ @Test
+ public void testFailOnMoveExistingFileExistsEagerDeleteFalse() throws Exception {
+ if (!canTest()) {
+ return;
+ }
+
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=true", "Old file", Exchange.FILE_NAME, "renamed-hello.txt");
+
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=false", "Hello World", Exchange.FILE_NAME, "hello.txt");
+ try {
+ template.sendBodyAndHeader(getFtpUrl() + "&moveExisting=${file:parent}/renamed-${file:onlyname}&eagerDeleteTargetFile=false", "Bye World", Exchange.FILE_NAME, "hello.txt");
+ fail("Should have thrown an exception");
+ } catch (CamelExecutionException e) {
+ GenericFileOperationFailedException cause = assertIsInstanceOf(GenericFileOperationFailedException.class, e.getCause());
+ assertTrue(cause.getMessage().startsWith("Cannot moved existing file"));
+ }
+
+ // we could not write the new file so the previous context should be there
+ assertFileExists(FTP_ROOT_DIR + "/move/hello.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/hello.txt")));
+
+ // and the renamed file should be untouched
+ assertFileExists(FTP_ROOT_DIR + "/move/renamed-hello.txt");
+ assertEquals("Old file", context.getTypeConverter().convertTo(String.class, new File(FTP_ROOT_DIR + "/move/renamed-hello.txt")));
+ }
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+}
Propchange: camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpProducerMoveExistingTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/sftp/SftpProducerMoveExistingTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date