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 2013/03/27 11:57:50 UTC
svn commit: r1461507 - in /camel/trunk/camel-core/src:
main/java/org/apache/camel/component/file/
main/java/org/apache/camel/converter/ main/java/org/apache/camel/util/
test/java/org/apache/camel/component/file/
Author: davsclaus
Date: Wed Mar 27 10:57:50 2013
New Revision: 1461507
URL: http://svn.apache.org/r1461507
Log:
CAMEL-6205: Added forceWrites option to file producer. Thanks to Christian Tytgat for the patch.
Added:
camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerNoForcedWritesTest.java
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/converter/IOConverter.java
camel/trunk/camel-core/src/main/java/org/apache/camel/util/IOHelper.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=1461507&r1=1461506&r2=1461507&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 Mar 27 10:57:50 2013
@@ -34,6 +34,7 @@ public class FileEndpoint extends Generi
private FileOperations operations = new FileOperations(this);
private File file;
private boolean copyAndDeleteOnRenameFail = true;
+ private boolean forceWrites = true;
public FileEndpoint() {
// use marker file as default exclusive read locks
@@ -165,4 +166,12 @@ public class FileEndpoint extends Generi
public void setCopyAndDeleteOnRenameFail(boolean copyAndDeleteOnRenameFail) {
this.copyAndDeleteOnRenameFail = copyAndDeleteOnRenameFail;
}
+
+ public boolean isForceWrites() {
+ return forceWrites;
+ }
+
+ public void setForceWrites(boolean forceWrites) {
+ this.forceWrites = forceWrites;
+ }
}
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=1461507&r1=1461506&r2=1461507&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 Mar 27 10:57:50 2013
@@ -359,9 +359,7 @@ public class FileOperations implements G
}
} finally {
IOHelper.close(in, source.getName(), LOG);
- // force updates to be written, and then close afterwards
- IOHelper.force(out, target.getName(), LOG);
- IOHelper.close(out, target.getName(), LOG);
+ IOHelper.close(out, target.getName(), LOG, endpoint.isForceWrites());
}
}
@@ -383,25 +381,24 @@ public class FileOperations implements G
}
} finally {
IOHelper.close(in, target.getName(), LOG);
- // force updates to be written, and then close afterwards
- IOHelper.force(out, target.getName(), LOG);
- IOHelper.close(out, target.getName(), LOG);
+ IOHelper.close(out, target.getName(), LOG, endpoint.isForceWrites());
}
}
private void writeFileByReaderWithCharset(Reader in, File target, String charset) throws IOException {
boolean append = endpoint.getFileExist() == GenericFileExist.Append;
- Writer out = IOConverter.toWriter(target, append, charset);
+ FileOutputStream os = new FileOutputStream(target, append);
+ Writer out = IOConverter.toWriter(os, charset);
try {
LOG.debug("Using Reader to write file: {} with charset: {}", target, charset);
int size = endpoint.getBufferSize();
IOHelper.copy(in, out, size);
} finally {
IOHelper.close(in, target.getName(), LOG);
- IOHelper.close(out, target.getName(), LOG);
+ IOHelper.close(out, os, target.getName(), LOG, endpoint.isForceWrites());
}
}
-
+
/**
* Creates a new file if the file doesn't exist.
* If the endpoint's existing file logic is set to 'Override' then the target file will be truncated
@@ -416,8 +413,7 @@ public class FileOperations implements G
try {
out.truncate(0);
} finally {
- IOHelper.force(out, target.getName(), LOG);
- IOHelper.close(out, target.getName(), LOG);
+ IOHelper.close(out, target.getName(), LOG, endpoint.isForceWrites());
}
}
}
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/converter/IOConverter.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/converter/IOConverter.java?rev=1461507&r1=1461506&r2=1461507&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/converter/IOConverter.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/converter/IOConverter.java Wed Mar 27 10:57:50 2013
@@ -130,16 +130,21 @@ public final class IOConverter {
*/
@Deprecated
public static BufferedWriter toWriter(File file) throws IOException {
- return toWriter(file, false, IOHelper.getCharsetName(null, true));
+ FileOutputStream os = new FileOutputStream(file, false);
+ return toWriter(os, IOHelper.getCharsetName(null, true));
}
@Converter
public static BufferedWriter toWriter(File file, Exchange exchange) throws IOException {
- return toWriter(file, false, IOHelper.getCharsetName(exchange));
+ FileOutputStream os = new FileOutputStream(file, false);
+ return toWriter(os, IOHelper.getCharsetName(exchange));
}
public static BufferedWriter toWriter(File file, boolean append, String charset) throws IOException {
- FileOutputStream os = new FileOutputStream(file, append);
+ return toWriter(new FileOutputStream(file, append), charset);
+ }
+
+ public static BufferedWriter toWriter(FileOutputStream os, String charset) throws IOException {
return IOHelper.buffered(new EncodingFileWriter(os, charset));
}
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/IOHelper.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/IOHelper.java?rev=1461507&r1=1461506&r2=1461507&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/util/IOHelper.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/IOHelper.java Wed Mar 27 10:57:50 2013
@@ -21,6 +21,7 @@ import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Closeable;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -230,6 +231,62 @@ public final class IOHelper {
}
/**
+ * Forces any updates to a FileOutputStream be written to the storage device that contains it.
+ *
+ * @param os the file output stream
+ * @param name the name of the resource
+ * @param log the log to use when reporting warnings, will use this class's own {@link Logger} if <tt>log == null</tt>
+ */
+ public static void force(FileOutputStream os, String name, Logger log) {
+ try {
+ if (os != null) {
+ os.getFD().sync();
+ }
+ } catch (Exception e) {
+ if (log == null) {
+ // then fallback to use the own Logger
+ log = LOG;
+ }
+ if (name != null) {
+ log.warn("Cannot sync FileDescriptor: " + name + ". Reason: " + e.getMessage(), e);
+ } else {
+ log.warn("Cannot sync FileDescriptor. Reason: " + e.getMessage(), e);
+ }
+ }
+ }
+
+ /**
+ * Closes the given writer, logging any closing exceptions to the given log.
+ * An associated FileOutputStream can optionally be forced to disk.
+ *
+ * @param writer the writer to close
+ * @param os an underlying FileOutputStream that will to be forced to disk according to the the force parameter
+ * @param name the name of the resource
+ * @param log the log to use when reporting warnings, will use this class's own {@link Logger} if <tt>log == null</tt>
+ * @param force forces the FileOutputStream to disk
+ */
+ public static void close(Writer writer, FileOutputStream os, String name, Logger log, boolean force) {
+ if (writer != null && force) {
+ // flush the writer prior to syncing the FD
+ try {
+ writer.flush();
+ } catch (Exception e) {
+ if (log == null) {
+ // then fallback to use the own Logger
+ log = LOG;
+ }
+ if (name != null) {
+ log.warn("Cannot flush Writer: " + name + ". Reason: " + e.getMessage(), e);
+ } else {
+ log.warn("Cannot flush Writer. Reason: " + e.getMessage(), e);
+ }
+ }
+ force(os, name, log);
+ }
+ close(writer, name, log);
+ }
+
+ /**
* Closes the given resource if it is available, logging any closing exceptions to the given log.
*
* @param closeable the object to close
@@ -255,6 +312,22 @@ public final class IOHelper {
}
/**
+ * Closes the given channel if it is available, logging any closing exceptions to the given log.
+ * The file's channel can optionally be forced to disk.
+ *
+ * @param channel the file channel
+ * @param name the name of the resource
+ * @param log the log to use when reporting warnings, will use this class's own {@link Logger} if <tt>log == null</tt>
+ * @param force forces the file channel to disk
+ */
+ public static void close(FileChannel channel, String name, Logger log, boolean force) {
+ if (force) {
+ force(channel, name, log);
+ }
+ close(channel, name, log);
+ }
+
+ /**
* Closes the given resource if it is available.
*
* @param closeable the object to close
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerNoForcedWritesTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerNoForcedWritesTest.java?rev=1461507&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerNoForcedWritesTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerNoForcedWritesTest.java Wed Mar 27 10:57:50 2013
@@ -0,0 +1,58 @@
+/**
+ * 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.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+
+public class FileProducerNoForcedWritesTest extends ContextTestSupport {
+
+ @Override
+ protected void setUp() throws Exception {
+ deleteDirectory("target/file");
+ super.setUp();
+ template.sendBodyAndHeader("file://target/file", "Hello World", Exchange.FILE_NAME, "hello.txt");
+ }
+
+ public void testNoForcedWrites() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedBodiesReceived("Hello World");
+
+ assertMockEndpointsSatisfied();
+
+ assertFileExists("target/file/output.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File("target/file/output.txt")));
+
+ assertFileExists("target/file/output2.txt");
+ assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, new File("target/file/output2.txt")));
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("file:target/file?noop=true").multicast().to("file:target/file/?fileName=output.txt&forceWrites=false",
+ "file:target/file/?fileName=output2.txt&charset=iso-8859-1&forceWrites=false").to("mock:result");
+ }
+ };
+ }
+}