changeset 42972:47ca49eee534

8172102: jshell tool: remove print method forwarding to System.out from default startup Reviewed-by: briangoetz
author rfield
date Mon, 02 Jan 2017 18:31:30 -0800
parents 22c8c025a651
children 3795332b55c7
files langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties langtools/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT.jsh langtools/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/JAVASE.jsh langtools/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/PRINTING.jsh langtools/test/jdk/jshell/EditorTestBase.java langtools/test/jdk/jshell/ReplToolTesting.java langtools/test/jdk/jshell/StartOptionTest.java langtools/test/jdk/jshell/ToolBasicTest.java langtools/test/jdk/jshell/ToolCommandOptionTest.java langtools/test/jdk/jshell/ToolLocalSimpleTest.java langtools/test/jdk/jshell/ToolSimpleTest.java
diffstat 12 files changed, 412 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Fri Dec 23 11:17:50 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Mon Jan 02 18:31:30 2017 -0800
@@ -25,15 +25,18 @@
 
 package jdk.internal.jshell.tool;
 
+import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.PrintStream;
 import java.io.Reader;
 import java.io.StringReader;
+import java.net.URL;
 import java.nio.charset.Charset;
 import java.nio.file.AccessDeniedException;
 import java.nio.file.FileSystems;
@@ -196,6 +199,7 @@
     private boolean debug = false;
     public boolean testPrompt = false;
     private String cmdlineClasspath = null;
+    private String defaultStartup = null;
     private String startup = null;
     private String executionControlSpec = null;
     private EditorSetting editor = BUILT_IN_EDITOR;
@@ -213,16 +217,9 @@
     static final String MODE_KEY     = "MODE";
     static final String REPLAY_RESTORE_KEY = "REPLAY_RESTORE";
 
-    static final String DEFAULT_STARTUP =
-            "\n" +
-            "import java.util.*;\n" +
-            "import java.io.*;\n" +
-            "import java.math.*;\n" +
-            "import java.net.*;\n" +
-            "import java.util.concurrent.*;\n" +
-            "import java.util.prefs.*;\n" +
-            "import java.util.regex.*;\n" +
-            "void printf(String format, Object... args) { System.out.printf(format, args); }\n";
+    static final String DEFAULT_STARTUP_NAME = "DEFAULT";
+    static final Pattern BUILTIN_FILE_PATTERN = Pattern.compile("\\w+");
+    static final String BUILTIN_FILE_PATH_FORMAT = "jrt:/jdk.jshell/jdk/jshell/tool/resources/%s.jsh";
 
     // Tool id (tid) mapping: the three name spaces
     NameSpace mainNamespace;
@@ -482,7 +479,7 @@
         if (startup == null) {
             startup = prefs.get(STARTUP_KEY);
             if (startup == null) {
-                startup = DEFAULT_STARTUP;
+                startup = defaultStartup();
             }
         }
 
