src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolBuilder.java
changeset 47216 71c04702a3d5
parent 42843 a8d83044a192
child 47840 e0f08a49f3e3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolBuilder.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2016, 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 jdk.internal.jshell.tool;
+
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+import jdk.jshell.tool.JavaShellToolBuilder;
+
+/**
+ * Builder for programmatically building the jshell tool.
+ */
+public class JShellToolBuilder implements JavaShellToolBuilder {
+
+    private static final String PREFERENCES_NODE = "tool/JShell";
+    private InputStream cmdIn = System.in;
+    private InputStream userIn = null;
+    private PrintStream cmdOut = System.out;
+    private PrintStream console = System.out;
+    private PrintStream userOut = System.out;
+    private PrintStream cmdErr = System.err;
+    private PrintStream userErr = System.err;
+    private PersistentStorage prefs = null;
+    private Map<String, String> vars = null;
+    private Locale locale = Locale.getDefault();
+    private boolean capturePrompt = false;
+
+    /**
+     * Set the input channels.
+     * Default, if not set, {@code in(System.in, null)}.
+     *
+     * @param cmdIn source of command input
+     * @param userIn source of input for running user code, or {@code null} to
+     * be extracted from cmdIn
+     * @return the {@code JavaShellToolBuilder} instance
+     */
+    @Override
+    public JavaShellToolBuilder in(InputStream cmdIn, InputStream userIn) {
+        this.cmdIn = cmdIn;
+        this.userIn = userIn;
+        return this;
+    }
+
+    /**
+     * Set the output channels. Same as {@code out(output, output, output)}.
+     * Default, if not set, {@code out(System.out)}.
+     *
+     * @param output destination of command feedback, console interaction, and
+     * user code output
+     * @return the {@code JavaShellToolBuilder} instance
+     */
+    @Override
+    public JavaShellToolBuilder out(PrintStream output) {
+        this.cmdOut = output;
+        this.console = output;
+        this.userOut = output;
+        return this;
+    }
+
+    /**
+     * Set the output channels.
+     * Default, if not set, {@code out(System.out, System.out, System.out)}.
+     *
+     * @param cmdOut destination of command feedback including error messages
+     * for users
+     * @param console destination of console interaction
+     * @param userOut destination of user code output.  For example, user snippet
+     * {@code System.out.println("Hello")} when executed {@code Hello} goes to
+     * userOut.
+     * @return the {@code JavaShellToolBuilder} instance
+     */
+    @Override
+    public JavaShellToolBuilder out(PrintStream cmdOut, PrintStream console, PrintStream userOut) {
+        this.cmdOut = cmdOut;
+        this.console = console;
+        this.userOut = userOut;
+        return this;
+    }
+
+    /**
+     * Set the error channels. Same as {@code err(error, error)}.
+     * Default, if not set, {@code err(System.err)}.
+     *
+     * @param error destination of tool errors, and
+     * user code errors
+     * @return the {@code JavaShellToolBuilder} instance
+     */
+    @Override
+    public JavaShellToolBuilder err(PrintStream error) {
+        this.cmdErr = error;
+        this.userErr = error;
+        return this;
+    }
+
+    /**
+     * Set the error channels.
+     * Default, if not set, {@code err(System.err, System.err, System.err)}.
+     *
+     * @param cmdErr destination of tool start-up and fatal errors
+     * @param userErr destination of user code error output.
+     * For example, user snippet  {@code System.err.println("Oops")}
+     * when executed {@code Oops} goes to userErr.
+     * @return the {@code JavaShellToolBuilder} instance
+     */
+    @Override
+    public JavaShellToolBuilder err(PrintStream cmdErr, PrintStream userErr) {
+        this.cmdErr = cmdErr;
+        this.userErr = userErr;
+        return this;
+    }
+
+    /**
+     * Set the storage mechanism for persistent information which includes
+     * input history and retained settings. Default if not set is the
+     * tool's standard persistence mechanism.
+     *
+     * @param prefs an instance of {@link java.util.prefs.Preferences} that
+     * is used to retrieve and store persistent information
+     * @return the {@code JavaShellToolBuilder} instance
+     */
+    @Override
+    public JavaShellToolBuilder persistence(Preferences prefs) {
+        this.prefs = new PreferencesStorage(prefs);
+        return this;
+    }
+
+    /**
+     * Set the storage mechanism for persistent information which includes
+     * input history and retained settings.   Default if not set is the
+     * tool's standard persistence mechanism.
+     *
+     * @param prefsMap  an instance of {@link java.util.Map} that
+     * is used to retrieve and store persistent information
+     * @return the {@code JavaShellToolBuilder} instance
+     */
+    @Override
+    public JavaShellToolBuilder persistence(Map<String, String> prefsMap) {
+        this.prefs = new MapStorage(prefsMap);
+        return this;
+    }
+
+    /**
+     * Set the source for environment variables.
+     * Default, if not set, {@code env(System.getenv())}.
+     *
+     * @param vars the Map of environment variable names to values
+     * @return the {@code JavaShellToolBuilder} instance
+     */
+    @Override
+    public JavaShellToolBuilder env(Map<String, String> vars) {
+        this.vars = vars;
+        return this;
+    }
+
+    /**
+     * Set the locale.
+     * Default, if not set, {@code locale(Locale.getDefault())}.
+     *
+     * @param locale the locale
+     * @return the {@code JavaShellToolBuilder} instance
+     */
+    @Override
+    public JavaShellToolBuilder locale(Locale locale) {
+        this.locale = locale;
+        return this;
+    }
+
+    /**
+     * Set if the special command capturing prompt override should be used.
+     * Default, if not set, {@code promptCapture(false)}.
+     *
+     * @param capture if {@code true}, basic prompt is the {@code ENQ}
+     * character and continuation prompt is the {@code ACK} character.
+     * If false, prompts are as set with set-up or user {@code /set} commands.
+     * @return the {@code JavaShellToolBuilder} instance
+     */
+    @Override
+    public JavaShellToolBuilder promptCapture(boolean capture) {
+        this.capturePrompt = capture;
+        return this;
+    }
+
+    /**
+     * Create a tool instance for testing. Not in JavaShellToolBuilder.
+     *
+     * @return the tool instance
+     */
+    public JShellTool rawTool() {
+        if (prefs == null) {
+            prefs = new PreferencesStorage(Preferences.userRoot().node(PREFERENCES_NODE));
+        }
+        if (vars == null) {
+            vars = System.getenv();
+        }
+        JShellTool sh = new JShellTool(cmdIn, cmdOut, cmdErr, console, userIn,
+                userOut, userErr, prefs, vars, locale);
+        sh.testPrompt = capturePrompt;
+        return sh;
+    }
+
+    /**
+     * Run an instance of the Java shell tool as configured by the other methods
+     * in this interface.  This call is not destructive, more than one call of
+     * this method may be made from a configured builder.
+     *
+     * @param arguments the command-line arguments (including options), if any
+     * @throws Exception an unexpected fatal exception
+     */
+    @Override
+    public void run(String... arguments) throws Exception {
+        rawTool().start(arguments);
+    }
+
+    /**
+     * Persistence stored in Preferences.
+     */
+    private static class PreferencesStorage implements PersistentStorage {
+
+        final Preferences p;
+
+        PreferencesStorage(Preferences p) {
+            this.p = p;
+        }
+
+        @Override
+        public void clear() {
+            try {
+                p.clear();
+            } catch (BackingStoreException ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+
+        @Override
+        public String[] keys() {
+            try {
+                return p.keys();
+            } catch (BackingStoreException ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+
+        @Override
+        public String get(String key) {
+            return p.get(key, null);
+        }
+
+        @Override
+        public void put(String key, String value) {
+            p.put(key, value);
+        }
+
+        @Override
+        public void remove(String key) {
+            p.remove(key);
+        }
+
+        @Override
+        public void flush() {
+            try {
+                p.flush();
+            } catch (BackingStoreException ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+    }
+
+    /**
+     * Persistence stored in a Map.
+     */
+    private static class MapStorage implements PersistentStorage {
+
+        final Map<String, String> map;
+
+        MapStorage(Map<String, String> map) {
+            this.map = map;
+        }
+
+        @Override
+        public void clear() {
+
+            try {
+                map.clear();
+            } catch (UnsupportedOperationException ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+
+        @Override
+        public String[] keys() {
+            Set<String> ks = map.keySet();
+            return ks.toArray(new String[ks.size()]);
+        }
+
+        @Override
+        public String get(String key) {
+            Objects.requireNonNull(key);
+            return map.get(key);
+        }
+
+        @Override
+        public void put(String key, String value) {
+            Objects.requireNonNull(key);
+            Objects.requireNonNull(value);
+            map.put(key, value);
+        }
+
+        @Override
+        public void remove(String key) {
+            Objects.requireNonNull(key);
+            map.remove(key);
+        }
+
+        @Override
+        public void flush() {
+            // no-op always up-to-date
+        }
+    }
+
+}