# HG changeset patch # User chegar # Date 1294405698 0 # Node ID a23e3f47c5a86daa92c30d894edf14be77bc14c6 # Parent 0b2c3a61f004f9c36ab476ed5441f06f85aa90bf 7000511: PrintStream, PrintWriter, Formatter, Scanner leave files open when exception thrown Reviewed-by: alanb, mduigou diff -r 0b2c3a61f004 -r a23e3f47c5a8 jdk/src/share/classes/java/io/PrintStream.java --- a/jdk/src/share/classes/java/io/PrintStream.java Thu Jan 06 14:32:00 2011 -0800 +++ b/jdk/src/share/classes/java/io/PrintStream.java Fri Jan 07 13:08:18 2011 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,9 @@ import java.util.Formatter; import java.util.Locale; - +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; /** * A PrintStream adds functionality to another output stream, @@ -56,7 +58,7 @@ implements Appendable, Closeable { - private boolean autoFlush = false; + private final boolean autoFlush; private boolean trouble = false; private Formatter formatter; @@ -68,6 +70,60 @@ private OutputStreamWriter charOut; /** + * nonNull is explicitly delcared here so as not to create an extra + * dependency on java.util.Objects.nonNull. PrintStream is loaded + * early during system initialization. + */ + private static T nonNull(T obj, String message) { + if (obj == null) + throw new NullPointerException(message); + return obj; + } + + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws UnsupportedEncodingException if the charset is not supported + */ + private static Charset toCharset(String csn) + throws UnsupportedEncodingException + { + nonNull(csn, "charsetName"); + try { + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + // UnsupportedEncodingException should be thrown + throw new UnsupportedEncodingException(csn); + } + } + + /* Private constructors */ + private PrintStream(boolean autoFlush, OutputStream out) { + super(out); + this.autoFlush = autoFlush; + this.charOut = new OutputStreamWriter(this); + this.textOut = new BufferedWriter(charOut); + } + + private PrintStream(boolean autoFlush, OutputStream out, Charset charset) { + super(out); + this.autoFlush = autoFlush; + this.charOut = new OutputStreamWriter(this, charset); + this.textOut = new BufferedWriter(charOut); + } + + /* Variant of the private constructor so that the given charset name + * can be verified before evaluating the OutputStream argument. Used + * by constructors creating a FileOutputStream that also take a + * charset name. + */ + private PrintStream(boolean autoFlush, Charset charset, OutputStream out) + throws UnsupportedEncodingException + { + this(autoFlush, out, charset); + } + + /** * Creates a new print stream. This stream will not flush automatically. * * @param out The output stream to which values and objects will be @@ -79,27 +135,6 @@ this(out, false); } - /* Initialization is factored into a private constructor (note the swapped - * parameters so that this one isn't confused with the public one) and a - * separate init method so that the following two public constructors can - * share code. We use a separate init method so that the constructor that - * takes an encoding will throw an NPE for a null stream before it throws - * an UnsupportedEncodingException for an unsupported encoding. - */ - - private PrintStream(boolean autoFlush, OutputStream out) - { - super(out); - if (out == null) - throw new NullPointerException("Null output stream"); - this.autoFlush = autoFlush; - } - - private void init(OutputStreamWriter osw) { - this.charOut = osw; - this.textOut = new BufferedWriter(osw); - } - /** * Creates a new print stream. * @@ -113,8 +148,7 @@ * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean) */ public PrintStream(OutputStream out, boolean autoFlush) { - this(autoFlush, out); - init(new OutputStreamWriter(this)); + this(autoFlush, nonNull(out, "Null output stream")); } /** @@ -138,8 +172,9 @@ public PrintStream(OutputStream out, boolean autoFlush, String encoding) throws UnsupportedEncodingException { - this(autoFlush, out); - init(new OutputStreamWriter(this, encoding)); + this(autoFlush, + nonNull(out, "Null output stream"), + toCharset(encoding)); } /** @@ -171,7 +206,6 @@ */ public PrintStream(String fileName) throws FileNotFoundException { this(false, new FileOutputStream(fileName)); - init(new OutputStreamWriter(this)); } /** @@ -210,8 +244,8 @@ public PrintStream(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(false, new FileOutputStream(fileName)); - init(new OutputStreamWriter(this, csn)); + // ensure charset is checked before the file is opened + this(false, toCharset(csn), new FileOutputStream(fileName)); } /** @@ -243,7 +277,6 @@ */ public PrintStream(File file) throws FileNotFoundException { this(false, new FileOutputStream(file)); - init(new OutputStreamWriter(this)); } /** @@ -282,8 +315,8 @@ public PrintStream(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(false, new FileOutputStream(file)); - init(new OutputStreamWriter(this, csn)); + // ensure charset is checked before the file is opened + this(false, toCharset(csn), new FileOutputStream(file)); } /** Check to make sure that the stream has not been closed */ diff -r 0b2c3a61f004 -r a23e3f47c5a8 jdk/src/share/classes/java/io/PrintWriter.java --- a/jdk/src/share/classes/java/io/PrintWriter.java Thu Jan 06 14:32:00 2011 -0800 +++ b/jdk/src/share/classes/java/io/PrintWriter.java Fri Jan 07 13:08:18 2011 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,12 @@ package java.io; +import java.util.Objects; import java.util.Formatter; import java.util.Locale; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; /** * Prints formatted representations of objects to a text-output stream. This @@ -59,7 +63,7 @@ */ protected Writer out; - private boolean autoFlush = false; + private final boolean autoFlush; private boolean trouble = false; private Formatter formatter; private PrintStream psOut = null; @@ -68,7 +72,24 @@ * Line separator string. This is the value of the line.separator * property at the moment that the stream was created. */ - private String lineSeparator; + private final String lineSeparator; + + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws UnsupportedEncodingException if the charset is not supported + */ + private static Charset toCharset(String csn) + throws UnsupportedEncodingException + { + Objects.nonNull(csn, "charsetName"); + try { + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + // UnsupportedEncodingException should be thrown + throw new UnsupportedEncodingException(csn); + } + } /** * Creates a new PrintWriter, without automatic line flushing. @@ -164,6 +185,14 @@ false); } + /* Private constructor */ + private PrintWriter(Charset charset, File file) + throws FileNotFoundException + { + this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)), + false); + } + /** * Creates a new PrintWriter, without automatic line flushing, with the * specified file name and charset. This convenience constructor creates @@ -200,8 +229,7 @@ public PrintWriter(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)), - false); + this(toCharset(csn), new File(fileName)); } /** @@ -272,8 +300,7 @@ public PrintWriter(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)), - false); + this(toCharset(csn), file); } /** Checks to make sure that the stream has not been closed */ diff -r 0b2c3a61f004 -r a23e3f47c5a8 jdk/src/share/classes/java/util/Formatter.java --- a/jdk/src/share/classes/java/util/Formatter.java Thu Jan 06 14:32:00 2011 -0800 +++ b/jdk/src/share/classes/java/util/Formatter.java Fri Jan 07 13:08:18 2011 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,8 @@ import java.math.MathContext; import java.math.RoundingMode; import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; import java.text.DateFormatSymbols; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; @@ -1838,22 +1840,53 @@ */ public final class Formatter implements Closeable, Flushable { private Appendable a; - private Locale l; + private final Locale l; private IOException lastException; - private char zero = '0'; + private final char zero; private static double scaleUp; // 1 (sign) + 19 (max # sig digits) + 1 ('.') + 1 ('e') + 1 (sign) // + 3 (max # exp digits) + 4 (error) = 30 private static final int MAX_FD_CHARS = 30; - // Initialize internal data. - private void init(Appendable a, Locale l) { + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws UnsupportedEncodingException if the charset is not supported + */ + private static Charset toCharset(String csn) + throws UnsupportedEncodingException + { + Objects.nonNull(csn, "charsetName"); + try { + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + // UnsupportedEncodingException should be thrown + throw new UnsupportedEncodingException(csn); + } + } + + private static final Appendable nonNullAppendable(Appendable a) { + if (a == null) + return new StringBuilder(); + + return a; + } + + /* Private constructors */ + private Formatter(Locale l, Appendable a) { this.a = a; this.l = l; - setZero(); + this.zero = getZero(l); + } + + private Formatter(Charset charset, Locale l, File file) + throws FileNotFoundException + { + this(l, + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset))); } /** @@ -1867,7 +1900,7 @@ * virtual machine. */ public Formatter() { - init(new StringBuilder(), Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), new StringBuilder()); } /** @@ -1881,9 +1914,7 @@ * {@code null} then a {@link StringBuilder} will be created. */ public Formatter(Appendable a) { - if (a == null) - a = new StringBuilder(); - init(a, Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), nonNullAppendable(a)); } /** @@ -1900,7 +1931,7 @@ * is applied. */ public Formatter(Locale l) { - init(new StringBuilder(), l); + this(l, new StringBuilder()); } /** @@ -1916,9 +1947,7 @@ * is applied. */ public Formatter(Appendable a, Locale l) { - if (a == null) - a = new StringBuilder(); - init(a, l); + this(l, nonNullAppendable(a)); } /** @@ -1949,8 +1978,8 @@ * creating the file */ public Formatter(String fileName) throws FileNotFoundException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))), - Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName)))); } /** @@ -2025,8 +2054,7 @@ public Formatter(String fileName, String csn, Locale l) throws FileNotFoundException, UnsupportedEncodingException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)), - l); + this(toCharset(csn), l, new File(fileName)); } /** @@ -2057,8 +2085,8 @@ * creating the file */ public Formatter(File file) throws FileNotFoundException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))), - Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)))); } /** @@ -2133,8 +2161,7 @@ public Formatter(File file, String csn, Locale l) throws FileNotFoundException, UnsupportedEncodingException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)), - l); + this(toCharset(csn), l, file); } /** @@ -2151,9 +2178,8 @@ * The stream to use as the destination of this formatter. */ public Formatter(PrintStream ps) { - if (ps == null) - throw new NullPointerException(); - init((Appendable)ps, Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + (Appendable)Objects.nonNull(ps)); } /** @@ -2171,8 +2197,8 @@ * The output will be buffered. */ public Formatter(OutputStream os) { - init(new BufferedWriter(new OutputStreamWriter(os)), - Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + new BufferedWriter(new OutputStreamWriter(os))); } /** @@ -2222,13 +2248,15 @@ public Formatter(OutputStream os, String csn, Locale l) throws UnsupportedEncodingException { - init(new BufferedWriter(new OutputStreamWriter(os, csn)), l); + this(l, new BufferedWriter(new OutputStreamWriter(os, csn))); } - private void setZero() { + private static char getZero(Locale l) { if ((l != null) && !l.equals(Locale.US)) { DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l); - zero = dfs.getZeroDigit(); + return dfs.getZeroDigit(); + } else { + return '0'; } } diff -r 0b2c3a61f004 -r a23e3f47c5a8 jdk/src/share/classes/java/util/Scanner.java --- a/jdk/src/share/classes/java/util/Scanner.java Thu Jan 06 14:32:00 2011 -0800 +++ b/jdk/src/share/classes/java/util/Scanner.java Fri Jan 07 13:08:18 2011 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -571,10 +571,8 @@ * @return A scanner with the specified source and pattern */ private Scanner(Readable source, Pattern pattern) { - if (source == null) - throw new NullPointerException("source"); - if (pattern == null) - throw new NullPointerException("pattern"); + assert source != null : "source should not be null"; + assert pattern != null : "pattern should not be null"; this.source = source; delimPattern = pattern; buf = CharBuffer.allocate(BUFFER_SIZE); @@ -593,7 +591,7 @@ * interface */ public Scanner(Readable source) { - this(source, WHITESPACE_PATTERN); + this(Objects.nonNull(source, "source"), WHITESPACE_PATTERN); } /** @@ -620,23 +618,27 @@ * does not exist */ public Scanner(InputStream source, String charsetName) { - this(makeReadable(source, charsetName), WHITESPACE_PATTERN); + this(makeReadable(Objects.nonNull(source, "source"), toCharset(charsetName)), + WHITESPACE_PATTERN); } - private static Readable makeReadable(InputStream source, - String charsetName) - { - if (source == null) - throw new NullPointerException("source"); - InputStreamReader isr = null; + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws IllegalArgumentException if the charset is not supported + */ + private static Charset toCharset(String csn) { + Objects.nonNull(csn, "charsetName"); try { - isr = new InputStreamReader(source, charsetName); - } catch (UnsupportedEncodingException uee) { - IllegalArgumentException iae = new IllegalArgumentException(); - iae.initCause(uee); - throw iae; + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException e) { + // IllegalArgumentException should be thrown + throw new IllegalArgumentException(e); } - return isr; + } + + private static Readable makeReadable(InputStream source, Charset charset) { + return new InputStreamReader(source, charset); } /** @@ -648,9 +650,7 @@ * @param source A file to be scanned * @throws FileNotFoundException if source is not found */ - public Scanner(File source) - throws FileNotFoundException - { + public Scanner(File source) throws FileNotFoundException { this((ReadableByteChannel)(new FileInputStream(source).getChannel())); } @@ -669,8 +669,27 @@ public Scanner(File source, String charsetName) throws FileNotFoundException { - this((ReadableByteChannel)(new FileInputStream(source).getChannel()), - charsetName); + this(Objects.nonNull(source), toDecoder(charsetName)); + } + + private Scanner(File source, CharsetDecoder dec) + throws FileNotFoundException + { + this(makeReadable((ReadableByteChannel)(new FileInputStream(source).getChannel()), dec)); + } + + private static CharsetDecoder toDecoder(String charsetName) { + Objects.nonNull(charsetName, "charsetName"); + try { + return Charset.forName(charsetName).newDecoder(); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + throw new IllegalArgumentException(charsetName); + } + } + + private static Readable makeReadable(ReadableByteChannel source, + CharsetDecoder dec) { + return Channels.newReader(source, dec, -1); } /** @@ -708,10 +727,12 @@ * if the specified encoding is not found * @since 1.7 */ - public Scanner(FileRef source, String charsetName) - throws IOException - { - this(source.newInputStream(), charsetName); + public Scanner(FileRef source, String charsetName) throws IOException { + this(Objects.nonNull(source), toCharset(charsetName)); + } + + private Scanner(FileRef source, Charset charset) throws IOException { + this(makeReadable(source.newInputStream(), charset)); } /** @@ -733,16 +754,12 @@ * @param source A channel to scan */ public Scanner(ReadableByteChannel source) { - this(makeReadable(source), WHITESPACE_PATTERN); + this(makeReadable(Objects.nonNull(source, "source")), + WHITESPACE_PATTERN); } private static Readable makeReadable(ReadableByteChannel source) { - if (source == null) - throw new NullPointerException("source"); - String defaultCharsetName = - java.nio.charset.Charset.defaultCharset().name(); - return Channels.newReader(source, - java.nio.charset.Charset.defaultCharset().name()); + return makeReadable(source, Charset.defaultCharset().newDecoder()); } /** @@ -757,17 +774,8 @@ * does not exist */ public Scanner(ReadableByteChannel source, String charsetName) { - this(makeReadable(source, charsetName), WHITESPACE_PATTERN); - } - - private static Readable makeReadable(ReadableByteChannel source, - String charsetName) - { - if (source == null) - throw new NullPointerException("source"); - if (!Charset.isSupported(charsetName)) - throw new IllegalArgumentException(charsetName); - return Channels.newReader(source, charsetName); + this(makeReadable(Objects.nonNull(source, "source"), toDecoder(charsetName)), + WHITESPACE_PATTERN); } // Private primitives used to support scanning diff -r 0b2c3a61f004 -r a23e3f47c5a8 jdk/test/ProblemList.txt --- a/jdk/test/ProblemList.txt Thu Jan 06 14:32:00 2011 -0800 +++ b/jdk/test/ProblemList.txt Fri Jan 07 13:08:18 2011 +0000 @@ -718,9 +718,6 @@ # 11 separate stacktraces created... file reuse problem? java/util/zip/ZipFile/ReadLongZipFileName.java generic-all -# Failing on all -client 32bit platforms starting with b77? See 6908348. -java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java generic-all - # Assert error, failures, on Linux Fedora 9 -server # Windows samevm failure, assert error "Passed = 134, failed = 2" java/util/Arrays/ArrayObjectMethods.java generic-all @@ -737,9 +734,6 @@ # Fails on solaris-sparc -server (Set not equal to copy. 1) java/util/EnumSet/EnumSetBash.java solaris-sparc -# Failing to close an input stream? "foo", triggers samevm windows failures -java/util/Formatter/Constructors.java generic-all - # Need to be marked othervm, or changed to be samevm safe java/util/WeakHashMap/GCDuringIteration.java generic-all diff -r 0b2c3a61f004 -r a23e3f47c5a8 jdk/test/java/io/PrintStream/FailingConstructors.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/io/PrintStream/FailingConstructors.java Fri Jan 07 13:08:18 2011 +0000 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* PrintStream(File file, String csn) */ + try { + new PrintStream(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintStream(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* PrintStream(String fileName, String csn) */ + try { + new PrintStream(file.getName(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintStream(file.getName(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff -r 0b2c3a61f004 -r a23e3f47c5a8 jdk/test/java/io/PrintWriter/FailingConstructors.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/io/PrintWriter/FailingConstructors.java Fri Jan 07 13:08:18 2011 +0000 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* PrintWriter(File file, String csn) */ + try { + new PrintWriter(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintWriter(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* PrintWriter(String fileName, String csn) */ + try { + new PrintWriter(file.getName(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintWriter(file.getName(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff -r 0b2c3a61f004 -r a23e3f47c5a8 jdk/test/java/util/Formatter/Constructors.java --- a/jdk/test/java/util/Formatter/Constructors.java Thu Jan 06 14:32:00 2011 -0800 +++ b/jdk/test/java/util/Formatter/Constructors.java Fri Jan 07 13:08:18 2011 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 4981811 4984465 5064492 6240171 + * @bug 4981811 4984465 5064492 6240171 7000511 * @summary Unit test for all constructors introduced by the formatter feature */ @@ -85,10 +85,8 @@ } public static void main(String [] args) { - // Formatter() - try { - Formatter f = new Formatter(); + try (Formatter f = new Formatter()) { pass(); out(f, StringBuilder.class); locale(f); @@ -97,8 +95,7 @@ } // Formatter(Appendable a) - try { - Formatter f = new Formatter((Appendable) null); + try (Formatter f = new Formatter((Appendable) null)) { pass(); out(f, StringBuilder.class); locale(f); @@ -107,8 +104,7 @@ } // Formatter(Locale l) - try { - Formatter f = new Formatter((Locale) null); + try (Formatter f = new Formatter((Locale) null)) { pass(); out(f, StringBuilder.class); locale(f, null); @@ -117,8 +113,7 @@ } // Formatter(Appendable a, Locale l) - try { - Formatter f = new Formatter((Appendable) null, (Locale) null); + try (Formatter f = new Formatter((Appendable) null, (Locale) null)) { pass(); out(f, StringBuilder.class); locale(f, null); @@ -127,8 +122,7 @@ } // Formatter(String fileName) - try { - Formatter f = new Formatter("foo"); + try (Formatter f = new Formatter("foo")) { pass(); out(f, BufferedWriter.class); locale(f); @@ -137,7 +131,7 @@ } try { - Formatter f = new Formatter((String)null); + new Formatter((String)null); fail("new Formatter((String)null)"); } catch (NullPointerException x) { pass(); @@ -146,8 +140,7 @@ } // Formatter(String fileName, String csn) - try { - Formatter f = new Formatter("foo", "UTF-8"); + try (Formatter f = new Formatter("foo", "UTF-8")) { pass(); out(f, BufferedWriter.class); locale(f); @@ -167,15 +160,14 @@ try { new Formatter(".", "bar"); fail("new Formatter(\".\", \"bar\")"); - } catch (FileNotFoundException x) { + } catch (FileNotFoundException|UnsupportedEncodingException x) { pass(); } catch (Exception x) { fail("new Formatter(\".\", \"bar\")", x); } // Formatter(String fileName, String csn, Locale l) - try { - Formatter f = new Formatter("foo", "ISO-8859-1", Locale.GERMANY); + try (Formatter f = new Formatter("foo", "ISO-8859-1", Locale.GERMANY)) { pass(); out(f, BufferedWriter.class); locale(f, Locale.GERMANY); @@ -183,8 +175,7 @@ fail("new Formatter(\"foo\", \"ISO-8859-1\", Locale.GERMANY)", x); } - try { - Formatter f = new Formatter("foo", "ISO-8859-1", null); + try (Formatter f = new Formatter("foo", "ISO-8859-1", null)) { pass(); locale(f, null); out(f, BufferedWriter.class); @@ -193,8 +184,7 @@ } // Formatter(File) - try { - Formatter f = new Formatter(new File("foo")); + try (Formatter f = new Formatter(new File("foo"))) { pass(); locale(f); out(f, BufferedWriter.class); @@ -203,7 +193,7 @@ } try { - Formatter f = new Formatter((File)null); + new Formatter((File)null); fail("new Formatter((File)null)"); } catch (NullPointerException x) { pass(); @@ -231,8 +221,7 @@ fail("new Formatter((PrintStream) null)", x); } - try { - Formatter f = new Formatter(new PrintStream("foo")); + try (Formatter f = new Formatter(new PrintStream("foo"))) { pass(); locale(f); out(f, PrintStream.class); @@ -242,9 +231,8 @@ fail("new Formatter(new PrintStream(\"foo\")", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - Locale.JAPANESE); + try (Formatter f = new Formatter(new PrintStream("foo"), + Locale.JAPANESE)) { pass(); locale(f, Locale.JAPANESE); out(f, PrintStream.class); @@ -254,12 +242,11 @@ fail("new Formatter(new PrintStream(\"foo\")", x); } - try { + try (PrintStream ps = new PrintStream("foo")) { // The cast here is necessary to avoid an ambiguity error // between Formatter(Appendable a, Locale l) - // and Formatter(OutputStream os, String csn) - Formatter f = new Formatter(new PrintStream("foo"), - (String)null); + // and Formatter(OutputStream os, String csn) + new Formatter(ps, (String)null); fail("new Formatter(new PrintStream(\"foo\"), (String)null)"); } catch (FileNotFoundException x) { fail("new Formatter(new PrintStream(\"foo\"), (String)null)", x); @@ -271,12 +258,11 @@ fail("new Formatter(new PrintStream(\"foo\"), (String)null)", x); } - try { - // The cast here is necessary to avoid an ambiguity error - // between Formatter(Appendable a, Locale l) - // and Formatter(OutputStream os, String csn) - Formatter f = new Formatter(new PrintStream("foo"), - (Locale)null); + // The cast here is necessary to avoid an ambiguity error + // between Formatter(Appendable a, Locale l) + // and Formatter(OutputStream os, String csn) + try (Formatter f = new Formatter(new PrintStream("foo"), + (Locale)null)) { pass(); locale(f, null); out(f, PrintStream.class); @@ -286,9 +272,8 @@ fail("new Formatter(new PrintStream(\"foo\"), (Locale)null)", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - Locale.KOREAN); + try (Formatter f = new Formatter(new PrintStream("foo"), + Locale.KOREAN)) { pass(); locale(f, Locale.KOREAN); out(f, PrintStream.class); @@ -298,9 +283,8 @@ fail("new Formatter(new PrintStream(\"foo\"), Locale.KOREAN)", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - "UTF-16BE", null); + try (Formatter f = new Formatter(new PrintStream("foo"), + "UTF-16BE", null)) { pass(); locale(f, null); out(f, BufferedWriter.class); @@ -312,9 +296,8 @@ fail("new Formatter(new PrintStream(\"foo\"), \"UTF-16BE\", null"); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - "UTF-16BE", Locale.ITALIAN); + try (Formatter f = new Formatter(new PrintStream("foo"), + "UTF-16BE", Locale.ITALIAN)) { pass(); locale(f, Locale.ITALIAN); out(f, BufferedWriter.class); @@ -361,8 +344,7 @@ fail("new Formatter((OutputStream) null)", x); } - try { - Formatter f = new Formatter((OutputStream) new PrintStream("foo")); + try (Formatter f = new Formatter((OutputStream) new PrintStream("foo"))) { pass(); locale(f); out(f, BufferedWriter.class); @@ -380,8 +362,8 @@ fail("new Formatter((OutputStream) null, \"ISO-8859-1\")", x); } - try { - new Formatter((OutputStream) new PrintStream("foo"), null); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter((OutputStream) ps, null); fail("new Formatter((OutputStream) new PrintStream(\"foo\"), null"); } catch (NullPointerException x) { pass(); @@ -390,8 +372,8 @@ x); } - try { - new Formatter(new PrintStream("foo"), "bar"); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter(ps, "bar"); fail("new Formatter(new PrintStream(\"foo\"), \"bar\")"); } catch (UnsupportedEncodingException x) { pass(); @@ -399,8 +381,7 @@ fail("new Formatter(new PrintStream(\"foo\"), \"bar\")", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), "UTF-8"); + try (Formatter f = new Formatter(new PrintStream("foo"), "UTF-8")) { pass(); locale(f); out(f, BufferedWriter.class); @@ -419,8 +400,8 @@ x); } - try { - new Formatter(new PrintStream("foo"), null, Locale.UK); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter(ps, null, Locale.UK); fail("new Formatter(new PrintStream(\"foo\"), null, Locale.UK)"); } catch (NullPointerException x) { pass(); @@ -429,8 +410,8 @@ x); } - try { - new Formatter(new PrintStream("foo"), "bar", Locale.UK); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter(ps, "bar", Locale.UK); fail("new Formatter(new PrintStream(\"foo\"), \"bar\", Locale.UK)"); } catch (UnsupportedEncodingException x) { pass(); @@ -439,9 +420,7 @@ x); } - try { - Formatter f - = new Formatter(new PrintStream("foo"), "UTF-8", Locale.UK); + try (Formatter f = new Formatter(new PrintStream("foo"), "UTF-8", Locale.UK)) { pass(); out(f, BufferedWriter.class); locale(f, Locale.UK); @@ -451,8 +430,7 @@ } // PrintStream(String fileName) - try { - new PrintStream("foo"); + try (PrintStream ps = new PrintStream("foo")) { pass(); } catch (Exception x) { fail("new PrintStream(\"foo\")", x); @@ -469,8 +447,7 @@ } // PrintStream(File file) - try { - new PrintStream(new File("foo")); + try (PrintStream ps = new PrintStream(new File("foo"))) { pass(); } catch (Exception x) { fail("new PrintStream(new File(\"foo\"))", x); @@ -487,8 +464,7 @@ } // PrintWriter(String fileName) - try { - new PrintWriter("foo"); + try (PrintWriter pw = new PrintWriter("foo")) { pass(); } catch (Exception x) { fail("new PrintWriter(\"foo\")", x); @@ -505,8 +481,7 @@ } // PrintWriter(File file) - try { - new PrintWriter(new File("foo")); + try (PrintWriter pw = new PrintWriter(new File("foo"))) { pass(); } catch (Exception x) { fail("new PrintWriter(new File(\"foo\"))", x); diff -r 0b2c3a61f004 -r a23e3f47c5a8 jdk/test/java/util/Formatter/FailingConstructors.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/Formatter/FailingConstructors.java Fri Jan 07 13:08:18 2011 +0000 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Formatter; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* Formatter(File file, String csn) */ + try { + new Formatter(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new Formatter(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* Formatter(String fileName, String csn) */ + try { + new Formatter(file.getName(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new Formatter(file.getName(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff -r 0b2c3a61f004 -r a23e3f47c5a8 jdk/test/java/util/Scanner/FailingConstructors.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/Scanner/FailingConstructors.java Fri Jan 07 13:08:18 2011 +0000 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Scanner; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* Scanner(File source, String charsetName) */ + try { + new Scanner(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|IllegalArgumentException e) { + pass(); + } + + check(exists, file); + + try { + new Scanner(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* Scanner(FileRef source, String charsetName) */ + try { + new Scanner(file.toPath(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|IllegalArgumentException e) { + pass(); + } + + check(exists, file); + + try { + new Scanner(file.toPath(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +}