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.util.Collections; 30 import java.util.HashSet; 31 import java.util.Set; 32 import java.util.function.Function; 33 import java.util.function.Supplier; 34 import jdk.internal.jline.console.history.FileHistory; 35 import jdk.internal.jline.console.history.History; 36 import jdk.nashorn.api.scripting.AbstractJSObject; 37 import jdk.nashorn.api.scripting.JSObject; 38 import jdk.nashorn.internal.runtime.JSType; 39 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 40 41 /* 42 * A script friendly object that exposes history of commands to scripts. 43 */ 44 final class HistoryObject extends AbstractJSObject { 45 private static final Set<String> props; 46 static { 47 final HashSet<String> s = new HashSet<>(); 48 s.add("clear"); 49 s.add("forEach"); 50 s.add("print"); 51 s.add("size"); 52 s.add("toString"); 53 props = Collections.unmodifiableSet(s); 54 } 55 56 private final FileHistory hist; 57 58 HistoryObject(final FileHistory hist) { 59 this.hist = hist; 60 } 61 62 @Override 63 public Object getMember(final String name) { 64 switch (name) { 65 case "clear": 66 return (Runnable)hist::clear; 67 case "forEach": 68 return (Function<JSObject, Object>)this::iterate; 69 case "print": 70 return (Runnable)this::print; 71 case "size": 72 return hist.size(); 73 case "toString": 74 return (Supplier<String>)this::toString; 75 } 76 return UNDEFINED; 77 } 78 79 @Override 80 public Object getDefaultValue(final Class<?> hint) { 81 if (hint == String.class) { 82 return toString(); 83 } 84 return UNDEFINED; 85 } 86 87 @Override 88 public String toString() { 89 final StringBuilder buf = new StringBuilder(); 90 for (History.Entry e : hist) { 91 buf.append(e.value()).append('\n'); 92 } 93 return buf.toString(); 94 } 95 96 @Override 97 public Set<String> keySet() { 98 return props; 99 } 100 101 private void print() { 102 for (History.Entry e : hist) { 103 System.out.println(e.value()); 104 } 105 } 106 107 private Object iterate(final JSObject func) { 108 for (History.Entry e : hist) { 109 if (JSType.toBoolean(func.call(this, e.value().toString()))) { 110 break; // return true from callback to skip iteration 111 } 112 } 113 return UNDEFINED; 114 } 115 } | 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.BufferedReader; 29 import java.io.File; 30 import java.io.FileReader; 31 import java.io.IOException; 32 import java.io.PrintWriter; 33 import java.util.Collections; 34 import java.util.HashSet; 35 import java.util.Set; 36 import java.util.function.Consumer; 37 import java.util.function.Function; 38 import java.util.function.Supplier; 39 import jdk.internal.jline.console.history.FileHistory; 40 import jdk.internal.jline.console.history.History; 41 import jdk.nashorn.api.scripting.AbstractJSObject; 42 import jdk.nashorn.api.scripting.JSObject; 43 import jdk.nashorn.internal.runtime.JSType; 44 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 45 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 46 47 /* 48 * A script friendly object that exposes history of commands to scripts. 49 */ 50 final class HistoryObject extends AbstractJSObject { 51 private static final Set<String> props; 52 static { 53 final HashSet<String> s = new HashSet<>(); 54 s.add("clear"); 55 s.add("forEach"); 56 s.add("load"); 57 s.add("print"); 58 s.add("save"); 59 s.add("size"); 60 s.add("toString"); 61 props = Collections.unmodifiableSet(s); 62 } 63 64 private final FileHistory hist; 65 private final PrintWriter err; 66 private final Consumer<String> evaluator; 67 68 HistoryObject(final FileHistory hist, final PrintWriter err, 69 final Consumer<String> evaluator) { 70 this.hist = hist; 71 this.err = err; 72 this.evaluator = evaluator; 73 } 74 75 @Override 76 public boolean isFunction() { 77 return true; 78 } 79 80 @Override 81 public Object call(final Object thiz, final Object... args) { 82 if (args.length > 0) { 83 int index = JSType.toInteger(args[0]); 84 if (index < 0) { 85 index += (hist.size() - 1); 86 } else { 87 index--; 88 } 89 90 if (index >= 0 && index < (hist.size() - 1)) { 91 final CharSequence src = hist.get(index); 92 hist.replace(src); 93 err.println(src); 94 evaluator.accept(src.toString()); 95 } else { 96 hist.removeLast(); 97 err.println("no history entry @ " + (index + 1)); 98 } 99 } 100 return UNDEFINED; 101 } 102 103 @Override 104 public Object getMember(final String name) { 105 switch (name) { 106 case "clear": 107 return (Runnable)hist::clear; 108 case "forEach": 109 return (Function<JSObject, Object>)this::iterate; 110 case "load": 111 return (Consumer<Object>)this::load; 112 case "print": 113 return (Runnable)this::print; 114 case "save": 115 return (Consumer<Object>)this::save; 116 case "size": 117 return hist.size(); 118 case "toString": 119 return (Supplier<String>)this::toString; 120 } 121 return UNDEFINED; 122 } 123 124 @Override 125 public Object getDefaultValue(final Class<?> hint) { 126 if (hint == String.class) { 127 return toString(); 128 } 129 return UNDEFINED; 130 } 131 132 @Override 133 public String toString() { 134 final StringBuilder buf = new StringBuilder(); 135 for (History.Entry e : hist) { 136 buf.append(e.value()).append('\n'); 137 } 138 return buf.toString(); 139 } 140 141 @Override 142 public Set<String> keySet() { 143 return props; 144 } 145 146 private void save(final Object obj) { 147 final File file = getFile(obj); 148 try (final PrintWriter pw = new PrintWriter(file)) { 149 for (History.Entry e : hist) { 150 pw.println(e.value()); 151 } 152 } catch (final IOException exp) { 153 throw new RuntimeException(exp); 154 } 155 } 156 157 private void load(final Object obj) { 158 final File file = getFile(obj); 159 String item = null; 160 try (final BufferedReader r = new BufferedReader(new FileReader(file))) { 161 while ((item = r.readLine()) != null) { 162 hist.add(item); 163 } 164 } catch (final IOException exp) { 165 throw new RuntimeException(exp); 166 } 167 } 168 169 private void print() { 170 for (History.Entry e : hist) { 171 System.out.printf("%3d %s\n", e.index() + 1, e.value()); 172 } 173 } 174 175 private Object iterate(final JSObject func) { 176 for (History.Entry e : hist) { 177 if (JSType.toBoolean(func.call(this, e.value().toString()))) { 178 break; // return true from callback to skip iteration 179 } 180 } 181 return UNDEFINED; 182 } 183 184 private static File getFile(final Object obj) { 185 File file = null; 186 if (obj instanceof String) { 187 file = new File((String)obj); 188 } else if (obj instanceof File) { 189 file = (File)obj; 190 } else { 191 throw typeError("not.a.file", JSType.toString(obj)); 192 } 193 194 return file; 195 } 196 } |