| # autoimports script requires -scripting mode |
| |
| /* |
| * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * - Neither the name of Oracle nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* |
| * It is tedious to import Java classes used in a script. Sometimes it is easier |
| * use simple names of java classes and have a script auto import Java classes. |
| * You can load this script at the start of an interactive jjs session or at the |
| * start of your script. This script defines a __noSuchProperty__ hook to auto |
| * import Java classes as needed and when they are referred to for the first time |
| * in your script. You can also call the "autoimports" function to print script |
| * statements that you need to use in your script, i.e., have the function generate |
| * a script to import Java classes used by your script so far. After running your |
| * script, you can call autoimports to get the exact Java imports you need and replace |
| * the autoimports load with the generated import statements (to avoid costly init of |
| * the autoimports script). |
| */ |
| |
| (function() { |
| var ArrayList = Java.type("java.util.ArrayList"); |
| var HashMap = Java.type("java.util.HashMap"); |
| var JarFile = Java.type("java.util.jar.JarFile"); |
| var File = Java.type("java.io.File"); |
| var Files = Java.type("java.nio.file.Files"); |
| var FileSystems = Java.type("java.nio.file.FileSystems"); |
| var System = Java.type("java.lang.System"); |
| var URI = Java.type("java.net.URI"); |
| |
| // initialize a class to package map by iterating all |
| // classes available in the system by walking through "jrt fs" |
| |
| var clsToPkg = new HashMap(); |
| |
| // locate rt.jar from sun.boot.class.path |
| function findRtJar() { |
| var paths = System.getProperty("sun.boot.class.path").split(File.pathSeparator); |
| for each (var p in paths) { |
| if (p.endsWith("rt.jar") && new File(p).exists()) { |
| return p; |
| } |
| } |
| } |
| |
| |
| function addToClsToPkg(c, p) { |
| if (clsToPkg.containsKey(c)) { |
| var val = clsToPkg.get(c); |
| if (val instanceof ArrayList) { |
| val.add(p); |
| } else { |
| var al = new ArrayList(); |
| al.add(val); |
| al.add(p); |
| clsToPkg.put(c, al); |
| } |
| } else { |
| clsToPkg.put(c, p); |
| } |
| } |
| |
| // handle collision and allow user to choose package |
| function getPkgOfCls(c) { |
| var val = clsToPkg.get(c); |
| if (val instanceof ArrayList) { |
| var count = 1; |
| print("Multiple matches for " + c + ", choose package:"); |
| for each (var v in val) { |
| print(count + ". " + v); |
| count++; |
| } |
| var choice = parseInt(readLine()); |
| if (isNaN(choice) || choice < 1 || choice > val.size()) { |
| print("invalid choice: " + choice); |
| return undefined; |
| } |
| return val.get(choice - 1); |
| } else { |
| return val; |
| } |
| } |
| |
| var rtJar = findRtJar(); |
| var stream = new JarFile(rtJar).stream(); |
| try { |
| stream.forEach( |
| function(entry) { |
| var str = entry.name; |
| if (str.endsWith(".class")) { |
| if (str.startsWith("java") || |
| str.startsWith("javax") || |
| str.startsWith("org")) { |
| var lastIdx = str.lastIndexOf('/'); |
| if (lastIdx != -1) { |
| var pkg = str.substring(0, lastIdx).replaceAll('/', '.'); |
| var cls = str.substring(lastIdx + 1, str.lastIndexOf(".class")); |
| addToClsToPkg(cls, pkg); |
| } |
| } |
| } |
| }); |
| } finally { |
| stream.close(); |
| } |
| |
| var imports = new ArrayList(); |
| var global = this; |
| var oldNoSuchProp = global.__noSuchProperty__; |
| this.__noSuchProperty__ = function(name) { |
| 'use strict'; |
| |
| if (clsToPkg.containsKey(name)) { |
| var pkg = getPkgOfCls(name); |
| if (pkg) { |
| var clsName = pkg + "." + name; |
| imports.add("var " + name + " = Java.type('" + clsName + "');"); |
| return global[name] = Java.type(clsName); |
| } |
| } else if (typeof oldNoSuchProp == 'function') { |
| return oldNoSuchProp.call(this, name); |
| } |
| |
| if (typeof this == 'undefined') { |
| throw new ReferenceError(name); |
| } else { |
| return undefined; |
| } |
| } |
| |
| this.autoimports = function() { |
| for each (var im in imports) { |
| print(im); |
| } |
| } |
| })(); |