src/sample/nashorn/autoimports.js
changeset 47216 71c04702a3d5
parent 31096 a3a697c1edd5
child 47286 cd02250e9370
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     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 it is easier
       
    36  * use simple names of java classes and have a script auto import Java classes. 
       
    37  * You can load this script at the start of an interactive jjs session or at the
       
    38  * start of your script. This script defines a __noSuchProperty__ hook to auto 
       
    39  * import Java classes as needed and when they are referred to for the first time
       
    40  * in your script. You can also call the "autoimports" function to print script 
       
    41  * statements that you need to use in your script, i.e., have the function generate
       
    42  * a script to import Java classes used by your script so far. After running your
       
    43  * script, you can call autoimports to get the exact Java imports you need and replace
       
    44  * the autoimports load with the generated import statements (to avoid costly init of
       
    45  * the autoimports script).
       
    46  */
       
    47 
       
    48 (function() {
       
    49     var ArrayList = Java.type("java.util.ArrayList");
       
    50     var HashMap = Java.type("java.util.HashMap");
       
    51     var Files = Java.type("java.nio.file.Files");
       
    52     var FileSystems = Java.type("java.nio.file.FileSystems");
       
    53     var URI = Java.type("java.net.URI");
       
    54 
       
    55     // initialize a class to package map by iterating all
       
    56     // classes available in the system by walking through "jrt fs"
       
    57     var fs = FileSystems.getFileSystem(URI.create("jrt:/"));
       
    58     var root = fs.getPath('/');
       
    59 
       
    60     var clsToPkg = new HashMap();
       
    61 
       
    62     function addToClsToPkg(c, p) {
       
    63         if (clsToPkg.containsKey(c)) {
       
    64             var val = clsToPkg.get(c);
       
    65             if (val instanceof ArrayList) {
       
    66                 val.add(p);
       
    67             } else {
       
    68                 var al = new ArrayList();
       
    69                 al.add(val);
       
    70                 al.add(p);
       
    71                 clsToPkg.put(c, al);
       
    72             }
       
    73         } else {
       
    74             clsToPkg.put(c, p);
       
    75         }
       
    76     }
       
    77 
       
    78     // handle collision and allow user to choose package
       
    79     function getPkgOfCls(c) {
       
    80         var val = clsToPkg.get(c);
       
    81         if (val instanceof ArrayList) {
       
    82             var count = 1;
       
    83             print("Multiple matches for " + c + ", choose package:");
       
    84             for each (var v in val) {
       
    85                 print(count + ". " + v);
       
    86                 count++;
       
    87             }
       
    88             var choice = parseInt(readLine());
       
    89             if (isNaN(choice) || choice < 1 || choice > val.size()) {
       
    90                 print("invalid choice: " + choice);
       
    91                 return undefined;
       
    92             }
       
    93             return val.get(choice - 1);
       
    94         } else {
       
    95             return val;
       
    96         }
       
    97     }
       
    98 
       
    99     Files.walk(root).forEach(function(p) {
       
   100         if (Files.isRegularFile(p)) {
       
   101             var str = p.toString();
       
   102             if (str.endsWith(".class")) {
       
   103                 str = str.substring(1);
       
   104                 var idx = str.indexOf('/');
       
   105                 if (idx != -1) {
       
   106                     str = str.substring(idx + 1);
       
   107                     if (str.startsWith("java") ||
       
   108                         str.startsWith("javax") ||
       
   109                         str.startsWith("org")) {
       
   110                         var lastIdx = str.lastIndexOf('/');
       
   111                         if (lastIdx != -1) {
       
   112                             var pkg = str.substring(0, lastIdx).replaceAll('/', '.');
       
   113                             var cls = str.substring(lastIdx + 1, str.lastIndexOf(".class"));
       
   114                             addToClsToPkg(cls, pkg);
       
   115                         }
       
   116                     }
       
   117                 }
       
   118             }
       
   119         } 
       
   120     });
       
   121 
       
   122     var imports = new ArrayList();
       
   123     var global = this;
       
   124     var oldNoSuchProp = global.__noSuchProperty__;
       
   125     this.__noSuchProperty__ = function(name) {
       
   126         'use strict';
       
   127 
       
   128         if (clsToPkg.containsKey(name)) {
       
   129             var pkg = getPkgOfCls(name);
       
   130             if (pkg) {
       
   131                 var clsName = pkg + "." + name;
       
   132                 imports.add("var " + name + " = Java.type('" + clsName + "');");
       
   133                 return global[name] = Java.type(clsName);
       
   134             }
       
   135         } else if (typeof oldNoSuchProp == 'function') {
       
   136             return oldNoSuchProp.call(this, name);
       
   137         }
       
   138 
       
   139         if (typeof this == 'undefined') {
       
   140             throw new ReferenceError(name);
       
   141         } else {
       
   142             return undefined;
       
   143         }
       
   144     }
       
   145 
       
   146     this.autoimports = function() {
       
   147         for each (var im in imports) {
       
   148             print(im);
       
   149         }
       
   150     }
       
   151 })();