test/tools/javac/T8003967/DetectMutableStaticFields.java

Mon, 10 Dec 2012 16:21:26 +0000

author
vromero
date
Mon, 10 Dec 2012 16:21:26 +0000
changeset 1442
fcf89720ae71
parent 0
959103a6100f
permissions
-rw-r--r--

8003967: detect and remove all mutable implicit static enum fields in langtools
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     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  */
    26 /*
    27  * @test
    28  * @bug 8003967
    29  * @summary detect and remove all mutable implicit static enum fields in langtools
    30  * @run main DetectMutableStaticFields
    31  */
    33 import java.io.File;
    34 import java.io.IOException;
    35 import java.net.URI;
    36 import java.net.URISyntaxException;
    37 import java.util.ArrayList;
    38 import java.util.Arrays;
    39 import java.util.EnumSet;
    40 import java.util.HashMap;
    41 import java.util.List;
    42 import java.util.Map;
    43 import javax.tools.JavaCompiler;
    44 import javax.tools.JavaFileManager;
    45 import javax.tools.JavaFileObject;
    46 import javax.tools.StandardJavaFileManager;
    47 import javax.tools.StandardLocation;
    48 import javax.tools.ToolProvider;
    49 import com.sun.tools.classfile.ClassFile;
    50 import com.sun.tools.classfile.ConstantPoolException;
    51 import com.sun.tools.classfile.Descriptor;
    52 import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
    53 import com.sun.tools.classfile.Field;
    55 import static javax.tools.JavaFileObject.Kind.CLASS;
    56 import static com.sun.tools.classfile.AccessFlags.ACC_ENUM;
    57 import static com.sun.tools.classfile.AccessFlags.ACC_FINAL;
    58 import static com.sun.tools.classfile.AccessFlags.ACC_STATIC;
    60 public class DetectMutableStaticFields {
    62     private static final String keyResource =
    63             "com/sun/tools/javac/tree/JCTree.class";
    65     private String[] packagesToSeekFor = new String[] {
    66         "javax.tools",
    67         "javax.lang.model",
    68         "com.sun.javadoc",
    69         "com.sun.source",
    70         "com.sun.tools.classfile",
    71         "com.sun.tools.doclets",
    72         "com.sun.tools.javac",
    73         "com.sun.tools.javadoc",
    74         "com.sun.tools.javah",
    75         "com.sun.tools.javap",
    76     };
    78     private static final Map<String, List<String>> classFieldsToIgnoreMap = new HashMap<>();
    80     static {
    81         classFieldsToIgnoreMap.
    82                 put("javax/tools/ToolProvider",
    83                     Arrays.asList("instance"));
    84         classFieldsToIgnoreMap.
    85                 put("com/sun/tools/javah/JavahTask",
    86                     Arrays.asList("versionRB"));
    87         classFieldsToIgnoreMap.
    88                 put("com/sun/tools/classfile/Dependencies$DefaultFilter",
    89                     Arrays.asList("instance"));
    90         classFieldsToIgnoreMap.
    91                 put("com/sun/tools/javap/JavapTask",
    92                     Arrays.asList("versionRB"));
    93         classFieldsToIgnoreMap.
    94                 put("com/sun/tools/doclets/formats/html/HtmlDoclet",
    95                     Arrays.asList("docletToStart"));
    96         classFieldsToIgnoreMap.
    97                 put("com/sun/tools/javac/util/JCDiagnostic",
    98                     Arrays.asList("fragmentFormatter"));
    99         classFieldsToIgnoreMap.
   100                 put("com/sun/tools/javac/util/JavacMessages",
   101                     Arrays.asList("defaultBundle", "defaultMessages"));
   102         classFieldsToIgnoreMap.
   103                 put("com/sun/tools/javac/file/ZipFileIndexCache",
   104                     Arrays.asList("sharedInstance"));
   105         classFieldsToIgnoreMap.
   106                 put("com/sun/tools/javac/main/JavaCompiler",
   107                     Arrays.asList("versionRB"));
   108         classFieldsToIgnoreMap.
   109                 put("com/sun/tools/javac/code/Type",
   110                     Arrays.asList("moreInfo"));
   111         classFieldsToIgnoreMap.
   112                 put("com/sun/tools/javac/util/SharedNameTable",
   113                     Arrays.asList("freelist"));
   114         classFieldsToIgnoreMap.
   115                 put("com/sun/tools/javac/util/Log",
   116                     Arrays.asList("useRawMessages"));
   117     }
   119     private List<String> errors = new ArrayList<>();
   121     public static void main(String[] args) {
   122         try {
   123             new DetectMutableStaticFields().run();
   124         } catch (Exception ex) {
   125             throw new AssertionError(
   126                     "Exception during test execution with cause ",
   127                     ex.getCause());
   128         }
   129     }
   131     private void run()
   132         throws
   133             IOException,
   134             ConstantPoolException,
   135             InvalidDescriptor,
   136             URISyntaxException {
   138         URI resource = findResource(keyResource);
   139         if (resource == null) {
   140             throw new AssertionError("Resource " + keyResource +
   141                 "not found in the class path");
   142         }
   143         analyzeResource(resource);
   145         if (errors.size() > 0) {
   146             for (String error: errors) {
   147                 System.err.println(error);
   148             }
   149             throw new AssertionError("There are mutable fields, "
   150                 + "please check output");
   151         }
   152     }
   154     URI findResource(String className) throws URISyntaxException {
   155         URI uri = getClass().getClassLoader().getResource(className).toURI();
   156         if (uri.getScheme().equals("jar")) {
   157             String ssp = uri.getRawSchemeSpecificPart();
   158             int sep = ssp.lastIndexOf("!");
   159             uri = new URI(ssp.substring(0, sep));
   160         } else if (uri.getScheme().equals("file")) {
   161             uri = new URI(uri.getPath().substring(0,
   162                     uri.getPath().length() - keyResource.length()));
   163         }
   164         return uri;
   165     }
   167     boolean shouldAnalyzePackage(String packageName) {
   168         for (String aPackage: packagesToSeekFor) {
   169             if (packageName.contains(aPackage)) {
   170                 return true;
   171             }
   172         }
   173         return false;
   174     }
   176     void analyzeResource(URI resource)
   177         throws
   178             IOException,
   179             ConstantPoolException,
   180             InvalidDescriptor {
   181         JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
   182         StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
   183         JavaFileManager.Location location =
   184                 StandardLocation.locationFor(resource.getPath());
   185         fm.setLocation(location, com.sun.tools.javac.util.List.of(
   186                 new File(resource.getPath())));
   188         for (JavaFileObject file : fm.list(location, "", EnumSet.of(CLASS), true)) {
   189             String className = fm.inferBinaryName(location, file);
   190             int index = className.lastIndexOf('.');
   191             String pckName = index == -1 ? "" : className.substring(0, index);
   192             if (shouldAnalyzePackage(pckName)) {
   193                 analyzeClassFile(ClassFile.read(file.openInputStream()));
   194             }
   195         }
   196     }
   198     List<String> currentFieldsToIgnore;
   200     boolean ignoreField(String field) {
   201         if (currentFieldsToIgnore != null) {
   202             for (String fieldToIgnore : currentFieldsToIgnore) {
   203                 if (field.equals(fieldToIgnore)) {
   204                     return true;
   205                 }
   206             }
   207         }
   208         return false;
   209     }
   211     void analyzeClassFile(ClassFile classFileToCheck)
   212         throws
   213             IOException,
   214             ConstantPoolException,
   215             Descriptor.InvalidDescriptor {
   216         boolean enumClass =
   217                 (classFileToCheck.access_flags.flags & ACC_ENUM) != 0;
   218         boolean nonFinalStaticEnumField;
   219         boolean nonFinalStaticField;
   221         currentFieldsToIgnore =
   222                 classFieldsToIgnoreMap.get(classFileToCheck.getName());
   224         for (Field field : classFileToCheck.fields) {
   225             if (ignoreField(field.getName(classFileToCheck.constant_pool))) {
   226                 continue;
   227             }
   228             nonFinalStaticEnumField =
   229                     (field.access_flags.flags & (ACC_ENUM | ACC_FINAL)) == 0;
   230             nonFinalStaticField =
   231                     (field.access_flags.flags & ACC_STATIC) != 0 &&
   232                     (field.access_flags.flags & ACC_FINAL) == 0;
   233             if (enumClass ? nonFinalStaticEnumField : nonFinalStaticField) {
   234                 errors.add("There is a mutable field named " +
   235                         field.getName(classFileToCheck.constant_pool) +
   236                         ", at class " +
   237                         classFileToCheck.getName());
   238             }
   239         }
   240     }
   242 }

mercurial