1 # autoimports script requires -scripting mode 2 3 /* 4 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * - Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * - Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * - Neither the name of Oracle nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /** 35 * It is tedious to import Java classes used in a script. Sometimes 36 * it is easier use simple names of java classes and have a script 37 * auto import Java classes. You can load this script at the statt of 38 * interactive jjs session or at the start of your script. This script 39 * defines a __noSuchProperty__ hook to auto import Java classes as 40 * and when referred first time in your script. You can also call 41 * "autoimports" function to print script statements that you need to 42 * use in your script. i.e., generates script to import Java classes 43 * used by your script so far. After running your script, you can call 44 * autoimports to get exact java imports you need and replace autoimports 45 * load with the generated import statements (to avoid costly init of 46 * this autoimports script). 47 */ 48 49 (function() { 50 var ArrayList = Java.type("java.util.ArrayList"); 51 var HashMap = Java.type("java.util.HashMap"); 52 var Files = Java.type("java.nio.file.Files"); 53 var FileSystems = Java.type("java.nio.file.FileSystems"); 54 var URI = Java.type("java.net.URI"); 55 56 // initialize a class to package map by iterating all 57 // classes available in the system by walking through "jrt fs" 58 var fs = FileSystems.getFileSystem(URI.create("jrt:/")); 59 var root = fs.getPath('/'); 60 61 var clsToPkg = new HashMap(); 62 63 function addToClsToPkg(c, p) { 64 if (clsToPkg.containsKey(c)) { 65 var val = clsToPkg.get(c); 66 if (val instanceof ArrayList) { 67 val.add(p); 68 } else { 69 var al = new ArrayList(); 70 al.add(val); 71 al.add(p); 72 clsToPkg.put(c, al); 73 } 74 } else { 75 clsToPkg.put(c, p); 76 } 77 } 78 79 // handle collision and allow user to choose package 80 function getPkgOfCls(c) { 81 var val = clsToPkg.get(c); 82 if (val instanceof ArrayList) { 83 var count = 1; 84 print("Multiple matches for " + c + ", choose package:"); 85 for each (var v in val) { 86 print(count + ". " + v); 87 count++; 88 } 89 var choice = parseInt(readLine()); 90 if (isNaN(choice) || choice < 1 || choice > val.size()) { 91 print("invalid choice: " + choice); 92 return undefined; 93 } 94 return val.get(choice - 1); 95 } else { 96 return val; 97 } 98 } 99 100 Files.walk(root).forEach(function(p) { 101 if (Files.isRegularFile(p)) { 102 var str = p.toString(); 103 if (str.endsWith(".class")) { 104 str = str.substring(1); 105 var idx = str.indexOf('/'); 106 if (idx != -1) { 107 str = str.substring(idx + 1); 108 if (str.startsWith("java") || 109 str.startsWith("javax") || 110 str.startsWith("org")) { 111 var lastIdx = str.lastIndexOf('/'); 112 if (lastIdx != -1) { 113 var pkg = str.substring(0, lastIdx).replaceAll('/', '.'); 114 var cls = str.substring(lastIdx + 1, str.lastIndexOf(".class")); 115 addToClsToPkg(cls, pkg); 116 } 117 } 118 } 119 } 120 } 121 }); 122 123 var imports = new ArrayList(); 124 var global = this; 125 var oldNoSuchProp = global.__noSuchProperty__; 126 this.__noSuchProperty__ = function(name) { 127 'use strict'; 128 129 if (clsToPkg.containsKey(name)) { 130 var pkg = getPkgOfCls(name); 131 if (pkg) { 132 var clsName = pkg + "." + name; 133 imports.add("var " + name + " = Java.type('" + clsName + "');"); 134 return global[name] = Java.type(clsName); 135 } 136 } else if (typeof oldNoSuchProp == 'function') { 137 return oldNoSuchProp.call(this, name); 138 } 139 140 if (typeof this == 'undefined') { 141 throw new ReferenceError(name); 142 } else { 143 return undefined; 144 } 145 } 146 147 this.autoimports = function() { 148 for each (var im in imports) { 149 print(im); 150 } 151 } 152 })();