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(InputStream cmdin, PrintStream cmdout, Preferences prefs, Completer completer) throws IOException { 48 in = new ConsoleReader(cmdin, cmdout); 49 in.setExpandEvents(false); 50 in.setHandleUserInterrupt(true); 51 in.setBellEnabled(true); 52 in.setHistory(history = new PersistentHistory(prefs)); 53 in.addCompleter(completer); 54 Runtime.getRuntime().addShutdownHook(new Thread(()->close())); 55 } 56 57 String readLine(String prompt) throws IOException { 58 return in.readLine(prompt); 59 } 60 61 62 @Override 63 public void close() { 64 history.save(); 65 } 66 67 public static class PersistentHistory extends MemoryHistory { 68 69 private final Preferences prefs; 70 71 protected PersistentHistory(Preferences prefs) { 72 this.prefs = prefs; 73 load(); 74 } 75 76 private static final String HISTORY_LINE_PREFIX = "HISTORY_LINE_"; 77 78 public final void load() { 79 try { 80 List<String> keys = new ArrayList<>(Arrays.asList(prefs.keys())); 81 Collections.sort(keys); 82 for (String key : keys) { 83 if (!key.startsWith(HISTORY_LINE_PREFIX)) 84 continue; 85 CharSequence line = prefs.get(key, ""); 86 add(line); 87 } 88 } catch (BackingStoreException ex) { 89 throw new IllegalStateException(ex); 90 } 91 } 92 93 public void save() { 94 Iterator<Entry> entries = iterator(); 95 if (entries.hasNext()) { 96 int len = (int) Math.ceil(Math.log10(size()+1)); 97 String format = HISTORY_LINE_PREFIX + "%0" + len + "d"; 98 while (entries.hasNext()) { 99 Entry entry = entries.next(); 100 prefs.put(String.format(format, entry.index()), entry.value().toString()); 101 } 102 } 103 } 104 105 } 106 }