@@ -606,14 +603,19 @@
         }
         if (options.has(st)) {
             List<String> sts = options.valuesOf(st);
-            if (sts.size() != 1 || options.has("no-startup")) {
-                startmsg("jshell.err.opt.startup.one");
+            if (options.has("no-startup")) {
+                startmsg("jshell.err.opt.startup.conflict");
                 return null;
             }
-            startup = readFile(sts.get(0), "--startup");
-            if (startup == null) {
-                return null;
+            StringBuilder sb = new StringBuilder();
+            for (String fn : sts) {
+                String s = readFile(fn, "--startup");
+                if (s == null) {
+                    return null;
+                }
+                sb.append(s);
             }
+            startup = sb.toString();
         } else if (options.has("no-startup")) {
             startup = "";
         }
@@ -798,7 +800,7 @@
 
     //where
     private void startUpRun(String start) {
-        try (IOContext suin = new FileScannerIOContext(new StringReader(start))) {
+        try (IOContext suin = new ScannerIOContext(new StringReader(start))) {
             run(suin);
         } catch (Exception ex) {
             hardmsg("jshell.err.startup.unexpected.exception", ex);
@@ -1623,14 +1625,17 @@
     // The sub-command:  /set start <start-file>
     boolean setStart(ArgTokenizer at) {
         at.allowedOptions("-default", "-none", "-retain");
-        String fn = at.next();
+        List<String> fns = new ArrayList<>();
+        while (at.next() != null) {
+            fns.add(at.val());
+        }
         if (!checkOptionsAndRemainingInput(at)) {
             return false;
         }
         boolean defaultOption = at.hasOption("-default");
         boolean noneOption = at.hasOption("-none");
         boolean retainOption = at.hasOption("-retain");
-        boolean hasFile = fn != null;
+        boolean hasFile = !fns.isEmpty();
 
         int argCount = (defaultOption ? 1 : 0) + (noneOption ? 1 : 0) + (hasFile ? 1 : 0);
         if (argCount > 1) {
@@ -1643,13 +1648,17 @@
             return true;
         }
         if (hasFile) {
-            String init = readFile(fn, "/set start");
-            if (init == null) {
-                return false;
+            StringBuilder sb = new StringBuilder();
+            for (String fn : fns) {
+                String s = readFile(fn, "/set start");
+                if (s == null) {
+                    return false;
+                }
+                sb.append(s);
             }
-            startup = init;
+            startup = sb.toString();
         } else if (defaultOption) {
-            startup = DEFAULT_STARTUP;
+            startup = defaultStartup();
         } else if (noneOption) {
             startup = "";
         }
@@ -1673,7 +1682,7 @@
     void showSetStart(boolean isRetained, String start) {
         String cmd = "/set start" + (isRetained ? " -retain " : " ");
         String stset;
-        if (start.equals(DEFAULT_STARTUP)) {
+        if (start.equals(defaultStartup())) {
             stset = cmd + "-default";
         } else if (start.isEmpty()) {
             stset = cmd + "-none";
@@ -2166,7 +2175,16 @@
     private boolean runFile(String filename, String context) {
         if (!filename.isEmpty()) {
             try {
-                run(new FileScannerIOContext(toPathResolvingUserHome(filename).toString()));
+                Path path = toPathResolvingUserHome(filename);
+                Reader reader;
+                String resource;
+                if (!Files.exists(path) && (resource = getResource(filename)) != null) {
+                    // Not found as file, but found as resource
+                    reader = new StringReader(resource);
+                } else {
+                    reader = new FileReader(path.toString());
+                }
+                run(new ScannerIOContext(reader));
                 return true;
             } catch (FileNotFoundException e) {
                 errormsg("jshell.err.file.not.found", context, filename, e.getMessage());
@@ -2189,11 +2207,16 @@
     String readFile(String filename, String context) {
         if (filename != null) {
             try {
-                byte[] encoded = Files.readAllBytes(Paths.get(filename));
+                byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename));
                 return new String(encoded);
             } catch (AccessDeniedException e) {
                 errormsg("jshell.err.file.not.accessible", context, filename, e.getMessage());
             } catch (NoSuchFileException e) {
+                String resource = getResource(filename);
+                if (resource != null) {
+                    // Not found as file, but found as resource
+                    return resource;
+                }
                 errormsg("jshell.err.file.not.found", context, filename);
             } catch (Exception e) {
                 errormsg("jshell.err.file.exception", context, filename, e);
@@ -2205,6 +2228,44 @@
 
     }
 
+    // Read a built-in file from resources or null
+    String getResource(String name) {
+        if (BUILTIN_FILE_PATTERN.matcher(name).matches()) {
+            try {
+                return readResource(name);
+            } catch (Throwable t) {
+                // Fall-through to null
+            }
+        }
+        return null;
+    }
+
+    // Read a built-in file from resources
+    String readResource(String name) throws IOException {
+        // Attempt to find the file as a resource
+        String spec = String.format(BUILTIN_FILE_PATH_FORMAT, name);
+        URL url = new URL(spec);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
+        return reader.lines().collect(Collectors.joining("\n"));
+    }
+
+    // retrieve the default startup string
+    String defaultStartup() {
+        if (defaultStartup == null) {
+            defaultStartup = ""; // failure case
+            try {
+                defaultStartup = readResource(DEFAULT_STARTUP_NAME);
+            } catch (AccessDeniedException e) {
+                errormsg("jshell.err.file.not.accessible", "jshell", DEFAULT_STARTUP_NAME, e.getMessage());
+            } catch (NoSuchFileException e) {
+                errormsg("jshell.err.file.not.found", "jshell", DEFAULT_STARTUP_NAME);
+            } catch (Exception e) {
+                errormsg("jshell.err.file.exception", "jshell", DEFAULT_STARTUP_NAME, e);
+            }
+        }
+        return defaultStartup;
+    }
+
     private boolean cmdReset() {
         live = false;
         fluffmsg("jshell.msg.resetting.state");
@@ -2910,6 +2971,10 @@
         this.scannerIn = scannerIn;
     }
 
+    ScannerIOContext(Reader rdr) throws FileNotFoundException {
+        this(new Scanner(rdr));
+    }
+
     @Override
     public String readLine(String prompt, String prefix) {
         if (scannerIn.hasNextLine()) {
@@ -2930,17 +2995,6 @@
     }
 }
 
-class FileScannerIOContext extends ScannerIOContext {
-
-    FileScannerIOContext(String fn) throws FileNotFoundException {
-        this(new FileReader(fn));
-    }
-
-    FileScannerIOContext(Reader rdr) throws FileNotFoundException {
-        super(new Scanner(rdr));
-    }
-}
-
 class ReloadIOContext extends NonInteractiveIOContext {
     private final Iterator<String> it;
     private final PrintStream echoStream;
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Fri Dec 23 11:17:50 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Mon Jan 02 18:31:30 2017 -0800
@@ -29,7 +29,7 @@
 jshell.err.opt.arg = Argument to {0} missing.
 jshell.err.opt.invalid = Invalid options: {0}.
 jshell.err.opt.one = Only one {0} option may be used.
-jshell.err.opt.startup.one = Only one --startup or --no-startup option may be used.
+jshell.err.opt.startup.conflict = Conflicting options: both --startup and --no-startup were used.
 jshell.err.opt.feedback.one = Only one feedback option (--feedback, -q, -s, or -v) may be used.
 jshell.err.opt.unknown = Unknown option: {0}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT.jsh	Mon Jan 02 18:31:30 2017 -0800
@@ -0,0 +1,11 @@
+import java.io.*;
+import java.math.*;
+import java.net.*;
+import java.nio.file.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.function.*;
+import java.util.prefs.*;
+import java.util.regex.*;
+import java.util.stream.*;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/JAVASE.jsh	Mon Jan 02 18:31:30 2017 -0800
@@ -0,0 +1,173 @@
+import java.applet.*;
+import java.awt.*;
+import java.awt.color.*;
+import java.awt.datatransfer.*;
+import java.awt.desktop.*;
+import java.awt.dnd.*;
+import java.awt.event.*;
+import java.awt.font.*;
+import java.awt.geom.*;
+import java.awt.im.*;
+import java.awt.im.spi.*;
+import java.awt.image.*;
+import java.awt.image.renderable.*;
+import java.awt.print.*;
+import java.beans.*;
+import java.beans.beancontext.*;
+import java.io.*;
+import java.lang.*;
+import java.lang.annotation.*;
+import java.lang.instrument.*;
+import java.lang.invoke.*;
+import java.lang.management.*;
+import java.lang.module.*;
+import java.lang.ref.*;
+import java.lang.reflect.*;
+import java.math.*;
+import java.net.*;
+import java.net.spi.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.nio.channels.spi.*;
+import java.nio.charset.*;
+import java.nio.charset.spi.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.nio.file.spi.*;
+import java.rmi.*;
+import java.rmi.activation.*;
+import java.rmi.dgc.*;
+import java.rmi.registry.*;
+import java.rmi.server.*;
+import java.security.*;
+import java.security.acl.*;
+import java.security.cert.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
+import java.sql.*;
+import java.text.*;
+import java.text.spi.*;
+import java.time.*;
+import java.time.chrono.*;
+import java.time.format.*;
+import java.time.temporal.*;
+import java.time.zone.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.*;
+import java.util.function.*;
+import java.util.jar.*;
+import java.util.logging.*;
+import java.util.prefs.*;
+import java.util.regex.*;
+import java.util.spi.*;
+import java.util.stream.*;
+import java.util.zip.*;
+import javax.accessibility.*;
+import javax.annotation.processing.*;
+import javax.crypto.*;
+import javax.crypto.interfaces.*;
+import javax.crypto.spec.*;
+import javax.imageio.*;
+import javax.imageio.event.*;
+import javax.imageio.metadata.*;
+import javax.imageio.plugins.bmp.*;
+import javax.imageio.plugins.jpeg.*;
+import javax.imageio.plugins.tiff.*;
+import javax.imageio.spi.*;
+import javax.imageio.stream.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import javax.management.*;
+import javax.management.loading.*;
+import javax.management.modelmbean.*;
+import javax.management.monitor.*;
+import javax.management.openmbean.*;
+import javax.management.relation.*;
+import javax.management.remote.*;
+import javax.management.remote.rmi.*;
+import javax.management.timer.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.event.*;
+import javax.naming.ldap.*;
+import javax.naming.spi.*;
+import javax.net.*;
+import javax.net.ssl.*;
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.attribute.standard.*;
+import javax.print.event.*;
+import javax.rmi.ssl.*;
+import javax.script.*;
+import javax.security.auth.*;
+import javax.security.auth.callback.*;
+import javax.security.auth.kerberos.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+import javax.security.auth.x500.*;
+import javax.security.cert.*;
+import javax.security.sasl.*;
+import javax.sound.midi.*;
+import javax.sound.midi.spi.*;
+import javax.sound.sampled.*;
+import javax.sound.sampled.spi.*;
+import javax.sql.*;
+import javax.sql.rowset.*;
+import javax.sql.rowset.serial.*;
+import javax.sql.rowset.spi.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.colorchooser.*;
+import javax.swing.event.*;
+import javax.swing.filechooser.*;
+import javax.swing.plaf.*;
+import javax.swing.plaf.basic.*;
+import javax.swing.plaf.metal.*;
+import javax.swing.plaf.multi.*;
+import javax.swing.plaf.nimbus.*;
+import javax.swing.plaf.synth.*;
+import javax.swing.table.*;
+import javax.swing.text.*;
+import javax.swing.text.html.*;
+import javax.swing.text.html.parser.*;
+import javax.swing.text.rtf.*;
+import javax.swing.tree.*;
+import javax.swing.undo.*;
+import javax.tools.*;
+import javax.transaction.xa.*;
+import javax.xml.*;
+import javax.xml.catalog.*;
+import javax.xml.crypto.*;
+import javax.xml.crypto.dom.*;
+import javax.xml.crypto.dsig.*;
+import javax.xml.crypto.dsig.dom.*;
+import javax.xml.crypto.dsig.keyinfo.*;
+import javax.xml.crypto.dsig.spec.*;
+import javax.xml.datatype.*;
+import javax.xml.namespace.*;
+import javax.xml.parsers.*;
+import javax.xml.stream.*;
+import javax.xml.stream.events.*;
+import javax.xml.stream.util.*;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.sax.*;
+import javax.xml.transform.stax.*;
+import javax.xml.transform.stream.*;
+import javax.xml.validation.*;
+import javax.xml.xpath.*;
+import org.ietf.jgss.*;
+import org.w3c.dom.*;
+import org.w3c.dom.bootstrap.*;
+import org.w3c.dom.events.*;
+import org.w3c.dom.ls.*;
+import org.w3c.dom.ranges.*;
+import org.w3c.dom.traversal.*;
+import org.w3c.dom.views.*;
+import org.xml.sax.*;
+import org.xml.sax.ext.*;
+import org.xml.sax.helpers.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/PRINTING.jsh	Mon Jan 02 18:31:30 2017 -0800
@@ -0,0 +1,21 @@
+void print(boolean b) { System.out.print(b); }
+void print(char c) { System.out.print(c); }
+void print(int i) { System.out.print(i); }
+void print(long l) { System.out.print(l); }
+void print(float f) { System.out.print(f); }
+void print(double d) { System.out.print(d); }
+void print(char s[]) { System.out.print(s); }
+void print(String s) { System.out.print(s); }
+void print(Object obj) { System.out.print(obj); }
+void println() { System.out.println(); }
+void println(boolean b) { System.out.println(b); }
+void println(char c) { System.out.println(c); }
+void println(int i) { System.out.println(i); }
+void println(long l) { System.out.println(l); }
+void println(float f) { System.out.println(f); }
+void println(double d) { System.out.println(d); }
+void println(char s[]) { System.out.println(s); }
+void println(String s) { System.out.println(s); }
+void println(Object obj) { System.out.println(obj); }
+void printf(Locale l, String format, Object... args) { System.out.printf(l, format, args); }
+void printf(String format, Object... args) { System.out.printf(format, args); }
--- a/langtools/test/jdk/jshell/EditorTestBase.java	Fri Dec 23 11:17:50 2016 -0800
+++ b/langtools/test/jdk/jshell/EditorTestBase.java	Mon Jan 02 18:31:30 2017 -0800
@@ -219,7 +219,7 @@
     public void testStartup() {
         testEditor(true, new String[0],
                 a -> assertEditInput(a, "/ed", s -> assertTrue(s.isEmpty(), "Checking of startup: " + s), this::cancel),
-                a -> assertEditInput(a, "/ed printf", assertStartsWith("void printf"), this::cancel));
+                a -> assertEditInput(a, "/ed s1", assertStartsWith("import"), this::cancel));
     }
 
     @Test
--- a/langtools/test/jdk/jshell/ReplToolTesting.java	Fri Dec 23 11:17:50 2016 -0800
+++ b/langtools/test/jdk/jshell/ReplToolTesting.java	Mon Jan 02 18:31:30 2017 -0800
@@ -25,6 +25,7 @@
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -54,22 +55,45 @@
 
     private final static String DEFAULT_STARTUP_MESSAGE = "|  Welcome to";
     final static List<ImportInfo> START_UP_IMPORTS = Stream.of(
-                    "java.util.*",
                     "java.io.*",
                     "java.math.*",
                     "java.net.*",
+                    "java.nio.file.*",
+                    "java.util.*",
                     "java.util.concurrent.*",
+                    "java.util.function.*",
                     "java.util.prefs.*",
-                    "java.util.regex.*")
+                    "java.util.regex.*",
+                    "java.util.stream.*")
                     .map(s -> new ImportInfo("import " + s + ";", "", s))
                     .collect(toList());
-    final static List<MethodInfo> START_UP_METHODS = Stream.of(
-                    new MethodInfo("void printf(String format, Object... args) { System.out.printf(format, args); }",
-                            "(String,Object...)void", "printf"))
+    final static List<MethodInfo> START_UP_METHODS = Stream.<MethodInfo>of()
                     .collect(toList());
-    final static List<String> START_UP_CMD_METHOD = Stream.of(
-                    "|    printf (String,Object...)void")
+    final static List<String> START_UP_CMD_METHOD = Stream.<String>of()
                     .collect(toList());
+    final static List<String> PRINTING_CMD_METHOD = Stream.of(
+            "|    print (boolean)void",
+            "|    print (char)void",
+            "|    print (int)void",
+            "|    print (long)void",
+            "|    print (float)void",
+            "|    print (double)void",
+            "|    print (char s[])void",
+            "|    print (String)void",
+            "|    print (Object)void",
+            "|    println ()void",
+            "|    println (boolean)void",
+            "|    println (char)void",
+            "|    println (int)void",
+            "|    println (long)void",
+            "|    println (float)void",
+            "|    println (double)void",
+            "|    println (char s[])void",
+            "|    println (String)void",
+            "|    println (Object)void",
+            "|    printf (Locale,String,Object...)void",
+            "|    printf (String,Object...)void")
+            .collect(toList());
     final static List<String> START_UP = Collections.unmodifiableList(
             Stream.concat(START_UP_IMPORTS.stream(), START_UP_METHODS.stream())
             .map(s -> s.getSource())
@@ -432,9 +456,14 @@
         assertCommand(after, cmd, out, "", null, "", "");
     }
 
-    public void assertCommandOutputContains(boolean after, String cmd, String has) {
-        assertCommandCheckOutput(after, cmd, (s) ->
-                        assertTrue(s.contains(has), "Output: \'" + s + "' does not contain: " + has));
+    public void assertCommandOutputContains(boolean after, String cmd, String... hasThese) {
+        assertCommandCheckOutput(after, cmd, (s)
+                -> assertTrue(Arrays.stream(hasThese)
+                                    .allMatch(has -> s.contains(has)),
+                        "Output: \'" + s + "' does not contain: "
+                                + Arrays.stream(hasThese)
+                                        .filter(has -> !s.contains(has))
+                                        .collect(Collectors.joining(", "))));
     }
 
     public void assertCommandOutputStartsWith(boolean after, String cmd, String starts) {
@@ -467,7 +496,7 @@
     }
 
     public Consumer<String> assertStartsWith(String prefix) {
-        return (output) -> assertTrue(output.startsWith(prefix), "Output: \'" + output + "' does not start with: " + prefix);
+        return (output) -> assertTrue(output.trim().startsWith(prefix), "Output: \'" + output + "' does not start with: " + prefix);
     }
 
     public void assertOutput(String got, String expected, String display) {
--- a/langtools/test/jdk/jshell/StartOptionTest.java	Fri Dec 23 11:17:50 2016 -0800
+++ b/langtools/test/jdk/jshell/StartOptionTest.java	Mon Jan 02 18:31:30 2017 -0800
@@ -22,7 +22,7 @@
  */
 
 /*
- * @test 8151754 8080883 8160089 8170162 8166581
+ * @test 8151754 8080883 8160089 8170162 8166581 8172102
  * @summary Testing start-up options.
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -33,17 +33,14 @@
  * @run testng StartOptionTest
  */
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.util.HashMap;
 import java.util.Locale;
-import java.util.ServiceLoader;
 import java.util.function.Consumer;
 
-import javax.tools.Tool;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -157,9 +154,8 @@
         Path p = compiler.getPath("file.txt");
         compiler.writeToFile(p);
         start("", "Argument to startup missing.", "--startup");
-        start("", "Only one --startup or --no-startup option may be used.", "--startup", p.toString(), "--startup", p.toString());
-        start("", "Only one --startup or --no-startup option may be used.", "--no-startup", "--startup", p.toString());
-        start("", "Only one --startup or --no-startup option may be used.", "--startup", p.toString(), "--no-startup");
+        start("", "Conflicting options: both --startup and --no-startup were used.", "--no-startup", "--startup", p.toString());
+        start("", "Conflicting options: both --startup and --no-startup were used.", "--startup", p.toString(), "--no-startup");
         start("", "Argument to startup missing.", "--no-startup", "--startup");
     }
 
@@ -176,6 +172,7 @@
 
     public void testStartupUnknown() throws Exception {
         start("", "File 'UNKNOWN' for '--startup' is not found.", "--startup", "UNKNOWN");
+        start("", "File 'UNKNOWN' for '--startup' is not found.", "--startup", "DEFAULT", "--startup", "UNKNOWN");
     }
 
     public void testClasspath() throws Exception {
--- a/langtools/test/jdk/jshell/ToolBasicTest.java	Fri Dec 23 11:17:50 2016 -0800
+++ b/langtools/test/jdk/jshell/ToolBasicTest.java	Mon Jan 02 18:31:30 2017 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643 8170162
+ * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643 8170162 8172102
  * @summary Tests for Basic tests for REPL tool
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -310,10 +310,10 @@
                 (a) -> evaluateExpression(a, "A", "new A()", "A")
         );
         test(new String[]{"--no-startup"},
-                (a) -> assertCommandCheckOutput(a, "printf(\"\")", assertStartsWith("|  Error:\n|  cannot find symbol"))
+                (a) -> assertCommandCheckOutput(a, "Pattern.compile(\"x+\")", assertStartsWith("|  Error:\n|  cannot find symbol"))
         );
         test(
-                (a) -> assertCommand(a, "printf(\"A\")", "", "", null, "A", "")
+                (a) -> assertCommand(a, "Pattern.compile(\"x+\")", "$1 ==> x+", "", null, "", "")
         );
     }
 
@@ -385,6 +385,16 @@
         }
     }
 
+    public void testOpenResource() {
+        test(
+                (a) -> assertCommand(a, "/open PRINTING", ""),
+                (a) -> assertCommandOutputContains(a, "/list",
+                        "void println", "System.out.printf"),
+                (a) -> assertCommand(a, "printf(\"%4.2f\", Math.PI)",
+                        "", "", null, "3.14", "")
+        );
+    }
+
     public void testSave() throws IOException {
         Compiler compiler = new Compiler();
         Path path = compiler.getPath("testSave.repl");
--- a/langtools/test/jdk/jshell/ToolCommandOptionTest.java	Fri Dec 23 11:17:50 2016 -0800
+++ b/langtools/test/jdk/jshell/ToolCommandOptionTest.java	Mon Jan 02 18:31:30 2017 -0800
@@ -23,7 +23,7 @@
 
  /*
  * @test
- * @bug 8157395 8157393 8157517 8158738 8167128 8163840 8167637 8170368
+ * @bug 8157395 8157393 8157517 8158738 8167128 8163840 8167637 8170368 8172102
  * @summary Tests of jshell comand options, and undoing operations
  * @modules jdk.jshell/jdk.internal.jshell.tool
  *          jdk.compiler/com.sun.tools.javac.api
@@ -46,9 +46,9 @@
                 (a) -> assertCommand(a, "/li",
                         "1 : int x;"),
                 (a) -> assertCommandOutputStartsWith(a, "/lis -st",
-                        "\n  s1 : import"),
+                        "s1 : import"),
                 (a) -> assertCommandOutputStartsWith(a, "/list -all",
-                        "\n  s1 : import"),
+                        "s1 : import"),
                 (a) -> assertCommandOutputContains(a, "/list -all",
                         "1 : int x;"),
                 (a) -> assertCommandOutputContains(a, "/list -history",
@@ -260,10 +260,20 @@
                         "|  Specify no more than one of -default, -none, or a startup file name -- /set start foo -default"),
                 (a) -> assertCommand(a, "/set start frfg",
                         "|  File 'frfg' for '/set start' is not found."),
+                (a) -> assertCommand(a, "/set start DEFAULT frfg",
+                        "|  File 'frfg' for '/set start' is not found."),
                 (a) -> assertCommand(a, "/set start -default",
                         ""),
                 (a) -> assertCommand(a, "/set start",
                         "|  /set start -default"),
+                (a) -> assertCommand(a, "/set start DEFAULT",
+                        ""),
+                (a) -> assertCommand(a, "/set start",
+                        "|  /set start -default"),
+                (a) -> assertCommand(a, "/set start DEFAULT PRINTING",
+                        ""),
+                (a) -> assertCommandOutputContains(a, "/set start",
+                        "void println", "import java.util.*"),
                 (a) -> assertCommand(a, "/set start " + startup.toString(),
                         ""),
                 (a) -> assertCommand(a, "/set start",
--- a/langtools/test/jdk/jshell/ToolLocalSimpleTest.java	Fri Dec 23 11:17:50 2016 -0800
+++ b/langtools/test/jdk/jshell/ToolLocalSimpleTest.java	Mon Jan 02 18:31:30 2017 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8168615
+ * @bug 8168615 8172102
  * @summary Test all the ToolSimpleTest tests, but in local execution. Verify --execution flag
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -68,6 +68,15 @@
         );
     }
 
+    @Override
+    @Test
+    public void testCompoundStart() {
+        test(new String[]{"--startup", "DEFAULT", "--startup", "PRINTING"},
+                (a) -> assertCommandOutputContains(a, "/list -start",
+                        "System.out.println", "import java.util.concurrent")
+        );
+    }
+
     @Test
     public void testOptionBadR() {
         test(new String[]{"-R-RottenLiver"},
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java	Fri Dec 23 11:17:50 2016 -0800
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java	Mon Jan 02 18:31:30 2017 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368
+ * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102
  * @summary Simple jshell tool tests
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -391,8 +391,8 @@
                         s -> checkLineToList(s, START_UP)),
                 a -> assertCommandCheckOutput(a, "/list -all",
                         s -> checkLineToList(s, startVarList)),
-                a -> assertCommandCheckOutput(a, "/list printf",
-                        s -> assertTrue(s.contains("void printf"))),
+                a -> assertCommandOutputStartsWith(a, "/list s3",
+                        "s3 : import"),
                 a -> assertCommandOutputStartsWith(a, "/list " + arg,
                         "|  No such snippet: " + arg)
         );
@@ -417,8 +417,8 @@
                         s -> checkLineToList(s, startVarList)),
                 a -> assertCommandOutputStartsWith(a, "/vars -all",
                         "|    int aardvark = 0\n|    int a = "),
-                a -> assertCommandOutputStartsWith(a, "/vars printf",
-                        "|  This command does not accept the snippet 'printf'"),
+                a -> assertCommandOutputStartsWith(a, "/vars f",
+                        "|  This command does not accept the snippet 'f'"),
                 a -> assertCommand(a, "/var " + arg,
                         "|  No such snippet: " + arg)
         );
@@ -427,16 +427,18 @@
     @Test
     public void testMethodsArgs() {
         String arg = "qqqq";
-        List<String> startMethodList = new ArrayList<>(START_UP_CMD_METHOD);
-        test(
+        List<String> printingMethodList = new ArrayList<>(PRINTING_CMD_METHOD);
+        test(new String[]{"--startup", "PRINTING"},
                 a -> assertCommandCheckOutput(a, "/methods -all",
-                        s -> checkLineToList(s, startMethodList)),
+                        s -> checkLineToList(s, printingMethodList)),
                 a -> assertCommandCheckOutput(a, "/methods -start",
-                        s -> checkLineToList(s, startMethodList)),
-                a -> assertCommandCheckOutput(a, "/methods printf",
-                        s -> checkLineToList(s, startMethodList)),
+                        s -> checkLineToList(s, printingMethodList)),
+                a -> assertCommandCheckOutput(a, "/methods print println printf",
+                        s -> checkLineToList(s, printingMethodList)),
+                a -> assertCommandCheckOutput(a, "/methods println",
+                        s -> assertEquals(s.trim().split("\n").length, 10)),
                 a -> assertCommandCheckOutput(a, "/methods",
-                        s -> checkLineToList(s, startMethodList)),
+                        s -> checkLineToList(s, printingMethodList)),
                 a -> assertCommandOutputStartsWith(a, "/methods " + arg,
                         "|  No such snippet: " + arg),
                 a -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
@@ -448,9 +450,9 @@
                 a -> assertCommandOutputStartsWith(a, "/methods aardvark",
                         "|  This command does not accept the snippet 'aardvark' : int aardvark"),
                 a -> assertCommandCheckOutput(a, "/methods -start",
-                        s -> checkLineToList(s, startMethodList)),
-                a -> assertCommandCheckOutput(a, "/methods printf",
-                        s -> checkLineToList(s, startMethodList)),
+                        s -> checkLineToList(s, printingMethodList)),
+                a -> assertCommandCheckOutput(a, "/methods print println printf",
+                        s -> checkLineToList(s, printingMethodList)),
                 a -> assertCommandOutputStartsWith(a, "/methods g",
                         "|    g ()void"),
                 a -> assertCommandOutputStartsWith(a, "/methods f",
@@ -494,6 +496,22 @@
     }
 
     @Test
+    public void testCompoundStart() {
+        test(new String[]{"--startup", "DEFAULT", "--startup", "PRINTING"},
+                (a) -> assertCommand(a, "printf(\"%4.2f\", Math.PI)",
+                        "", "", null, "3.14", "")
+        );
+    }
+
+    @Test
+    public void testJavaSeStart() {
+        test(new String[]{"--startup", "JAVASE"},
+                (a) -> assertCommand(a, "ZoneOffsetTransitionRule.TimeDefinition.WALL",
+                        "$1 ==> WALL")
+        );
+    }
+
+    @Test
     public void defineClasses() {
         test(
                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),