Joe Qiang Luo created CAMEL-8032:
------------------------------------
Summary: FileUtil leaks FileInputStream when renameFile fails due
to permission issue
Key: CAMEL-8032
URL: https://issues.apache.org/jira/browse/CAMEL-8032
Project: Camel
Issue Type: Bug
Components: camel-core
Affects Versions: 2.12.3
Reporter: Joe Qiang Luo
I have a simple camel route:
{code}
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from
uri="file:C:/tmp/data/in?include=.*$&move=C:/tmp/data/done/${file:onlyname}-${exchangeId}"
/>
<setHeader headerName="CamelFileName">
<simple>${file:onlyname}-${exchangeId}</simple>
</setHeader>
<to uri="file:C:/tmp/data/out" />
</route>
</camelContext>
{code}
If the destination folder "C:/tmp/data/done/" for the move operation does not
allow writing, then the file dropped to the "C:/tmp/data/in/" folder will be
repeatedly polled, processed and rolled back due to "Access is denied"
exception.
Even if we fix the permission issue on the folder "C:/tmp/data/done/" to allow
writing, the problem still persists and above endless cycle continues. However
the reason for the issue will be a bit different now. It is caused by deletion
failure to the file from "C:/tmp/data/in/" folder after successful
FileUtil.renameFile() operation due to fact that something is still holding the
file handle.
The root cause is in the function FileUtil.copyFile():
{code}
public static void copyFile(File from, File to) throws IOException {
FileChannel in = new FileInputStream(from).getChannel();
FileChannel out = new FileOutputStream(to).getChannel();
try {
if (LOG.isTraceEnabled()) {
LOG.trace("Using FileChannel to copy from: " + in + " to: " +
out);
}
long size = in.size();
long position = 0;
while (position < size) {
position += in.transferTo(position, BUFFER_SIZE, out);
}
} finally {
IOHelper.close(in, from.getName(), LOG);
IOHelper.close(out, to.getName(), LOG);
}
}
{code}
If the destination folder "C:/tmp/data/done/" for move operation is not allowed
for writing, the creation of the FileOutputStream will throw an exception
straight away. However, because both FileInputStream and FileOutputStream are
created outside the try{}...finally{} block, the FileInputStream is never
closed. It still holds handle to the file and caused FileSystem unable to
delete it. Therefore caused the whole route to fail.
The solution is quite simple, we just need to create the Input/Output streams
inside try{}...finally{} loop to make sure that the Input/Output streams get
closed if something happens during creating of these objects.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)