Merge
authoramurillo
Wed, 29 Jul 2015 20:21:14 -0700
changeset 31913 03c74d3baafc
parent 31912 a0aefd43f3f2 (current diff)
parent 31903 752473818053 (diff)
child 31914 1b365849fcfa
Merge
--- a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java	Wed Jul 29 11:05:02 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java	Wed Jul 29 20:21:14 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, 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
@@ -40,8 +40,17 @@
 package java.util;
 
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnmappableCharacterException;
+import java.security.AccessController;
+import java.util.Locale;
+import sun.security.action.GetPropertyAction;
+import sun.util.PropertyResourceBundleCharset;
 import sun.util.ResourceBundleEnumeration;
 
 /**
@@ -108,11 +117,20 @@
  * <strong>Note:</strong> PropertyResourceBundle can be constructed either
  * from an InputStream or a Reader, which represents a property file.
  * Constructing a PropertyResourceBundle instance from an InputStream requires
- * that the input stream be encoded in ISO-8859-1.  In that case, characters
- * that cannot be represented in ISO-8859-1 encoding must be represented by Unicode Escapes
- * as defined in section 3.3 of
- * <cite>The Java&trade; Language Specification</cite>
+ * that the input stream be encoded in UTF-8. By default, if a
+ * {@link java.nio.charset.MalformedInputException} or an
+ * {@link java.nio.charset.UnmappableCharacterException} occurs on reading the
+ * input stream, then the PropertyResourceBundle instance resets to the state
+ * before the exception, re-reads the input stream in {@code ISO-8859-1}, and
+ * continues reading. If the system property
+ * {@code java.util.PropertyResourceBundle.encoding} is set to either
+ * "ISO-8859-1" or "UTF-8", the input stream is solely read in that encoding,
+ * and throws the exception if it encounters an invalid sequence.
+ * If "ISO-8859-1" is specified, characters that cannot be represented in
+ * ISO-8859-1 encoding must be represented by Unicode Escapes as defined in section
+ * 3.3 of <cite>The Java&trade; Language Specification</cite>
  * whereas the other constructor which takes a Reader does not have that limitation.
+ * Other encoding values are ignored for this system property.
  *
  * @see ResourceBundle
  * @see ListResourceBundle
@@ -120,10 +138,26 @@
  * @since 1.1
  */
 public class PropertyResourceBundle extends ResourceBundle {
+
+    // Check whether the strict encoding is specified.
+    // The possible encoding is either "ISO-8859-1" or "UTF-8".
+    private static final String encoding =
+        AccessController.doPrivileged(
+            new GetPropertyAction("java.util.PropertyResourceBundle.encoding", ""))
+        .toUpperCase(Locale.ROOT);
+
     /**
      * Creates a property resource bundle from an {@link java.io.InputStream
-     * InputStream}.  The property file read with this constructor
-     * must be encoded in ISO-8859-1.
+    * InputStream}. This constructor reads the property file in UTF-8 by default.
+    * If a {@link java.nio.charset.MalformedInputException} or an
+    * {@link java.nio.charset.UnmappableCharacterException} occurs on reading the
+    * input stream, then the PropertyResourceBundle instance resets to the state
+    * before the exception, re-reads the input stream in {@code ISO-8859-1} and
+    * continues reading. If the system property
+    * {@code java.util.PropertyResourceBundle.encoding} is set to either
+    * "ISO-8859-1" or "UTF-8", the input stream is solely read in that encoding,
+    * and throws the exception if it encounters an invalid sequence. Other
+    * encoding values are ignored for this system property.
      *
      * @param stream an InputStream that represents a property file
      *        to read from.
@@ -131,12 +165,19 @@
      * @throws NullPointerException if <code>stream</code> is null
      * @throws IllegalArgumentException if {@code stream} contains a
      *     malformed Unicode escape sequence.
+     * @throws MalformedInputException if the system property
+     *     {@code java.util.PropertyResourceBundle.encoding} is set to "UTF-8"
+     *     and {@code stream} contains an invalid UTF-8 byte sequence.
+     * @throws UnmappableCharacterException if the system property
+     *     {@code java.util.PropertyResourceBundle.encoding} is set to "UTF-8"
+     *     and {@code stream} contains an unmappable UTF-8 byte sequence.
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
     public PropertyResourceBundle (InputStream stream) throws IOException {
-        Properties properties = new Properties();
-        properties.load(stream);
-        lookup = new HashMap(properties);
+        this(new InputStreamReader(stream,
+            "ISO-8859-1".equals(encoding) ?
+                StandardCharsets.ISO_8859_1.newDecoder() :
+                new PropertyResourceBundleCharset("UTF-8".equals(encoding)).newDecoder()));
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/PropertyResourceBundleCharset.java	Wed Jul 29 20:21:14 2015 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.util;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import sun.util.logging.PlatformLogger;
+
+/**
+ * A Charset implementation for reading PropertyResourceBundle, in order
+ * for loading properties files. This first tries to load the properties
+ * file with UTF-8 encoding). If it fails, then load the file with ISO-8859-1
+ */
+public class PropertyResourceBundleCharset extends Charset {
+
+    private boolean strictUTF8 = false;
+
+    public PropertyResourceBundleCharset(boolean strictUTF8) {
+        this(PropertyResourceBundleCharset.class.getCanonicalName(), null);
+        this.strictUTF8 = strictUTF8;
+    }
+
+    public PropertyResourceBundleCharset(String canonicalName, String[] aliases) {
+        super(canonicalName, aliases);
+    }
+
+    @Override
+    public boolean contains(Charset cs) {
+        return false;
+    }
+
+    @Override
+    public CharsetDecoder newDecoder() {
+        return new PropertiesFileDecoder(this, 1.0f, 1.0f);
+    }
+
+    @Override
+    public CharsetEncoder newEncoder() {
+        throw new UnsupportedOperationException("Encoding is not supported");
+    }
+
+    private final class PropertiesFileDecoder extends CharsetDecoder {
+
+        private CharsetDecoder cdUTF_8 = StandardCharsets.UTF_8.newDecoder()
+                                .onMalformedInput(CodingErrorAction.REPORT)
+                                .onUnmappableCharacter(CodingErrorAction.REPORT);
+        private CharsetDecoder cdISO_8859_1 = null;
+
+        protected PropertiesFileDecoder(Charset cs,
+                float averageCharsPerByte, float maxCharsPerByte) {
+            super(cs, averageCharsPerByte, maxCharsPerByte);
+        }
+
+        protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+            if (Objects.nonNull(cdISO_8859_1)) {
+                return cdISO_8859_1.decode(in, out, false);
+            }
+            in.mark();
+            out.mark();
+
+            CoderResult cr = cdUTF_8.decode(in, out, false);
+            if (cr.isUnderflow() || cr.isOverflow() ||
+                PropertyResourceBundleCharset.this.strictUTF8) {
+                return cr;
+            }
+
+            in.reset();
+            out.reset();
+
+            PlatformLogger.getLogger(getClass().getCanonicalName()).info(
+                "Invalid or unmappable UTF-8 sequence detected. " +
+                "Switching encoding from UTF-8 to ISO-8859-1");
+            cdISO_8859_1 = StandardCharsets.ISO_8859_1.newDecoder();
+            return cdISO_8859_1.decode(in, out, false);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ResourceBundle/UTF8Properties/CodePointTest.java	Wed Jul 29 20:21:14 2015 -0700
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2015, 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 8027607
+ * @summary Test UTF-8 based properties files can be loaded successfully,
+ * @run main CodePointTest
+ * @run main/othervm -Djava.util.PropertyResourceBundle.encoding=ISO-8859-1 CodePointTest
+ * @run main/othervm -Djava.util.PropertyResourceBundle.encoding=UTF-8 CodePointTest
+ */
+
+import java.io.*;
+import java.nio.charset.*;
+import java.nio.file.*;
+import java.util.*;
+import static java.util.ResourceBundle.Control;
+import java.util.stream.*;
+
+/*
+ * Dumps every legal characters in ISO-8859-1/UTF-8 into
+ * a <CharSet>.properties file. Each entry has a form of
+ * "keyXXXX=c", where "XXXX" is a code point (variable length)
+ * and "c" is the character encoded in the passed character set.
+ * Then, load it with ResourceBundle.Control.newBundle() and compare both
+ * contents. This confirms the following two functions:
+ *  - For UTF-8.properties, UTF-8 code points are loaded correctly
+ *  - For ISO-8859-1.properties, UTF-8->ISO-8859-1 fallback works
+ *
+ * Does the same test with "java.util.PropertyResourceBundle.encoding"
+ * to "ISO-8859-1", and confirms only UTF-8 properties loading fails.
+ */
+public class CodePointTest {
+    static final Charset[] props = {StandardCharsets.ISO_8859_1,
+                                    StandardCharsets.UTF_8,
+                                    StandardCharsets.US_ASCII};
+    static final String encoding =
+        System.getProperty("java.util.PropertyResourceBundle.encoding", "");
+
+    public static void main(String[] args) {
+        for (Charset cs : props) {
+            try {
+                checkProps(cs,
+                    cs == StandardCharsets.UTF_8 &&
+                    encoding.equals("ISO-8859-1"));
+
+                if (cs == StandardCharsets.ISO_8859_1 &&
+                    encoding.equals("UTF-8")) {
+                    // should not happen
+                    throw new RuntimeException("Reading ISO-8859-1 properties in "+
+                        "strict UTF-8 encoding should throw an exception");
+                }
+            } catch (IOException e) {
+                if ((e instanceof MalformedInputException ||
+                     e instanceof UnmappableCharacterException) &&
+                    cs == StandardCharsets.ISO_8859_1 &&
+                    encoding.equals("UTF-8")) {
+                    // Expected exception is correctly detected.
+                } else {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+
+    static void checkProps(Charset cs, boolean shouldFail) throws IOException {
+        int start = Character.MIN_CODE_POINT;
+        int end= 0;
+
+        switch (cs.name()) {
+        case "ISO-8859-1":
+            end = 0xff;
+            break;
+        case "UTF-8":
+            end = Character.MAX_CODE_POINT;
+            break;
+        case "US-ASCII":
+            end = 0x7f;
+            break;
+        default:
+            assert false;
+        }
+
+        Properties p = new Properties();
+        String outputName = cs.name() + ".properties";
+
+        // Forget previous test artifacts
+        ResourceBundle.clearCache();
+
+        IntStream.range(start, end+1).forEach(c ->
+            {
+                if (Character.isDefined(c) &&
+                    (Character.isSupplementaryCodePoint(c) ||
+                     !Character.isSurrogate((char)c))) {
+                    p.setProperty("key"+Integer.toHexString(c),
+                        Character.isSupplementaryCodePoint(c) ?
+                            String.valueOf(Character.toChars(c)) :
+                            Character.toString((char)c));
+                }
+            }
+        );
+
+        try (BufferedWriter bw = Files.newBufferedWriter(
+                 FileSystems.getDefault().getPath(System.getProperty("test.classes", "."),
+                 outputName), cs)) {
+            p.store(bw, null);
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+
+        // try loading it
+        Control c = Control.getControl(Control.FORMAT_PROPERTIES);
+        ResourceBundle rb;
+        try {
+            rb = c.newBundle(cs.name(), Locale.ROOT, "java.properties",
+                        CodePointTest.class.getClassLoader(), false);
+        } catch (IllegalAccessException |
+                 InstantiationException ex) {
+            throw new RuntimeException(ex);
+        }
+        Properties result = new Properties();
+        rb.keySet().stream().forEach((key) -> {
+            result.setProperty(key, rb.getString(key));
+        });
+
+        if (!p.equals(result) && !shouldFail) {
+            System.out.println("Charset: "+cs);
+            rb.keySet().stream().sorted().forEach((key) -> {
+                if (!p.getProperty(key).equals(result.getProperty(key))) {
+                    System.out.println(key+": file: "+p.getProperty(key)+", RB: "+result.getProperty(key));
+                }
+            });
+            throw new RuntimeException("not equal!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ResourceBundle/UTF8Properties/IllegalSequenceTest.java	Wed Jul 29 20:21:14 2015 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, 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 8027607
+ * @summary Test whether illegal UTF-8 sequences are handled correctly.
+ * @run main/othervm -Djava.util.PropertyResourceBundle.encoding=UTF-8 IllegalSequenceTest
+ */
+
+import java.io.*;
+import java.nio.charset.*;
+import java.util.*;
+
+public class IllegalSequenceTest {
+    static final byte[][] illegalSequences = {
+        {(byte)0xc0, (byte)0xaf}, // non-shortest UTF-8
+        {(byte)0xc2, (byte)0xe0}, // consecutive leading bytes
+        {(byte)0xc2, (byte)0x80, (byte)0x80}, // two byte leading + 2 trailing
+        {(byte)0xe0, (byte)0x80}, // three byte leading + 1 trailing
+        {(byte)0xf4, (byte)0x90, (byte)0x80, (byte)0x80}, // 0x110000 (over U+10FFFF)
+    };
+
+    public static void main(String[] args) throws IOException {
+        for (byte[] illegalSec: illegalSequences) {
+            try (InputStream is = new ByteArrayInputStream(illegalSec)) {
+                ResourceBundle rb = new PropertyResourceBundle(is);
+                rb.getString("key");
+            } catch (MalformedInputException |
+                    UnmappableCharacterException e) {
+                // success
+                continue;
+            }
+            throw new RuntimeException("Excepted exception was not thrown.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Scanner/ScanTest.java	Wed Jul 29 20:21:14 2015 -0700
@@ -0,0 +1,1501 @@
+/*
+ * Copyright (c) 2003, 2015, 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 4313885 4926319 4927634 5032610 5032622 5049968 5059533 6223711 6277261 6269946 6288823
+ * @summary Basic tests of java.util.Scanner methods
+ * @key randomness
+ */
+
+import java.util.*;
+import java.text.*;
+import java.io.*;
+import java.nio.*;
+import java.util.regex.*;
+import java.math.*;
+
+public class ScanTest {
+
+    private static boolean failure = false;
+    private static int failCount = 0;
+    private static int NUM_SOURCE_TYPES = 2;
+
+    public static void main(String[] args) throws Exception {
+        Locale reservedLocale = Locale.getDefault();
+        String lang = reservedLocale.getLanguage();
+        try {
+            if (!"en".equals(lang) &&
+                !"zh".equals(lang) &&
+                !"ko".equals(lang) &&
+                !"ja".equals(lang)) {
+                //Before we have resource to improve the test to be ready for
+                //arbitrary locale, force the default locale to be "English"
+                //for now.
+                Locale.setDefault(Locale.ENGLISH);
+            }
+            skipTest();
+            findInLineTest();
+            findWithinHorizonTest();
+            findInEmptyLineTest();
+            removeTest();
+            fromFileTest();
+            ioExceptionTest();
+            matchTest();
+            delimiterTest();
+            useLocaleTest();
+            closeTest();
+            cacheTest();
+            cacheTest2();
+            nonASCIITest();
+            resetTest();
+
+            for (int j=0; j<NUM_SOURCE_TYPES; j++) {
+                hasNextTest(j);
+                nextTest(j);
+                hasNextPatternTest(j);
+                nextPatternTest(j);
+                booleanTest(j);
+                byteTest(j);
+                shortTest(j);
+                intTest(j);
+                longTest(j);
+                floatTest(j);
+                doubleTest(j);
+                integerPatternTest(j);
+                floatPatternTest(j);
+                bigIntegerPatternTest(j);
+                bigDecimalPatternTest(j);
+                hasNextLineTest(j);
+                nextLineTest(j);
+                singleDelimTest(j);
+            }
+
+            // Examples
+            //example1();
+            //example2();
+            //example3();
+
+            // Usage cases
+            useCase1();
+            useCase2();
+            useCase3();
+            useCase4();
+            useCase5();
+
+            if (failure)
+                throw new RuntimeException("Failure in the scanning tests.");
+            else
+                System.err.println("OKAY: All tests passed.");
+        } finally {
+            // restore the default locale
+            Locale.setDefault(reservedLocale);
+        }
+    }
+
+    public static void useCase1() throws Exception {
+        File f = new File(System.getProperty("test.src", "."), "input.txt");
+        Scanner sc = new Scanner(f);
+        sc.findWithinHorizon("usage case 1", 0);
+        String[] names = new String[4];
+        for (int i=0; i<4; i++) {
+            while(sc.hasNextFloat())
+                sc.nextFloat();
+            names[i] = sc.next();
+            sc.nextLine();
+        }
+        if (!names[0].equals("Frank"))
+            failCount++;
+        if (!names[1].equals("Joe"))
+            failCount++;
+        if (!names[2].equals("Mary"))
+            failCount++;
+        if (!names[3].equals("Michelle"))
+            failCount++;
+        sc.close();
+        report("Use case 1");
+    }
+
+    public static void useCase2() throws Exception {
+        File f = new File(System.getProperty("test.src", "."), "input.txt");
+        Scanner sc = new Scanner(f).useDelimiter("-");
+        String testDataTag = sc.findWithinHorizon("usage case 2\n", 0);
+        if (!testDataTag.equals("usage case 2\n"))
+            failCount++;
+        if (!sc.next().equals("cat"))
+            failCount++;
+        if (sc.nextInt() != 9)
+            failCount++;
+        if (!sc.next().equals("dog"))
+            failCount++;
+        if (sc.nextInt() != 6)
+            failCount++;
+        if (!sc.next().equals("pig"))
+            failCount++;
+        if (sc.nextInt() != 2)
+            failCount++;
+        if (!sc.next().equals(""))
+            failCount++;
+        if (sc.nextInt() != 5)
+            failCount++;
+        sc.close();
+        report("Use case 2");
+    }
+
+    public static void useCase3() throws Exception {
+        File f = new File(System.getProperty("test.src", "."), "input.txt");
+        Scanner sc = new Scanner(f);
+        String testDataTag = sc.findWithinHorizon("usage case 3\n", 0);
+        if (!testDataTag.equals("usage case 3\n"))
+            failCount++;
+        Pattern tagPattern = Pattern.compile("@[a-z]+");
+        Pattern endPattern = Pattern.compile("\\*\\/");
+        String tag;
+        String end = sc.findInLine(endPattern);
+
+        while (end == null) {
+            if ((tag = sc.findInLine(tagPattern)) != null) {
+                String text = sc.nextLine();
+                text = text.substring(0, text.length() - 1);
+                //System.out.println(text);
+            } else {
+                sc.nextLine();
+            }
+            end = sc.findInLine(endPattern);
+        }
+        report("Use case 3");
+    }
+
+    public static void useCase4() throws Exception {
+        File f = new File(System.getProperty("test.src", "."), "input.txt");
+        Scanner sc = new Scanner(f);
+        String testDataTag = sc.findWithinHorizon("usage case 4\n", 0);
+        if (!testDataTag.equals("usage case 4\n"))
+            failCount++;
+
+        // Read some text parts of four hrefs
+        String[] expected = { "Diffs", "Sdiffs", "Old", "New" };
+        for (int i=0; i<4; i++) {
+            sc.findWithinHorizon("<a href", 1000);
+            sc.useDelimiter("[<>\n]+");
+            sc.next();
+            String textOfRef = sc.next();
+            if (!textOfRef.equals(expected[i]))
+                failCount++;
+        }
+        // Read some html tags using < and > as delimiters
+        if (!sc.next().equals("/a"))
+            failCount++;
+        if (!sc.next().equals("b"))
+            failCount++;
+
+        // Scan some html tags using skip and next
+        Pattern nonTagStart = Pattern.compile("[^<]+");
+        Pattern tag = Pattern.compile("<[^>]+?>");
+        Pattern spotAfterTag = Pattern.compile("(?<=>)");
+        String[] expected2 = { "</b>", "<p>", "<ul>", "<li>" };
+        sc.useDelimiter(spotAfterTag);
+        int tagsFound = 0;
+        while(tagsFound < 4) {
+            if (!sc.hasNext(tag)) {
+                // skip text between tags
+                sc.skip(nonTagStart);
+            }
+            String tagContents = sc.next(tag);
+            if (!tagContents.equals(expected2[tagsFound]))
+                failCount++;
+            tagsFound++;
+        }
+
+        report("Use case 4");
+    }
+
+    public static void useCase5() throws Exception {
+        File f = new File(System.getProperty("test.src", "."), "input.txt");
+        Scanner sc = new Scanner(f);
+        String testDataTag = sc.findWithinHorizon("usage case 5\n", 0);
+        if (!testDataTag.equals("usage case 5\n"))
+            failCount++;
+
+        sc.findWithinHorizon("Share Definitions", 0);
+        sc.nextLine();
+        sc.next("\\[([a-z]+)\\]");
+        String shareName = sc.match().group(1);
+        if (!shareName.equals("homes"))
+            failCount++;
+
+        String[] keys = { "comment", "browseable", "writable", "valid users" };
+        String[] vals = { "Home Directories", "no", "yes", "%S" };
+        for (int i=0; i<4; i++) {
+            sc.useDelimiter("=");
+            String key = sc.next().trim();
+            if (!key.equals(keys[i]))
+                failCount++;
+            sc.skip("[ =]+");
+            sc.useDelimiter("\n");
+            String value = sc.next();
+            if (!value.equals(vals[i]))
+                failCount++;
+            sc.nextLine();
+        }
+
+        report("Use case 5");
+    }
+
+    public static void nonASCIITest() throws Exception {
+        String yourBasicTibetanNumberZero = "\u0f20";
+        String yourBasicTibetanFloatingNumber = "\u0f23.\u0f27";
+        String weirdMixtureOfTibetanAndASCII = "\u0f23.7";
+        String weirdMixtureOfASCIIAndTibetan = "3.\u0f27";
+        Scanner sc = new Scanner(yourBasicTibetanNumberZero);
+        int i = sc.nextInt();
+        if (i != 0)
+            failCount++;
+        sc = new Scanner(yourBasicTibetanFloatingNumber);
+        float f = sc.nextFloat();
+        if (f != Float.parseFloat("3.7"))
+            failCount++;
+        sc = new Scanner(weirdMixtureOfTibetanAndASCII);
+        f = sc.nextFloat();
+        if (f != Float.parseFloat("3.7"))
+            failCount++;
+        sc = new Scanner(weirdMixtureOfASCIIAndTibetan);
+        f = sc.nextFloat();
+        if (f != Float.parseFloat("3.7"))
+            failCount++;
+        report("Scanning non ASCII digits");
+    }
+
+    public static void findWithinHorizonTest() throws Exception {
+        // Test with a string source
+        Scanner sc = new Scanner("dog  cat     cat    dog     cat");
+        try {
+            sc.findWithinHorizon("dog", -1);
+            failCount++;
+        } catch (IllegalArgumentException iae) {
+            // Correct result
+        }
+        if (sc.findWithinHorizon("dog", 2) != null)
+            failCount++;
+        if (!sc.findWithinHorizon("dog", 3).equals("dog"))
+            failCount++;
+        if (sc.findWithinHorizon("cat", 4) != null)
+            failCount++;
+        if (!sc.findWithinHorizon("cat", 5).equals("cat"))
+            failCount++;
+         if (sc.findWithinHorizon("cat", 7) != null)
+            failCount++;
+        if (sc.findWithinHorizon("dog", 7) != null)
+            failCount++;
+        if (!sc.findWithinHorizon("cat", 0).equals("cat"))
+            failCount++;
+        if (!sc.findWithinHorizon("dog", 0).equals("dog"))
+            failCount++;
+        if (!sc.findWithinHorizon("cat", 0).equals("cat"))
+            failCount++;
+
+        // Test with a stream source
+        StutteringInputStream stutter = new StutteringInputStream();
+        for (int index=0; index<stutter.length(); index++) {
+            //System.out.println("index is now "+index);
+            sc = new Scanner(stutter);
+            String word = stutter.wordInIndex(index);
+            if (word != null) {
+                String result = sc.findWithinHorizon(word, index);
+                if ((result == null) || (!result.equals(word)))
+                    failCount++;
+            }
+            stutter.reset();
+            word = stutter.wordBeyondIndex(index);
+            sc = new Scanner(stutter);
+            String result = sc.findWithinHorizon(word, index);
+            if ((result != null) && (index > 0))
+                failCount++;
+            stutter.reset();
+        }
+
+        // We must loop to let StutteringInputStream do its magic
+        for (int j=0; j<10; j++) {
+            // An anchor at the end of stream should work
+            stutter.reset();
+            sc = new Scanner(stutter);
+            String result = sc.findWithinHorizon("phant$", 0);
+            if (!result.equals("phant"))
+                failCount++;
+            stutter.reset();
+            sc = new Scanner(stutter);
+            result = sc.findWithinHorizon("phant$", 54);
+            if (!result.equals("phant"))
+                failCount++;
+            // An anchor at the end of horizon should not
+            stutter.reset();
+            sc = new Scanner(stutter);
+            result = sc.findWithinHorizon("brummer$", 7);
+            if (result != null)
+                failCount++;
+            // An anchor at start should work
+            stutter.reset();
+            sc = new Scanner(stutter);
+            result = sc.findWithinHorizon("^brummer", 0);
+            if (!result.equals("brummer"))
+                failCount++;
+        }
+
+        report("Find to horizon test");
+    }
+
+    // StutteringInputStream returns 1 to 3 characters at a time
+    static class StutteringInputStream implements Readable {
+        StutteringInputStream() {
+            text = "brummer hisser tort zardzard rantrant caimagator phant";
+            datalen = 54;
+        }
+        StutteringInputStream(String text) {
+            this.text = text;
+            datalen = text.length();
+        }
+        Random generator = new Random();
+        String text;
+        int datalen;
+        int index = 0;
+        public int length() {
+            return datalen;
+        }
+        public void reset() {
+            index = 0;
+        }
+        public String wordInIndex(int index) {
+            if (index < 7)  return null;
+            if (index < 14) return "brummer";
+            if (index < 19) return "hisser";
+            if (index < 28) return "tort";
+            if (index < 37) return "zardzard";
+            if (index < 48) return "rantrant";
+            return "caimagator";
+        }
+        public String wordBeyondIndex(int index) {
+            if (index < 7)  return "brummer";
+            if (index < 14) return "hisser";
+            if (index < 19) return "tort";
+            if (index < 28) return "zardzard";
+            if (index < 37) return "rantrant";
+            if (index < 48) return "caimagator";
+            return "phantphant";
+        }
+        public int read(java.nio.CharBuffer target) throws IOException {
+            if (index > datalen-1)
+                return -1; // EOS
+            int len = target.remaining();
+            if (len > 4) // return 1 to 3 characters
+                len = generator.nextInt(3) + 1;
+            while ((index + len) > datalen)
+                len--;
+            for (int i=0; i<len; i++)
+                target.put(text.charAt(index++));
+            return len;
+        }
+    }
+
+    public static void hasNextLineTest(int sourceType) throws Exception {
+        Scanner sc = scannerFor("1\n2\n3 3\r\n4 4 4\r5", sourceType);
+        if (!sc.hasNextLine()) failCount++;
+        if (!sc.nextLine().equals("1")) failCount++;
+        if (!sc.hasNextLine()) failCount++;
+        if (sc.nextInt() != 2) failCount++;
+        if (!sc.hasNextLine()) failCount++;
+        if (!sc.nextLine().equals("")) failCount++;
+        if (!sc.hasNextLine()) failCount++;
+        if (sc.nextInt() != 3) failCount++;
+        if (!sc.hasNextLine()) failCount++;
+        if (!sc.nextLine().equals(" 3")) failCount++;
+        if (!sc.hasNextLine()) failCount++;
+        if (sc.nextInt() != 4) failCount++;
+        if (!sc.hasNextLine()) failCount++;
+        if (sc.nextInt() != 4) failCount++;
+        if (!sc.hasNextLine()) failCount++;
+        if (!sc.nextLine().equals(" 4")) failCount++;
+        if (!sc.hasNextLine()) failCount++;
+        if (!sc.nextLine().equals("5")) failCount++;
+        if (sc.hasNextLine()) failCount++;
+        sc = new Scanner("blah blah blah blah blah blah");
+        if (!sc.hasNextLine()) failCount++;
+        if (!sc.nextLine().equals("blah blah blah blah blah blah"))
+           failCount++;
+        if (sc.hasNextLine()) failCount++;
+
+        // Go through all the lines in a file
+        File f = new File(System.getProperty("test.src", "."), "input.txt");
+        sc = new Scanner(f);
+        String lastLine = "blah";
+        while(sc.hasNextLine())
+            lastLine = sc.nextLine();
+        if (!lastLine.equals("# Data for usage case 6")) failCount++;
+
+        report("Has next line test");
+    }
+
+    public static void nextLineTest(int sourceType) throws Exception {
+        Scanner sc = scannerFor("1\n2\n3 3\r\n4 4 4\r5", sourceType);
+        if (!sc.nextLine().equals("1"))
+            failCount++;
+        if (sc.nextInt() != 2)
+            failCount++;
+        if (!sc.nextLine().equals(""))
+           failCount++;
+        if (sc.nextInt() != 3)
+            failCount++;
+        if (!sc.nextLine().equals(" 3"))
+           failCount++;
+        if (sc.nextInt() != 4)
+            failCount++;
+        if (sc.nextInt() != 4)
+            failCount++;
+        if (!sc.nextLine().equals(" 4"))
+           failCount++;
+        if (!sc.nextLine().equals("5"))
+           failCount++;
+        sc = new Scanner("blah blah blah blah blah blah");
+        if (!sc.nextLine().equals("blah blah blah blah blah blah"))
+           failCount++;
+        report("Next line test");
+    }
+
+    public static void singleDelimTest(int sourceType) throws Exception {
+        Scanner sc = scannerFor("12 13  14   15    16     17      ",
+                                sourceType);
+        sc.useDelimiter(" ");
+        for (int i=0; i<6; i++) {
+            int j = sc.nextInt();
+            if (j != 12 + i)
+                failCount++;
+            for (int k=0; k<i; k++) {
+                String empty = sc.next();
+                if (!empty.equals(""))
+                    failCount++;
+            }
+        }
+        report("Single delim test");
+    }
+
+    /*
+     * The hasNextPattern caches a match of a pattern called the regular cache
+     * The hasNextType caches a match of that type called the type cache
+     * Any next must clear the caches whether it uses them or not, because
+     * it advances past a token thus invalidating any cached token; any
+     * hasNext must set a cache to what it finds.
+     */
+    public static void cacheTest() throws Exception {
+        // Test clearing of the type cache
+        Scanner scanner = new Scanner("777 dog");
+        scanner.hasNextInt();
+        scanner.findInLine("777");
+        try {
+            scanner.nextInt();
+            System.out.println("type cache not cleared by find");
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct
+        }
+
+        scanner = new Scanner("777 dog");
+        scanner.hasNextInt();
+        scanner.skip("777");
+        try {
+            scanner.nextInt();
+            System.out.println("type cache not cleared by skip");
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct
+        }
+
+        // Test clearing of the regular cache
+        scanner = new Scanner("777 dog");
+        scanner.hasNext("777");
+        scanner.findInLine("777");
+        try {
+            scanner.next("777");
+            System.out.println("regular cache not cleared by find");
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct
+        }
+
+        // Test two primitive next clearing of type cache
+        scanner = new Scanner("777 dog");
+        scanner.hasNextInt();
+        scanner.nextLong();
+        try {
+            scanner.nextInt();
+            System.out.println("type cache not cleared by primitive next");
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct
+        }
+
+        // Test using both of them, type first
+        scanner = new Scanner("777 dog");
+        scanner.hasNext("777");
+        scanner.nextInt();
+        try {
+            scanner.next("777");
+            System.out.println("regular cache not cleared by primitive next");
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct
+        }
+
+        // Test using both of them, regular first
+        scanner = new Scanner("777 dog");
+        scanner.hasNext("777");
+        scanner.hasNextInt();
+        scanner.next("777");
+        try {
+            scanner.nextInt();
+            System.out.println("type cache not cleared by regular next");
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct
+        }
+        report("Cache test");
+    }
+
+    /*
+     * The hasNext<IntegerType>(radix) method caches a matched integer type
+     * with specified radix for the next next<IntegerType>(radix) invoke.
+     * The cache value should not be used if the next<IntegerType>(radix)
+     * has different radix value with the last hasNext<IntegerType>(radix).
+     */
+    public static void cacheTest2() throws Exception {
+        // Test clearing of the type cache
+        Scanner scanner = new Scanner("10");
+        scanner.hasNextByte(16);
+        if (scanner.nextByte(10) != 10) {
+            System.out.println("wrong radix cache is used");
+            failCount++;
+        }
+        scanner = new Scanner("10");
+        scanner.hasNextShort(16);
+        if (scanner.nextShort(10) != 10) {
+            System.out.println("wrong radix cache is used");
+            failCount++;
+        }
+        scanner = new Scanner("10");
+        scanner.hasNextInt(16);
+        if (scanner.nextInt(10) != 10) {
+            System.out.println("wrong radix cache is used");
+            failCount++;
+        }
+        scanner = new Scanner("10");
+        scanner.hasNextLong(16);
+        if (scanner.nextLong(10) != 10) {
+            System.out.println("wrong radix cache is used");
+            failCount++;
+        }
+        scanner = new Scanner("10");
+        scanner.hasNextBigInteger(16);
+        if (scanner.nextBigInteger(10).intValue() != 10) {
+            System.out.println("wrong radix cache is used");
+            failCount++;
+        }
+        report("Cache test2");
+    }
+
+
+    public static void closeTest() throws Exception {
+        Scanner sc = new Scanner("testing");
+        sc.close();
+        sc.ioException();
+        sc.delimiter();
+        sc.useDelimiter("blah");
+        sc.useDelimiter(Pattern.compile("blah"));
+        for (int i=0; i<NUM_METHODS; i++) {
+            try {
+                methodCall(sc, i);
+                failCount++;
+            } catch (IllegalStateException ise) {
+                // Correct
+            }
+        }
+        report("Close test");
+    }
+
+    private static int NUM_METHODS = 23;
+
+    private static void methodCall(Scanner sc, int i) {
+        switch(i) {
+            case 0: sc.hasNext(); break;
+            case 1: sc.next(); break;
+            case 2: sc.hasNext(Pattern.compile("blah")); break;
+            case 3: sc.next(Pattern.compile("blah")); break;
+            case 4: sc.hasNextBoolean(); break;
+            case 5: sc.nextBoolean(); break;
+            case 6: sc.hasNextByte(); break;
+            case 7: sc.nextByte(); break;
+            case 8: sc.hasNextShort(); break;
+            case 9: sc.nextShort(); break;
+            case 10: sc.hasNextInt(); break;
+            case 11: sc.nextInt(); break;
+            case 12: sc.hasNextLong(); break;
+            case 13: sc.nextLong(); break;
+            case 14: sc.hasNextFloat(); break;
+            case 15: sc.nextFloat(); break;
+            case 16: sc.hasNextDouble(); break;
+            case 17: sc.nextDouble(); break;
+            case 18: sc.hasNextBigInteger(); break;
+            case 19: sc.nextBigInteger(); break;
+            case 20: sc.hasNextBigDecimal(); break;
+            case 21: sc.nextBigDecimal(); break;
+            case 22: sc.hasNextLine(); break;
+            default:
+                break;
+        }
+    }
+
+    public static void removeTest() throws Exception {
+        Scanner sc = new Scanner("testing");
+        try {
+            sc.remove();
+            failCount++;
+        } catch (UnsupportedOperationException uoe) {
+            // Correct result
+        }
+        report("Remove test");
+    }
+
+    public static void delimiterTest() throws Exception {
+        Scanner sc = new Scanner("blah");
+        Pattern test = sc.delimiter();
+        if (!test.toString().equals("\\p{javaWhitespace}+"))
+            failCount++;
+        sc.useDelimiter("a");
+        test = sc.delimiter();
+        if (!test.toString().equals("a"))
+            failCount++;
+        sc.useDelimiter(Pattern.compile("b"));
+        test = sc.delimiter();
+        if (!test.toString().equals("b"))
+            failCount++;
+        report("Delimiter test");
+    }
+
+    public static void ioExceptionTest() throws Exception {
+        Readable thrower = new ThrowingReadable();
+        Scanner sc = new Scanner(thrower);
+        try {
+            sc.nextInt();
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Correct result
+        }
+        Exception thrown = sc.ioException();
+        String detail = thrown.getMessage();
+        if (!detail.equals("ThrowingReadable always throws"))
+            failCount++;
+
+        report("IOException test");
+    }
+
+    public static void bigIntegerPatternTest(int sourceType) throws Exception {
+        Scanner sc = scannerFor("23 9223372036854775817", sourceType);
+        if (!sc.nextBigInteger().equals(BigInteger.valueOf(23)))
+            failCount++;
+        if (!sc.nextBigInteger().equals(new BigInteger(
+            "9223372036854775817", 10)))
+            failCount++;
+
+        // Test another radix
+        sc = new Scanner("4a4 4A4").useRadix(16);
+        if (!sc.nextBigInteger().equals(new BigInteger("4a4", 16)))
+            failCount++;
+        if (!sc.nextBigInteger().equals(new BigInteger("4A4", 16)))
+            failCount++;
+
+        // Test alternating radices
+        sc = new Scanner("12 4a4 14 4f4");
+        if (!sc.nextBigInteger(10).equals(new BigInteger("12", 10)))
+            failCount++;
+        if (!sc.nextBigInteger(16).equals(new BigInteger("4a4", 16)))
+            failCount++;
+        if (!sc.nextBigInteger(10).equals(new BigInteger("14", 10)))
+            failCount++;
+        if (!sc.nextBigInteger(16).equals(new BigInteger("4f4", 16)))
+            failCount++;
+
+        // Test use of a lot of radices
+        for (int i=2; i<17; i++) {
+            sc = new Scanner("1111");
+            if (!sc.nextBigInteger(i).equals(new BigInteger("1111", i)))
+                failCount++;
+        }
+
+        report("BigInteger pattern");
+    }
+
+    public static void bigDecimalPatternTest(int sourceType) throws Exception {
+        Scanner sc = scannerFor("23 45.99 -45,067.444 3.4e10", sourceType);
+        if (!sc.nextBigDecimal().equals(BigDecimal.valueOf(23)))
+            failCount++;
+        if (!sc.nextBigDecimal().equals(new BigDecimal("45.99")))
+            failCount++;
+        if (!sc.nextBigDecimal().equals(new BigDecimal("-45067.444")))
+            failCount++;
+        if (!sc.nextBigDecimal().equals(new BigDecimal("3.4e10")))
+            failCount++;
+        report("BigDecimal pattern");
+    }
+
+    public static void integerPatternTest(int sourceType) throws Exception {
+        String input =
+            "1 22 f FF Z -3 -44 123 1,200 -123 -3,400,000 5,40 ,500 ";
+        Scanner sc = scannerFor(input, sourceType);
+        integerPatternBody(sc);
+        CharBuffer cb = CharBuffer.wrap(input);
+        sc = new Scanner(cb);
+        integerPatternBody(sc);
+        report("Integer pattern");
+    }
+
+    public static void integerPatternBody(Scanner sc) throws Exception {
+        if (sc.nextInt() != 1)        failCount++;
+        if (sc.nextShort() != 22)     failCount++;
+        if (sc.nextShort(16) != 15)   failCount++;
+        if (sc.nextShort(16) != 255)  failCount++;
+        if (sc.nextShort(36) != 35)   failCount++;
+        if (!sc.hasNextInt())         failCount++;
+        if (sc.nextInt() != -3)       failCount++;
+        if (sc.nextInt() != -44)      failCount++;
+        if (sc.nextLong() != 123)     failCount++;
+        if (!sc.hasNextInt())         failCount++;
+        if (sc.nextInt() != 1200)     failCount++;
+        if (sc.nextInt() != -123)     failCount++;
+        if (sc.nextInt() != -3400000) failCount++;
+        try {
+            sc.nextInt();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct result
+        }
+        sc.next();
+        try {
+            sc.nextLong();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct result
+        }
+        sc.next();
+        try {
+            sc.next();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            failCount++;
+        } catch (NoSuchElementException nse) {
+            // Correct result
+        }
+    }
+
+    public static void floatPatternTest(int sourceType) throws Exception {
+        String input =
+            "090.090 1 22.0 -3 -44.05 +.123 -.1234 -3400000 56,566.6 " +
+            "Infinity +Infinity -Infinity NaN -NaN +NaN 5.4.0 5-.00 ++6.07";
+        Scanner sc = scannerFor(input, sourceType);
+        floatPatternBody(sc);
+        CharBuffer cb = CharBuffer.wrap(input);
+        sc = new Scanner(cb);
+        floatPatternBody(sc);
+        report("Float pattern");
+    }
+
+    public static void floatPatternBody(Scanner sc) throws Exception {
+        if (sc.nextFloat() != 090.090f)                   failCount++;
+        if (sc.nextFloat() != 1f)                         failCount++;
+        if (sc.nextFloat() != 22.0f)                      failCount++;
+        if (sc.nextDouble() != -3d)                       failCount++;
+        if (sc.nextDouble() != -44.05d)                   failCount++;
+        if (sc.nextFloat() != .123f)                      failCount++;
+        if (sc.nextFloat() != -.1234f)                    failCount++;
+        if (sc.nextDouble() != -3400000d)                 failCount++;
+        if (sc.nextDouble() != 56566.6d)                  failCount++;
+        if (sc.nextDouble() != Double.POSITIVE_INFINITY)  failCount++;
+        if (sc.nextDouble() != Double.POSITIVE_INFINITY)  failCount++;
+        if (sc.nextDouble() != Double.NEGATIVE_INFINITY)  failCount++;
+        if (!Double.valueOf(sc.nextDouble()).isNaN())     failCount++;
+        if (!Double.valueOf(sc.nextDouble()).isNaN())     failCount++;
+        if (!Double.valueOf(sc.nextDouble()).isNaN())     failCount++;
+        try {
+            sc.nextFloat();
+            failCount++;
+        } catch (NoSuchElementException nse) {
+            // Correct result
+        }
+        try {
+            sc.nextDouble();
+            failCount++;
+        } catch (NoSuchElementException nse) {
+            // Correct result
+        }
+        try {
+            sc.nextDouble();
+            failCount++;
+        } catch (NoSuchElementException nse) {
+            // Correct result
+        }
+    }
+
+    public static void fromFileTest() throws Exception {
+        File f = new File(System.getProperty("test.src", "."), "input.txt");
+        Scanner sc = new Scanner(f).useDelimiter("\n+");
+        String testDataTag = sc.findWithinHorizon("fromFileTest", 0);
+        if (!testDataTag.equals("fromFileTest"))
+            failCount++;
+
+        int count = 0;
+        while (sc.hasNextLong()) {
+            long blah = sc.nextLong();
+            count++;
+        }
+        if (count != 7)
+            failCount++;
+        sc.close();
+        report("From file");
+    }
+
+    private static void example1() throws Exception {
+        Scanner s = new Scanner("1 fish 2 fish red fish blue fish");
+        s.useDelimiter("\\s*fish\\s*");
+        List <String> results = new ArrayList<String>();
+        while(s.hasNext())
+            results.add(s.next());
+        System.out.println(results);
+    }
+
+    private static void example2() throws Exception {
+        Scanner s = new Scanner("1 fish 2 fish red fish blue fish");
+        s.useDelimiter("\\s*fish\\s*");
+        System.out.println(s.nextInt());
+        System.out.println(s.nextInt());
+        System.out.println(s.next());
+        System.out.println(s.next());
+    }
+
+    private static void example3() throws Exception {
+        Scanner s = new Scanner("1 fish 2 fish red fish blue fish");
+        s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
+        for (int i=1; i<=s.match().groupCount(); i++)
+            System.out.println(s.match().group(i));
+    }
+
+    private static void findInLineTest() throws Exception {
+        Scanner s = new Scanner("abc def ghi jkl mno");
+        Pattern letters = Pattern.compile("[a-z]+");
+        Pattern frogs = Pattern.compile("frogs");
+        String str = s.findInLine(letters);
+        if (!str.equals("abc"))
+            failCount++;
+        if (!s.hasNext(letters))
+            failCount++;
+        try {
+            str = s.findInLine(frogs);
+        } catch (NoSuchElementException nsee) {
+            // Correct
+        }
+        if (!s.hasNext())
+            failCount++;
+        if (!s.hasNext(letters))
+            failCount++;
+        str = s.findInLine(letters);
+        if (!str.equals("def"))
+            failCount++;
+
+        report("Find patterns");
+    }
+
+    private static void findInEmptyLineTest() throws Exception {
+        String eol = System.getProperty("line.separator");
+        Scanner s = new Scanner("line 1" + eol + "" + eol + "line 3" + eol);
+        int lineNo = 0;
+        while (s.hasNextLine()) {
+            lineNo++;
+            s.findInLine("3");
+            s.nextLine();
+        }
+        if (lineNo != 3)
+            failCount++;
+        report("findInEmptyLine test");
+    }
+
+    private static void matchTest() throws Exception {
+        Scanner s = new Scanner("1 fish 2 fish red fish blue fish");
+        s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
+
+        MatchResult result = s.match();
+        if (!result.group(1).equals("1"))
+            failCount++;
+        if (!result.group(2).equals("2"))
+            failCount++;
+        if (!result.group(3).equals("red"))
+            failCount++;
+        if (!result.group(4).equals("blue"))
+            failCount++;
+
+        report("Match patterns");
+    }
+
+    private static void skipTest() throws Exception {
+        Scanner s = new Scanner("abc def ghi jkl mno");
+        Pattern letters = Pattern.compile("[a-z]+");
+        Pattern spaceLetters = Pattern.compile(" [a-z]+");
+        Pattern frogs = Pattern.compile("frogs");
+        try {
+            s.skip(letters);
+        } catch (NoSuchElementException ime) {
+            failCount++;
+        }
+        String token = s.next(letters);
+        if (!token.equals("def")) {
+            System.out.println("expected def");
+            System.out.println("I found "+token);
+            failCount++;
+        }
+        try {
+            s.skip(letters);
+            failCount++;
+        } catch (NoSuchElementException ime) {
+            // Correct result
+        }
+        token = s.next(letters);
+        if (!token.equals("ghi")) {
+            System.out.println("expected ghi");
+            System.out.println("I found "+token);
+            failCount++;
+        }
+        try {
+            s.skip(letters);
+            failCount++;
+        } catch (NoSuchElementException ime) {
+            // Correct result because skip ignores delims
+        }
+        try {
+            s.skip(spaceLetters);
+        } catch (NoSuchElementException ime) {
+            failCount++;
+        }
+        token = s.next(letters);
+        if (!token.equals("mno")) {
+            System.out.println("expected mno");
+            System.out.println("I found "+token);
+            failCount++;
+        }
+        try {
+            s.skip(letters);
+            failCount++;
+        } catch (NoSuchElementException ime) {
+            // Correct result
+        }
+        report("Skip patterns");
+    }
+
+    private static void byteTest(int sourceType) throws Exception {
+        String input = " 3 0 00 b -B 012 44 -55 12 127 129 -131 dog 0x12";
+        Scanner s = scannerFor(input, sourceType);
+        if (!s.hasNextByte())          failCount++;
+        if (s.nextByte() != (byte)3)   failCount++;
+        if (!s.hasNextByte())          failCount++;
+        if (s.nextByte() != (byte)0)   failCount++;
+        if (!s.hasNextByte())          failCount++;
+        if (s.nextByte() != (byte)0)   failCount++;
+        if (!s.hasNextByte(16))        failCount++;
+        if (s.nextByte(16) != (byte)11)failCount++;
+        if (!s.hasNextByte(16))        failCount++;
+        if (s.nextByte(16) != (byte)-11) failCount++;
+        if (!s.hasNextByte())          failCount++;
+        if (s.nextByte() != (byte)12)  failCount++;
+        if (!s.hasNextByte())          failCount++;
+        if (s.nextByte() != (byte)44)  failCount++;
+        if (!s.hasNextByte())          failCount++;
+        if (s.nextByte() != (byte)-55) failCount++;
+        if (!s.hasNextByte())          failCount++;
+        if (s.nextByte() != (byte)12)  failCount++;
+        if (!s.hasNextByte())          failCount++;
+        if (s.nextByte() != (byte)127) failCount++;
+        if (s.hasNextByte())           failCount++;
+
+        try {
+            s.nextByte();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct result
+        }
+        if (s.hasNextByte())           failCount++;
+        if (s.nextInt() != 129)        failCount++;
+        if (s.hasNextByte())           failCount++;
+        try {
+            s.nextByte();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct result
+        }
+        if (s.nextInt() != -131)       failCount++;
+        if (s.hasNextByte())           failCount++;
+        try {
+            s.nextByte();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            // Correct result
+        }
+        s.next(Pattern.compile("\\w+"));
+        if (s.hasNextByte())
+            failCount++;
+        try {
+            s.nextByte();
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Correct result
+        }
+        s.next();
+        if (s.hasNextByte())
+            failCount++;
+        try {
+            byte bb = s.nextByte();
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Correct result
+        }
+        report("Scan bytes");
+    }
+
+    private static void shortTest(int sourceType) throws Exception {
+        String input = "  017 22 00E -34 44,333 -53999 0x19 dog";
+        Scanner s = scannerFor(input, sourceType);
+        if (!s.hasNextShort())             failCount++;
+        if (s.nextShort() != (short)17)   failCount++;
+        if (!s.hasNextShort())            failCount++;
+        if (s.nextShort() != (short)22)   failCount++;
+        if (!s.hasNextShort(16))          failCount++;
+        if (s.nextShort(16) != (short)14) failCount++;
+        if (!s.hasNextShort())            failCount++;
+        if (s.nextShort() != (short)-34)  failCount++;
+        for (int i=0; i<4; i++) {
+            if (s.hasNextShort())
+                failCount++;
+            try {
+                s.nextShort();
+                failCount++;
+            } catch (InputMismatchException ime) {
+                // Correct result
+            }
+            s.next();
+        }
+        try {
+            s.next();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            failCount++;
+        } catch (NoSuchElementException nse) {
+            // Correct result
+        }
+        report("Scan shorts");
+    }
+
+    private static void intTest(int sourceType) throws Exception {
+        Scanner s = scannerFor(
+            "22 022 C -34 0x80000000 -2147483649 dog ", sourceType);
+        if (!s.hasNextInt())      failCount++;
+        if (s.nextInt() != 22)    failCount++;
+        if (!s.hasNextInt())      failCount++;
+        if (s.nextInt() != 22)    failCount++;
+        if (!s.hasNextInt(16))    failCount++;
+        if (s.nextInt(16) != 12)  failCount++;
+        if (!s.hasNextInt())      failCount++;
+        if (s.nextInt() != -34)   failCount++;
+        for (int i=0; i<3; i++) {
+            if (s.hasNextInt())
+                failCount++;
+            try {
+                s.nextInt();
+                failCount++;
+            } catch (InputMismatchException ime) {
+                // Correct result
+            }
+            s.next();
+        }
+        try {
+            s.next();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            failCount++;
+        } catch (NoSuchElementException nse) {
+            // Correct result
+        }
+        report("Scan ints");
+    }
+
+    private static void longTest(int sourceType) throws Exception {
+        Scanner s = scannerFor(
+        "022 9223372036854775807 0x8000000000000000 9223372036854775808 dog ",
+              sourceType);
+        if (!s.hasNextLong())                        failCount++;
+        if (s.nextLong() != (long)22)                failCount++;
+        if (!s.hasNextLong())                        failCount++;
+        if (s.nextLong() != 9223372036854775807L)    failCount++;
+        for (int i=0; i<3; i++) {
+            if (s.hasNextLong())
+                failCount++;
+            try {
+                s.nextLong();
+                failCount++;
+            } catch (InputMismatchException ime) {
+                // Correct result
+            }
+            s.next();
+        }
+        try {
+            s.next();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            failCount++;
+        } catch (NoSuchElementException nse) {
+            // Correct result
+        }
+        report("Scan longs");
+    }
+
+    private static void floatTest(int sourceType) throws Exception {
+        Scanner s = scannerFor(
+            "0 0. 0.0 2 2. 2.0 2.3 -2 -2.0 -2.3 -. 2-. 2..3", sourceType);
+        if (!s.hasNextFloat())      failCount++;
+        if (s.nextFloat() != 0f)    failCount++;
+        if (!s.hasNextFloat())      failCount++;
+        if (s.nextFloat() != 0f)    failCount++;
+        if (!s.hasNextFloat())      failCount++;
+        if (s.nextFloat() != 0f)    failCount++;
+        if (!s.hasNextFloat())      failCount++;
+        if (s.nextFloat() != 2f)    failCount++;
+        if (!s.hasNextFloat())      failCount++;
+        if (s.nextFloat() != 2f)    failCount++;
+        if (!s.hasNextFloat())      failCount++;
+        if (s.nextFloat() != 2f)    failCount++;
+        if (!s.hasNextFloat())      failCount++;
+        if (s.nextFloat() != 2.3f)  failCount++;
+        if (!s.hasNextFloat())      failCount++;
+        if (s.nextFloat() != -2f)   failCount++;
+        if (!s.hasNextFloat())      failCount++;
+        if (s.nextFloat() != -2f)   failCount++;
+        if (!s.hasNextFloat())      failCount++;
+        if (s.nextFloat() != -2.3f) failCount++;
+        for (int i=0; i<3; i++) {
+            if (s.hasNextLong())
+                failCount++;
+            try {
+                s.nextFloat();
+                failCount++;
+            } catch (InputMismatchException ime) {
+                // Correct result
+            }
+            s.next();
+        }
+        try {
+            s.next();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            failCount++;
+        } catch (NoSuchElementException nse) {
+            // Correct result
+        }
+        report("Scan floats");
+    }
+
+    private static void doubleTest(int sourceType) throws Exception {
+        Scanner s = scannerFor(
+            "0 0. 0.0 2 2. 2.0 2.3 -2 -2.0 -2.3 -. 2-. 2..3", sourceType);
+        if (!s.hasNextDouble())             failCount++;
+        if (s.nextDouble() != 0d)           failCount++;
+        if (!s.hasNextDouble())             failCount++;
+        if (s.nextDouble() != 0d)           failCount++;
+        if (!s.hasNextDouble())             failCount++;
+        if (s.nextDouble() != 0d)           failCount++;
+        if (!s.hasNextDouble())             failCount++;
+        if (s.nextDouble() != 2d)           failCount++;
+        if (!s.hasNextDouble())             failCount++;
+        if (s.nextDouble() != 2d)           failCount++;
+        if (!s.hasNextDouble())             failCount++;
+        if (s.nextDouble() != 2d)           failCount++;
+        if (!s.hasNextDouble())             failCount++;
+        if (s.nextDouble() != 2.3d)         failCount++;
+        if (!s.hasNextDouble())             failCount++;
+        if (s.nextDouble() != -2d)          failCount++;
+        if (!s.hasNextDouble())             failCount++;
+        if (s.nextDouble() != -2d)          failCount++;
+        if (!s.hasNextDouble())             failCount++;
+        if (s.nextDouble() != -2.3d)        failCount++;
+        for (int i=0; i<3; i++) {
+            if (s.hasNextLong())
+                failCount++;
+            try {
+                s.nextDouble();
+                failCount++;
+            } catch (InputMismatchException ime) {
+                // Correct result
+            }
+            s.next();
+        }
+        try {
+            s.next();
+            failCount++;
+        } catch (InputMismatchException ime) {
+            failCount++;
+        } catch (NoSuchElementException nse) {
+            // Correct result
+        }
+        report("Scan doubles");
+    }
+
+    private static void booleanTest(int sourceType) throws Exception {
+        Scanner s = scannerFor(
+            " true false\t \r\n true FaLse \n  True Tru", sourceType);
+        if (!s.nextBoolean())     failCount++;
+        if (!s.hasNextBoolean())  failCount++;
+        if (s.nextBoolean())      failCount++;
+        if (!s.nextBoolean())     failCount++;
+        if (s.nextBoolean())      failCount++;
+        if (!s.nextBoolean())     failCount++;
+        if (s.hasNextBoolean())   failCount++;
+        try {
+            s.nextBoolean();
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Expected result
+        }
+        report("Scan booleans");
+    }
+
+    private static void hasNextTest(int sourceType) throws Exception {
+        Scanner s = scannerFor(
+            " blah blech\t blather  alongblatherindeed", sourceType);
+        if (!s.hasNext())            failCount++;
+        if (!s.hasNext())            failCount++;
+        String result = s.next();
+        if (!result.equals("blah"))  failCount++;
+        if (!s.hasNext())            failCount++;
+        if (!s.hasNext())            failCount++;
+        result = s.next();
+        if (!result.equals("blech")) failCount++;
+        if (!s.hasNext())            failCount++;
+        result = s.next();
+        if (!result.equals("blather")) failCount++;
+        if (!s.hasNext())              failCount++;
+        if (!s.hasNext())              failCount++;
+        result = s.next();
+        if (!result.equals("alongblatherindeed")) failCount++;
+        if (s.hasNext())                          failCount++;
+        try {
+            result = s.next();
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Correct result
+        }
+        report("Has next test");
+    }
+
+    private static void nextTest(int sourceType) throws Exception {
+        Scanner s = scannerFor(
+            " blah blech\t blather  alongblatherindeed", sourceType);
+        String result = (String)s.next();
+        if (!result.equals("blah"))    failCount++;
+        result = (String)s.next();
+        if (!result.equals("blech"))   failCount++;
+        result = (String)s.next();
+        if (!result.equals("blather")) failCount++;
+        result = (String)s.next();
+        if (!result.equals("alongblatherindeed"))
+            failCount++;
+        try {
+            result = (String)s.next();
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Correct result
+        }
+        report("Next test");
+    }
+
+    private static void hasNextPatternTest(int sourceType) throws Exception {
+        Scanner s = scannerFor(
+            " blah blech\t blather  alongblatherindeed", sourceType);
+        Pattern p1 = Pattern.compile("\\w+");
+        Pattern p2 = Pattern.compile("blech");
+        if (!s.hasNext(p1))    failCount++;
+        if (!s.hasNext(p1))    failCount++;
+        if (s.hasNext(p2))     failCount++;
+        String result = (String)s.next();
+        if (!result.equals("blah"))  failCount++;
+        if (!s.hasNext(p1))          failCount++;
+        if (!s.hasNext(p2))          failCount++;
+        result = (String)s.next();
+        if (!result.equals("blech")) failCount++;
+        if (!s.hasNext(p1))          failCount++;
+        if (s.hasNext(p2))           failCount++;
+        result = (String)s.next();
+        if (!result.equals("blather")) failCount++;
+        if (!s.hasNext(p1))            failCount++;
+        if (s.hasNext(p2))             failCount++;
+        result = (String)s.next();
+        if (!result.equals("alongblatherindeed")) failCount++;
+        if (s.hasNext(p1))  failCount++;
+        if (s.hasNext(p2))  failCount++;
+        report("Has Next Pattern test");
+    }
+
+    private static void nextPatternTest(int sourceType) throws Exception {
+        Scanner s = scannerFor(
+            " blah blech\t blather  alongblatherindeed", sourceType);
+        Pattern p1 = Pattern.compile("blah");
+        Pattern p2 = Pattern.compile("blech");
+        Pattern p3 = Pattern.compile("blather");
+        Pattern p4 = Pattern.compile("alongblatherindeed");
+        String result = null;
+        try {
+            result = (String)s.next(p2);
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Correct result
+        }
+        result = (String)s.next(p1);
+        if (!result.equals("blah"))
+            failCount++;
+        try {
+            result = (String)s.next(p1);
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Correct result
+        }
+        result = (String)s.next(p2);
+        if (!result.equals("blech"))
+            failCount++;
+        try {
+            result = (String)s.next(p4);
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Correct result
+        }
+        result = (String)s.next(p3);
+        if (!result.equals("blather"))
+            failCount++;
+        try {
+            result = (String)s.next(p3);
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Correct result
+        }
+        result = (String)s.next(p4);
+        if (!result.equals("alongblatherindeed"))
+            failCount++;
+        try {
+            result = (String)s.next();
+            failCount++;
+        } catch (NoSuchElementException nsee) {
+            // Correct result
+        }
+        report("Next pattern test");
+    }
+
+    private static void useLocaleTest() throws Exception {
+        Scanner s = new Scanner("334.65").useLocale(Locale.ENGLISH);
+        if (!s.hasNextFloat())           failCount++;
+        if (s.nextFloat() != 334.65f)    failCount++;
+
+        s = new Scanner("334,65").useLocale(Locale.FRENCH);
+        if (!s.hasNextFloat())           failCount++;
+        if (s.nextFloat() != 334.65f)    failCount++;
+
+        s = new Scanner("4.334,65").useLocale(Locale.GERMAN);
+        if (!s.hasNextFloat())           failCount++;
+        if (s.nextFloat() != 4334.65f)    failCount++;
+
+        // Test case reported from India
+        try {
+            String Message = "123978.90 $";
+            Locale locale = new Locale("hi","IN");
+            NumberFormat form = NumberFormat.getInstance(locale);
+            double myNumber = 1902.09;
+            Scanner scanner = new Scanner(form.format(myNumber).toString());
+            scanner.useLocale(locale);
+            double d = scanner.nextDouble();
+        } catch (InputMismatchException ime) {
+            failCount++;
+        }
+        report("Use locale test");
+    }
+
+    public static void resetTest() throws Exception {
+        Scanner sc = new Scanner("");
+        int radix = sc.radix();
+        Locale locale = sc.locale();
+        Pattern delimiter = sc.delimiter();
+        Pattern a = Pattern.compile("A");
+        sc.useDelimiter(a);
+        Locale dummy = new Locale("en", "US", "dummy");
+        sc.useLocale(dummy);
+        sc.useRadix(16);
+        if (sc.radix() != 16 ||
+            !sc.locale().equals(dummy) ||
+            !sc.delimiter().pattern().equals(a.pattern())) {
+            failCount++;
+        } else {
+            sc.reset();
+            if (sc.radix() != radix ||
+                !sc.locale().equals(locale) ||
+                !sc.delimiter().pattern().equals(delimiter.pattern())) {
+                failCount++;
+            }
+        }
+        sc.close();
+        report("Reset test");
+    }
+
+    private static void report(String testName) {
+        int spacesToAdd = 30 - testName.length();
+        StringBuffer paddedNameBuffer = new StringBuffer(testName);
+        for (int i=0; i<spacesToAdd; i++)
+            paddedNameBuffer.append(" ");
+        String paddedName = paddedNameBuffer.toString();
+        System.err.println(paddedName + ": " +
+                           (failCount==0 ? "Passed":"Failed("+failCount+")"));
+        if (failCount > 0)
+            failure = true;
+        failCount = 0;
+    }
+
+    static Scanner scannerFor(String input, int sourceType) {
+        if (sourceType == 1)
+            return new Scanner(input);
+        else
+            return new Scanner(new StutteringInputStream(input));
+    }
+
+    static class ThrowingReadable implements Readable {
+        ThrowingReadable() {
+        }
+        public int read(java.nio.CharBuffer cb) throws IOException {
+            throw new IOException("ThrowingReadable always throws");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Scanner/input.txt	Wed Jul 29 20:21:14 2015 -0700
@@ -0,0 +1,438 @@
+# Data for fromFileTest
+14343441
+24134342
+34324233
+43234234
+53423425
+63424326
+74324337
+
+
+# Data for usage case 1
+23.4 Frank 34.8 -9.0
+2.333 6.75 Joe -2
+3.3 -888.8 -16.00 Mary
+Michelle -5 -5.5 -5.555
+
+
+# Data for usage case 2
+cat-9-dog-6-pig-2--5-
+
+
+# Data for usage case 3
+    /**
+     * Returns the next string in the input that matches the specified pattern. 
+     * This method may block while waiting for input 
+     * to scan, even if a previous invocation of {@link #hasNext(Pattern)} 
+     * returned <code>true</code>. If the match is successful, the scanner 
+     * advances past the input that matched the pattern. 
+     *
+     * @param pattern the pattern to scan for
+     * @return the next token
+     * @throws NoSuchElementException if no more tokens are available
+     * @throws IllegalStateException if this scanner is closed
+     */
+
+
+# Data for usage case 4
+<html>
+<body bgcolor="#EEEEEE">
+<title>Source Directory</title>
+<center><h1>tiger</h1></center>
+<p>
+Parent workspace is /java/jdk/1.5/ws/integration/TL/j2se <br>
+Child  workspace is /export/tiger <br>
+<hr>
+<code>
+<p>
+<a href=make/java/java/mapfile-vers.diff.html>Diffs</a>
+<a href=make/java/java/mapfile-vers.sdiff.html>Sdiffs</a>
+<a href=make/java/java/mapfile-vers-.html>Old</a>
+<a href=make/java/java/mapfile-vers.html>New</a>
+<b>make/java/java/mapfile-vers</b><p>
+<ul> 
+<li><a href=http://example.com/cgi-bin/bugtraq_showbug?bugid=4904881>4904881</a>: JVM crash during java.io.File.deleteOnExit()<br>
+</ul>
+<p>
+<a href=src/share/classes/java/lang/Shutdown.java.diff.html>Diffs</a>
+<a href=src/share/classes/java/lang/Shutdown.java.sdiff.html>Sdiffs</a>
+<a href=src/share/classes/java/lang/Shutdown.java-.html>Old</a>
+<a href=src/share/classes/java/lang/Shutdown.java.html>New</a>
+<b>src/share/classes/java/lang/Shutdown.java</b><p>
+<ul>
+<li><a href=http://example.com/cgi-bin/bugtraq_showbug?bugid=4904881>4904881</a>: JVM crash during java.io.File.deleteOnExit()<br>
+</ul>
+<p>
+<a href=src/share/native/java/lang/Shutdown.c.diff.html>Diffs</a>
+<a href=src/share/native/java/lang/Shutdown.c.sdiff.html>Sdiffs</a>
+<a href=src/share/native/java/lang/Shutdown.c-.html>Old</a>
+<a href=src/share/native/java/lang/Shutdown.c.html>New</a>
+<b>src/share/native/java/lang/Shutdown.c</b><p>
+<ul>
+<li><a href=http://example.com/cgi-bin/bugtraq_showbug?bugid=4904881>4904881</a>: JVM crash during java.io.File.deleteOnExit()<br>
+</ul>
+</code>
+<p>
+</font>
+</html>
+
+# Data for usage case 5
+
+# This is the main Samba configuration file. You should read the
+# smb.conf(5) manual page in order to understand the options listed
+# here. Samba has a huge number of configurable options (perhaps too
+# many!) most of which are not shown in this example
+#
+# Any line which starts with a ; (semi-colon) or a # (hash)
+# is a comment and is ignored. In this example we will use a #
+# for commentry and a ; for parts of the config file that you
+# may wish to enable
+#
+# NOTE: Whenever you modify this file you should run the command "testparm"
+# to check that you have not many any basic syntactic errors.
+#
+#======================= Global Settings =====================================
+[global]
+
+##
+## Basic Server Settings
+##
+
+	# workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4
+	workgroup = MYGROUP
+
+	# server string is the equivalent of the NT Description field
+	server string = Samba Server
+
+	# This option is important for security. It allows you to restrict
+	# connections to machines which are on your local network. The
+	# following example restricts access to two C class networks and
+	# the "loopback" interface. For more examples of the syntax see
+	# the smb.conf man page
+	; hosts allow = 192.168.1. 192.168.2.0./24 192.168.3.0/255.255.255.0 127.0.0.1
+
+	# Uncomment this if you want a guest account, you must add this to /etc/passwd
+	# otherwise the user "nobody" is used
+	; guest account = pcguest
+
+	# this tells Samba to use a separate log file for each machine
+	# that connects
+	log file = /usr/local/samba/var/log.%m
+
+	# How much information do you want to see in the logs?
+	# default is only to log critical messages
+	; log level = 1
+
+	# Put a capping on the size of the log files (in Kb).
+	max log size = 50
+
+	# Security mode. Most people will want user level security. See
+	# security_level.txt for details.
+	security = user
+
+	# Using the following line enables you to customise your configuration
+	# on a per machine basis. The %m gets replaced with the netbios name
+	# of the machine that is connecting.
+	# Note: Consider carefully the location in the configuration file of
+	#       this line.  The included file is read at that point.
+	;   include = /usr/local/samba/lib/smb.conf.%m
+
+	# Most people will find that this option gives better performance.
+	# See speed.txt and the manual pages for details
+	# You may want to add the following on a Linux system:
+	#         SO_RCVBUF=8192 SO_SNDBUF=8192
+	; socket options = TCP_NODELAY
+
+	# Configure Samba to use multiple interfaces
+	# If you have multiple network interfaces and want to limit smbd will
+	# use, list the ones desired here.  Otherwise smbd & nmbd will bind to all
+	# active interfaces on the system.  See the man page for details.
+	;   interfaces = 192.168.12.2/24 192.168.13.2/24
+
+	# Should smbd report that it has MS-DFS Capabilities? Only available
+	# if --with-msdfs was passed to ./configure
+	; host msdfs = yes
+
+##
+## Network Browsing
+##
+	# set local master to no if you don't want Samba to become a master
+	# browser on your network. Otherwise the normal election rules apply
+	; local master = no
+
+	# OS Level determines the precedence of this server in master browser
+	# elections. The default value (20) should be reasonable
+	; os level = 20
+
+	# Domain Master specifies Samba to be the Domain Master Browser. This
+	# allows Samba to collate browse lists between subnets. Don't use this
+	# if you already have a Windows NT domain controller doing this job
+	; domain master = yes
+
+	# Preferred Master causes Samba to force a local browser election on startup
+	# and gives it a slightly higher chance of winning the election
+	; preferred master = yes
+
+
+##
+## WINS & Name Resolution
+##
+	# Windows Internet Name Serving Support Section:
+	# WINS Support - Tells the NMBD component of Samba to enable it's WINS Server
+	; wins support = yes
+
+	# WINS Server - Tells the NMBD components of Samba to be a WINS Client
+	#	Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
+	; wins server = w.x.y.z
+
+	# WINS Proxy - Tells Samba to answer name resolution queries on
+	# behalf of a non WINS capable client, for this to work there must be
+	# at least one	WINS Server on the network. The default is NO.
+	; wins proxy = yes
+
+	# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names
+	# via DNS nslookups.
+	dns proxy = no
+
+
+##
+## Passwords & Authentication
+##
+	# Use password server option only with security = server
+	# The argument list may include:
+	#   password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name]
+	# or to auto-locate the domain controller/s
+	;   password server = *
+	;   password server = <NT-Server-Name>
+
+	# You may wish to use password encryption. Please read
+	# ENCRYPTION.txt, Win95.txt and WinNT.txt in the Samba documentation.
+	# Do not enable this option unless you have read those documents
+	;  encrypt passwords = yes
+
+	# Should smbd obey the session and account lines in /etc/pam.d/samba ?
+	# only available if --with-pam was used at compile time
+	; obey pam restrictions = yes
+
+	# When using encrypted passwords, Samba can synchronize the local
+	# UNIX password as well.  You will also need the "passwd chat" parameters
+	; unix password sync = yes
+
+	# how should smbd talk to the local system when changing a UNIX
+	# password?  See smb.conf(5) for details
+	; passwd chat = <custom chat string>
+
+	# This is only available if you compiled Samba to include --with-pam
+	# Use PAM for changing the password
+	; pam password change = yes
+
+##
+## Domain Control
+##
+	# Enable this if you want Samba act as a domain controller.
+	# make sure you have read the Samba-PDC-HOWTO included in the documentation
+	# before enabling this parameter
+	;   domain logons = yes
+
+	# if you enable domain logons then you may want a per-machine or
+	# per user logon script
+	# run a specific logon batch file per workstation (machine)
+	; logon script = %m.bat
+	# run a specific logon batch file per username
+	; logon script = %U.bat
+
+	# Where to store roving profiles (only for Win95 and WinNT)
+	#        %L substitutes for this servers netbios name, %U is username
+	#        You must uncomment the [Profiles] share below
+	; logon path = \\%L\Profiles\%U
+
+	# UNC path specifying the network location of the user's home directory
+	# only used when acting as a DC for WinNT/2k/XP.  Ignored by Win9x clients
+	; logon home = \\%L\%U
+
+	# What drive should the "logon home" be mounted at upon login ?
+	# only used when acting as a DC for WinNT/2k/XP.  Ignored by Win9x clients
+	; logon drive = H:
+
+##
+## Printing
+##
+
+	# If you want to automatically load your printer list rather
+	# than setting them up individually then you'll need this
+	load printers = yes
+
+	# you may wish to override the location of the printcap file
+	; printcap name = /etc/printcap
+
+	# on SystemV system setting printcap name to lpstat should allow
+	# you to automatically obtain a printer list from the SystemV spool
+	# system
+	; printcap name = lpstat
+
+	# It should not be necessary to specify the print system type unless
+	# it is non-standard. Currently supported print systems include:
+	# bsd, sysv, plp, lprng, aix, hpux, qnx
+	; printing = bsd
+
+	# Enable this to make Samba 2.2 behavior just like Samba 2.0
+	# not recommended nuless you are sure of what you are doing
+	; disable spoolss = yes
+
+	# list of users and groups which should be able to remotely manage
+	# printer drivers installed on the server
+	; printer admin = root, +ntadmin
+
+
+##
+## Winbind
+##
+
+	# specify the uid range which can be used by winbindd
+	# to allocate uids for Windows users as necessary
+	; winbind uid = 10000-65000
+
+	# specify the uid range which can be used by winbindd
+	# to allocate uids for Windows users as necessary
+	; winbind gid = 10000-65000
+
+	# Define a home directory to be given to passwd(5) style entries
+	# generated by libnss_winbind.so.  You can use variables here
+	; winbind template homedir = /home/%D/%U
+
+	# Specify a shell for all winbind user entries return by the
+	# libnss_winbind.so library.
+	; winbind template shell = /bin/sh
+
+	# What character should be used to separate the DOMAIN and Username
+	# for a Windows user.  The default is DOMAIN\user, but many people
+	# prefer DOMAIN+user
+	; winbind separator = +
+
+
+#============================ Share Definitions ==============================
+[homes]
+     comment = Home Directories
+     browseable = no
+     writable = yes
+     valid users = %S
+
+# Un-comment the following and create the netlogon directory for Domain Logons
+; [netlogon]
+;    comment = Network Logon Service
+;    path = /usr/local/samba/lib/netlogon
+;    guest ok = yes
+;    writable = no
+;    share modes = no
+
+
+# Un-comment the following to provide a specific roving profile share
+# the default is to use the user's home directory
+;[Profiles]
+;    path = /usr/local/samba/profiles
+;    browseable = no
+;    guest ok = yes
+
+
+# NOTE: If you have a BSD-style print system there is no need to
+# specifically define each individual printer
+[printers]
+   comment = All Printers
+   path = /usr/spool/samba
+   browseable = no
+   # Set public = yes to allow user 'guest account' to print
+   guest ok = no
+   writable = no
+   printable = yes
+
+# This one is useful for people to share files
+#[tmp]
+#   comment = Temporary file space
+#   path = /tmp
+#   read only = no
+#   public = yes
+
+
+# MS-DFS support is only available if Samba was compiled to
+# include --with-msdfs
+;[dfsroot]
+;   dfs root = yes
+
+
+# A publicly accessible directory, but read only, except for people in
+# the "staff" group
+;[public]
+;   comment = Public Stuff
+;   path = /home/samba
+;   public = yes
+;   writable = yes
+;   printable = no
+;   write list = @staff
+
+
+##
+## Other examples.
+##
+
+# A private printer, usable only by fred. Spool data will be placed in fred's
+# home directory. Note that fred must have write access to the spool directory,
+# wherever it is.
+#[fredsprn]
+#   comment = Fred's Printer
+#   valid users = fred
+#   path = /homes/fred
+#   printer = freds_printer
+#   public = no
+#   writable = no
+#   printable = yes
+
+# A private directory, usable only by fred. Note that fred requires write
+# access to the directory.
+#[fredsdir]
+#   comment = Fred's Service
+#   path = /usr/somewhere/private
+#   valid users = fred
+#   public = no
+#   writable = yes
+#   printable = no
+
+# a service which has a different directory for each machine that connects
+# this allows you to tailor configurations to incoming machines. You could
+# also use the %U option to tailor it by user name.
+# The %m gets replaced with the machine name that is connecting.
+#[pchome]
+#  comment = PC Directories
+#  path = /usr/pc/%m
+#  public = no
+#  writable = yes
+
+# A publicly accessible directory, read/write to all users. Note that all files
+# created in the directory by users will be owned by the default user, so
+# any user with access can delete any other user's files. Obviously this
+# directory must be writable by the default user. Another user could of course
+# be specified, in which case all files would be owned by that user instead.
+#[public]
+#   path = /usr/somewhere/else/public
+#   public = yes
+#   only guest = yes
+#   writable = yes
+#   printable = no
+
+# The following two entries demonstrate how to share a directory so that two
+# users can place files there that will be owned by the specific users. In this
+# setup, the directory should be writable by both users and should have the
+# sticky bit set on it to prevent abuse. Obviously this could be extended to
+# as many users as required.
+#[myshare]
+#   comment = Mary's and Fred's stuff
+#   path = /usr/somewhere/shared
+#   valid users = mary fred
+#   public = no
+#   writable = yes
+#   printable = no
+#   create mask = 0765
+
+
+
+
+# Data for usage case 6