diff --git a/core/src/main/java/cucumber/api/formatter/NiceAppendable.java b/core/src/main/java/cucumber/api/formatter/NiceAppendable.java index cca1bf179b..cf31ea5e13 100644 --- a/core/src/main/java/cucumber/api/formatter/NiceAppendable.java +++ b/core/src/main/java/cucumber/api/formatter/NiceAppendable.java @@ -65,7 +65,7 @@ public NiceAppendable println(CharSequence csq) { public void close() { try { tryFlush(); - if (out instanceof Closeable && out != System.out && out != System.err) { + if (out instanceof Closeable) { ((Closeable) out).close(); } } catch (IOException e) { diff --git a/core/src/main/java/cucumber/runtime/formatter/HTMLFormatter.java b/core/src/main/java/cucumber/runtime/formatter/HTMLFormatter.java index 1a010f0d84..8cefde21e9 100644 --- a/core/src/main/java/cucumber/runtime/formatter/HTMLFormatter.java +++ b/core/src/main/java/cucumber/runtime/formatter/HTMLFormatter.java @@ -37,6 +37,7 @@ import gherkin.pickles.PickleTable; import gherkin.pickles.PickleTag; +import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -119,11 +120,11 @@ public void receive(TestRunFinished event) { }; public HTMLFormatter(URL htmlReportDir) { - this.htmlReportDir = htmlReportDir; + this(htmlReportDir, createJsOut(htmlReportDir)); } - public HTMLFormatter(URL htmlReportDir, NiceAppendable jsOut) { - this(htmlReportDir); + HTMLFormatter(URL htmlReportDir, NiceAppendable jsOut) { + this.htmlReportDir = htmlReportDir; this.jsOut = jsOut; } @@ -144,7 +145,7 @@ private void handleTestSourceRead(TestSourceRead event) { private void handleTestCaseStarted(TestCaseStarted event) { if (firstFeature) { - jsOut().append("$(document).ready(function() {").append("var ") + jsOut.append("$(document).ready(function() {").append("var ") .append(JS_FORMATTER_VAR).append(" = new CucumberHTML.DOMFormatter($('.cucumber-report'));"); firstFeature = false; } @@ -188,7 +189,7 @@ private void handleEmbed(EmbedEvent event) { String extension = MIME_TYPES_EXTENSIONS.get(mimeType); if (extension != null) { StringBuilder fileName = new StringBuilder("embedded").append(embeddedIndex++).append(".").append(extension); - writeBytesAndClose(event.data, reportFileOutputStream(fileName.toString())); + writeBytesToURL(event.data, toUrl(fileName.toString())); jsFunctionCall("embedding", mimeType, fileName); } } @@ -200,10 +201,10 @@ private void handleWrite(WriteEvent event) { private void finishReport() { if (!firstFeature) { - jsOut().append("});"); + jsOut.append("});"); copyReportFiles(); } - jsOut().close(); + jsOut.close(); } private void handleStartOfFeature(TestCase testCase) { @@ -441,7 +442,7 @@ private Map createResultMap(Result result) { } private void jsFunctionCall(String functionName, Object... args) { - NiceAppendable out = jsOut().append(JS_FORMATTER_VAR + ".").append(functionName).append("("); + NiceAppendable out = jsOut.append(JS_FORMATTER_VAR + ".").append(functionName).append("("); boolean comma = false; for (Object arg : args) { if (comma) { @@ -463,12 +464,22 @@ private void copyReportFiles() { if (textAssetStream == null) { throw new CucumberException("Couldn't find " + textAsset + ". Is cucumber-html on your classpath? Make sure you have the right version."); } - String baseName = new File(textAsset).getName(); - writeStreamAndClose(textAssetStream, reportFileOutputStream(baseName)); + String fileName = new File(textAsset).getName(); + writeStreamToURL(textAssetStream, toUrl(fileName)); } } - private void writeStreamAndClose(InputStream in, OutputStream out) { + private URL toUrl(String fileName) { + try { + return new URL(htmlReportDir, fileName); + } catch (IOException e) { + throw new CucumberException(e); + } + } + + private static void writeStreamToURL(InputStream in, URL url) { + OutputStream out = createReportFileOutputStream(url); + byte[] buffer = new byte[16 * 1024]; try { int len = in.read(buffer); @@ -476,37 +487,46 @@ private void writeStreamAndClose(InputStream in, OutputStream out) { out.write(buffer, 0, len); len = in.read(buffer); } - out.close(); } catch (IOException e) { throw new CucumberException("Unable to write to report file item: ", e); + } finally { + closeQuietly(out); } } - private void writeBytesAndClose(byte[] buf, OutputStream out) { + private static void writeBytesToURL(byte[] buf, URL url) throws CucumberException { + OutputStream out = createReportFileOutputStream(url); try { out.write(buf); } catch (IOException e) { throw new CucumberException("Unable to write to report file item: ", e); + } finally { + closeQuietly(out); } } - private NiceAppendable jsOut() { - if (jsOut == null) { - try { - jsOut = new NiceAppendable(new OutputStreamWriter(reportFileOutputStream(JS_REPORT_FILENAME), "UTF-8")); - } catch (IOException e) { - throw new CucumberException(e); - } + private static NiceAppendable createJsOut(URL htmlReportDir) { + try { + return new NiceAppendable(new OutputStreamWriter(createReportFileOutputStream(new URL(htmlReportDir, JS_REPORT_FILENAME)), "UTF-8")); + } catch (IOException e) { + throw new CucumberException(e); } - return jsOut; } - private OutputStream reportFileOutputStream(String fileName) { + private static OutputStream createReportFileOutputStream(URL url) { try { - return new URLOutputStream(new URL(htmlReportDir, fileName)); + return new URLOutputStream(url); } catch (IOException e) { throw new CucumberException(e); } } + private static void closeQuietly(Closeable out) { + try { + out.close(); + } catch (IOException ignored) { + // go gentle into that good night + } + } + } \ No newline at end of file diff --git a/core/src/main/java/cucumber/runtime/formatter/JUnitFormatter.java b/core/src/main/java/cucumber/runtime/formatter/JUnitFormatter.java index 59258d2afd..c1a39bf0d0 100644 --- a/core/src/main/java/cucumber/runtime/formatter/JUnitFormatter.java +++ b/core/src/main/java/cucumber/runtime/formatter/JUnitFormatter.java @@ -28,7 +28,10 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; + +import java.io.Closeable; import java.io.IOException; +import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; @@ -151,6 +154,7 @@ private void finishReport() { StreamResult result = new StreamResult(out); DOMSource source = new DOMSource(doc); trans.transform(source, result); + closeQuietly(out); } catch (TransformerException e) { throw new CucumberException("Error while transforming.", e); } @@ -332,4 +336,11 @@ private Element createElement(Document doc, StringBuilder sb, String elementType } + private static void closeQuietly(Closeable out) { + try { + out.close(); + } catch (IOException ignored) { + // go gentle into that good night + } + } } diff --git a/core/src/main/java/cucumber/runtime/formatter/TestNGFormatter.java b/core/src/main/java/cucumber/runtime/formatter/TestNGFormatter.java index 6832d809d2..17d23e8478 100644 --- a/core/src/main/java/cucumber/runtime/formatter/TestNGFormatter.java +++ b/core/src/main/java/cucumber/runtime/formatter/TestNGFormatter.java @@ -28,6 +28,8 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; + +import java.io.Closeable; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; @@ -149,6 +151,7 @@ private void finishReport() { StreamResult streamResult = new StreamResult(writer); DOMSource domSource = new DOMSource(document); transformer.transform(domSource, streamResult); + closeQuietly(writer); } catch (TransformerException e) { throw new CucumberException("Error transforming report.", e); } @@ -301,4 +304,12 @@ private Element createException(Document doc, String clazz, String message, Stri return exceptionElement; } } + + private static void closeQuietly(Closeable out) { + try { + out.close(); + } catch (IOException ignored) { + // go gentle into that good night + } + } } diff --git a/testng/src/main/java/cucumber/api/testng/TestNGCucumberRunner.java b/testng/src/main/java/cucumber/api/testng/TestNGCucumberRunner.java index 75409695e5..0145984d6b 100644 --- a/testng/src/main/java/cucumber/api/testng/TestNGCucumberRunner.java +++ b/testng/src/main/java/cucumber/api/testng/TestNGCucumberRunner.java @@ -11,6 +11,7 @@ import cucumber.runtime.io.ResourceLoaderClassFinder; import cucumber.runtime.model.CucumberFeature; +import java.io.PrintStream; import java.util.ArrayList; import java.util.List; @@ -36,7 +37,12 @@ public TestNGCucumberRunner(Class clazz) { RuntimeOptionsFactory runtimeOptionsFactory = new RuntimeOptionsFactory(clazz); runtimeOptions = runtimeOptionsFactory.create(); - reporter = new TestNgReporter(System.out); + reporter = new TestNgReporter(new PrintStream(System.out) { + @Override + public void close() { + // We have no intention to close System.out + } + }); ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader); resultListener = new FeatureResultListener(runtimeOptions.isStrict()); runtime = new Runtime(resourceLoader, classFinder, classLoader, runtimeOptions);