From 8aa307060da899fca5b537055c37e2b59f77e06d Mon Sep 17 00:00:00 2001 From: Derek Hulley Date: Mon, 24 Oct 2011 14:30:17 +0000 Subject: [PATCH] Fixed ALF-11014: Content output stream close errors are absorbed silently - Found while testing XAMcontentStore - Pulled stream copy code into AbstractContentWriter - OutputStream closure (write-side) exception is rethrown to allow full rollback, etc git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@31441 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repo/content/AbstractContentWriter.java | 56 +++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/source/java/org/alfresco/repo/content/AbstractContentWriter.java b/source/java/org/alfresco/repo/content/AbstractContentWriter.java index d1de7af0d6..c212e16b86 100644 --- a/source/java/org/alfresco/repo/content/AbstractContentWriter.java +++ b/source/java/org/alfresco/repo/content/AbstractContentWriter.java @@ -46,7 +46,6 @@ import org.alfresco.util.TempFileProvider; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.framework.ProxyFactory; -import org.springframework.util.FileCopyUtils; /** * Implements all the convenience methods of the interface. The only methods @@ -434,7 +433,7 @@ public abstract class AbstractContentWriter extends AbstractContentAccessor impl try { OutputStream os = getContentOutputStream(); - FileCopyUtils.copy(is, os); // both streams are closed + copyStreams(is, os); // both streams are closed // done } catch (IOException e) @@ -451,7 +450,7 @@ public abstract class AbstractContentWriter extends AbstractContentAccessor impl { OutputStream os = getContentOutputStream(); FileInputStream is = new FileInputStream(file); - FileCopyUtils.copy(is, os); // both streams are closed + copyStreams(is, os); // both streams are closed // done } catch (IOException e) @@ -463,6 +462,55 @@ public abstract class AbstractContentWriter extends AbstractContentAccessor impl } } + /** + * Copy of the the Spring FileCopyUtils, but does not silently absorb IOExceptions + * when the streams are closed. We require the stream write to happen successfully. + *

+ * Both streams are closed but any IOExceptions are thrown + */ + private final int copyStreams(InputStream in, OutputStream out) throws IOException + { + int byteCount = 0; + IOException error = null; + try + { + byte[] buffer = new byte[4096]; + int bytesRead = -1; + while ((bytesRead = in.read(buffer)) != -1) + { + out.write(buffer, 0, bytesRead); + byteCount += bytesRead; + } + out.flush(); + } + finally + { + try + { + in.close(); + } + catch (IOException e) + { + error = e; + logger.error("Failed to close output stream: " + this, e); + } + try + { + out.close(); + } + catch (IOException e) + { + error = e; + logger.error("Failed to close output stream: " + this, e); + } + } + if (error != null) + { + throw error; + } + return byteCount; + } + /** * Makes use of the encoding, if available, to convert the string to bytes. * @@ -490,7 +538,7 @@ public abstract class AbstractContentWriter extends AbstractContentAccessor impl // get the stream OutputStream os = getContentOutputStream(); ByteArrayInputStream is = new ByteArrayInputStream(bytes); - FileCopyUtils.copy(is, os); // both streams are closed + copyStreams(is, os); // both streams are closed // done } catch (IOException e)