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

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

mercurial