samples/getclassnpe.js

Fri, 05 Jun 2015 12:38:53 +0200

author
mhaupt
date
Fri, 05 Jun 2015 12:38:53 +0200
changeset 1398
2f1b9f4daec1
parent 1232
09bd5b8abcba
permissions
-rw-r--r--

8080087: Nashorn $ENV.PWD is originally undefined
Summary: On Windows, the PWD environment variable does not exist and cannot be imported in scripting mode, so it is set explicitly.
Reviewed-by: lagergren, sundar

     1 #// Usage: jjs getclassnpe.js -- <directory>
     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  */
    34 /*
    35  * java.lang.Object.getClass() is sometimes used to do null check. This
    36  * obfuscating Object.getClass() check relies on non-related intrinsic
    37  * performance, which is potentially not available everywhere.
    38  * See also http://cr.openjdk.java.net/~shade/scratch/NullChecks.java
    39  * This nashorn script checks for such uses in your .java files in the
    40  * given directory (recursively).
    41  */
    43 if (arguments.length == 0) {
    44     print("Usage: jjs getclassnpe.js -- <directory>");
    45     exit(1);
    46 }
    48 // Java types used
    49 var File = Java.type("java.io.File");
    50 var Files = Java.type("java.nio.file.Files");
    51 var StringArray = Java.type("java.lang.String[]");
    52 var ToolProvider = Java.type("javax.tools.ToolProvider");
    53 var MethodInvocationTree = Java.type("com.sun.source.tree.MethodInvocationTree");
    54 var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
    56 // parse a specific .java file to check if it uses
    57 // Object.getClass() for null check.
    58 function checkGetClassNPE() {
    59     // get the system compiler tool
    60     var compiler = ToolProvider.systemJavaCompiler;
    61     // get standard file manager
    62     var fileMgr = compiler.getStandardFileManager(null, null, null);
    63     // Using Java.to convert script array (arguments) to a Java String[]
    64     var compUnits = fileMgr.getJavaFileObjects(
    65         Java.to(arguments, StringArray));
    66     // create a new compilation task
    67     var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
    68     // subclass SimpleTreeVisitor - to check for obj.getClass(); statements
    69     var GetClassNPEChecker = Java.extend(TreeScanner);
    71     var visitor = new GetClassNPEChecker() {
    72         lineMap: null,
    73         sourceFile: null,
    75         // save compilation unit details for reporting
    76         visitCompilationUnit: function(node, p) {
    77            this.sourceFile = node.sourceFile;
    78            this.lineMap = node.lineMap;
    79            return Java.super(visitor).visitCompilationUnit(node, p);
    80         },
    82         // look for "foo.getClass();" expression statements
    83         visitExpressionStatement: function(node, p) {
    84             var expr = node.expression;
    85             if (expr instanceof MethodInvocationTree) {
    86                 var name = String(expr.methodSelect.identifier);
    88                 // will match any "getClass" call with zero arguments!
    89                 if (name == "getClass" && expr.arguments.size() == 0) {
    90                     print(this.sourceFile.getName()
    91                      + " @ "
    92                      + this.lineMap.getLineNumber(node.pos)
    93                      + ":"
    94                      + this.lineMap.getColumnNumber(node.pos));
    96                     print("\t", node);
    97                 }
    98             }
    99         }
   100     }
   102     for each (var cu in task.parse()) {
   103         cu.accept(visitor, null);
   104     }
   105 }
   107 // for each ".java" file in the directory (recursively)
   108 function main(dir) {
   109     Files.walk(dir.toPath()).
   110       forEach(function(p) {
   111           var name = p.toFile().absolutePath;
   112           if (name.endsWith(".java")) {
   113               try {
   114                   checkGetClassNPE(p.toFile().getAbsolutePath());
   115               } catch (e) {
   116                   print(e);
   117               }
   118           }
   119       });
   120 }
   122 main(new File(arguments[0]));

mercurial