1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.tools.jjs; 27 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.io.PrintStream; 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.Collections; 34 import java.util.Iterator; 35 import java.util.List; 36 import java.util.prefs.BackingStoreException; 37 import java.util.prefs.Preferences; 38 import jdk.internal.jline.console.ConsoleReader; 39 import jdk.internal.jline.console.completer.Completer; 40 import jdk.internal.jline.console.history.History.Entry; 41 import jdk.internal.jline.console.history.MemoryHistory; 42 43 class Console implements AutoCloseable { 44 private final ConsoleReader in; 45 private final PersistentHistory history; 46 47 Console(final InputStream cmdin, final PrintStream cmdout, final Preferences prefs, 48 final Completer completer) throws IOException { 49 in = new ConsoleReader(cmdin, cmdout); 50 in.setExpandEvents(false); 51 in.setHandleUserInterrupt(true); 52 in.setBellEnabled(true); 53 in.setHistory(history = new PersistentHistory(prefs)); 54 in.addCompleter(completer); 55 Runtime.getRuntime().addShutdownHook(new Thread(()->close())); 56 } 57 58 String readLine(final String prompt) throws IOException { 59 return in.readLine(prompt); 60 } 61 62 63 @Override 64 public void close() { 65 history.save(); 66 } 67 68 public static class PersistentHistory extends MemoryHistory { 69 70 private final Preferences prefs; 71 72 protected PersistentHistory(final Preferences prefs) { 73 this.prefs = prefs; 74 load(); 75 } 76 77 private static final String HISTORY_LINE_PREFIX = "HISTORY_LINE_"; 78 79 public final void load() { 80 try { 81 final List<String> keys = new ArrayList<>(Arrays.asList(prefs.keys())); 82 Collections.sort(keys); 83 for (String key : keys) { 84 if (!key.startsWith(HISTORY_LINE_PREFIX)) 85 continue; 86 CharSequence line = prefs.get(key, ""); 87 add(line); 88 } 89 } catch (BackingStoreException ex) { 90 throw new IllegalStateException(ex); 91 } 92 } 93 94 public void save() { 95 Iterator<Entry> entries = iterator(); 96 if (entries.hasNext()) { 97 int len = (int) Math.ceil(Math.log10(size()+1)); 98 String format = HISTORY_LINE_PREFIX + "%0" + len + "d"; 99 while (entries.hasNext()) { 100 Entry entry = entries.next(); 101 prefs.put(String.format(format, entry.index()), entry.value().toString()); 102 } 103 } 104 } 105 106 } 107 }