test/tools/javadoc/CheckResourceKeys.java

Wed, 14 Nov 2018 10:18:25 -0800

author
diazhou
date
Wed, 14 Nov 2018 10:18:25 -0800
changeset 3762
7909abb85562
parent 1413
bdcef2ef52d2
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Added tag jdk8u201-b04 for changeset a7f48b9dfb82

jjg@1397 1 /*
jjg@1397 2 * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
jjg@1397 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@1397 4 *
jjg@1397 5 * This code is free software; you can redistribute it and/or modify it
jjg@1397 6 * under the terms of the GNU General Public License version 2 only, as
jjg@1397 7 * published by the Free Software Foundation.
jjg@1397 8 *
jjg@1397 9 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@1397 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@1397 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@1397 12 * version 2 for more details (a copy is included in the LICENSE file that
jjg@1397 13 * accompanied this code).
jjg@1397 14 *
jjg@1397 15 * You should have received a copy of the GNU General Public License version
jjg@1397 16 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@1397 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@1397 18 *
jjg@1397 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jjg@1397 20 * or visit www.oracle.com if you need additional information or have any
jjg@1397 21 * questions.
jjg@1397 22 */
jjg@1397 23
jjg@1397 24 /*
jjg@1397 25 * @test
jjg@1397 26 * @bug 8000612
jjg@1397 27 * @summary need test program to validate javadoc resource bundles
jjg@1397 28 */
jjg@1397 29
jjg@1397 30 import java.io.*;
jjg@1397 31 import java.util.*;
jjg@1397 32 import javax.tools.*;
jjg@1397 33 import com.sun.tools.classfile.*;
jjg@1397 34
jjg@1397 35 /**
jjg@1397 36 * Compare string constants in javadoc classes against keys in javadoc resource bundles.
jjg@1397 37 */
jjg@1397 38 public class CheckResourceKeys {
jjg@1397 39 /**
jjg@1397 40 * Main program.
jjg@1397 41 * Options:
jjg@1397 42 * -finddeadkeys
jjg@1397 43 * look for keys in resource bundles that are no longer required
jjg@1397 44 * -findmissingkeys
jjg@1397 45 * look for keys in resource bundles that are missing
jjg@1397 46 *
jjg@1397 47 * @throws Exception if invoked by jtreg and errors occur
jjg@1397 48 */
jjg@1397 49 public static void main(String... args) throws Exception {
jjg@1397 50 CheckResourceKeys c = new CheckResourceKeys();
jjg@1397 51 if (c.run(args))
jjg@1397 52 return;
jjg@1397 53
jjg@1397 54 if (is_jtreg())
jjg@1397 55 throw new Exception(c.errors + " errors occurred");
jjg@1397 56 else
jjg@1397 57 System.exit(1);
jjg@1397 58 }
jjg@1397 59
jjg@1397 60 static boolean is_jtreg() {
jjg@1397 61 return (System.getProperty("test.src") != null);
jjg@1397 62 }
jjg@1397 63
jjg@1397 64 /**
jjg@1397 65 * Main entry point.
jjg@1397 66 */
jjg@1397 67 boolean run(String... args) throws Exception {
jjg@1397 68 boolean findDeadKeys = false;
jjg@1397 69 boolean findMissingKeys = false;
jjg@1397 70
jjg@1397 71 if (args.length == 0) {
jjg@1397 72 if (is_jtreg()) {
jjg@1397 73 findDeadKeys = true;
jjg@1397 74 findMissingKeys = true;
jjg@1397 75 } else {
jjg@1397 76 System.err.println("Usage: java CheckResourceKeys <options>");
jjg@1397 77 System.err.println("where options include");
jjg@1397 78 System.err.println(" -finddeadkeys find keys in resource bundles which are no longer required");
jjg@1397 79 System.err.println(" -findmissingkeys find keys in resource bundles that are required but missing");
jjg@1397 80 return true;
jjg@1397 81 }
jjg@1397 82 } else {
jjg@1397 83 for (String arg: args) {
jjg@1397 84 if (arg.equalsIgnoreCase("-finddeadkeys"))
jjg@1397 85 findDeadKeys = true;
jjg@1397 86 else if (arg.equalsIgnoreCase("-findmissingkeys"))
jjg@1397 87 findMissingKeys = true;
jjg@1397 88 else
jjg@1397 89 error("bad option: " + arg);
jjg@1397 90 }
jjg@1397 91 }
jjg@1397 92
jjg@1397 93 if (errors > 0)
jjg@1397 94 return false;
jjg@1397 95
jjg@1397 96 Set<String> codeKeys = getCodeKeys();
jjg@1397 97 Set<String> resourceKeys = getResourceKeys();
jjg@1397 98
jjg@1397 99 System.err.println("found " + codeKeys.size() + " keys in code");
jjg@1397 100 System.err.println("found " + resourceKeys.size() + " keys in resource bundles");
jjg@1397 101
jjg@1397 102 if (findDeadKeys)
jjg@1397 103 findDeadKeys(codeKeys, resourceKeys);
jjg@1397 104
jjg@1397 105 if (findMissingKeys)
jjg@1397 106 findMissingKeys(codeKeys, resourceKeys);
jjg@1397 107
jjg@1397 108 return (errors == 0);
jjg@1397 109 }
jjg@1397 110
jjg@1397 111 /**
jjg@1397 112 * Find keys in resource bundles which are probably no longer required.
jjg@1397 113 * A key is required if there is a string in the code that is a resource key,
jjg@1397 114 * or if the key is well-known according to various pragmatic rules.
jjg@1397 115 */
jjg@1397 116 void findDeadKeys(Set<String> codeKeys, Set<String> resourceKeys) {
jjg@1397 117 for (String rk: resourceKeys) {
jjg@1397 118 if (codeKeys.contains(rk))
jjg@1397 119 continue;
jjg@1397 120
jjg@1397 121 error("Resource key not found in code: " + rk);
jjg@1397 122 }
jjg@1397 123 }
jjg@1397 124
jjg@1397 125 /**
jjg@1397 126 * For all strings in the code that look like they might be
jjg@1397 127 * a resource key, verify that a key exists.
jjg@1397 128 */
jjg@1397 129 void findMissingKeys(Set<String> codeKeys, Set<String> resourceKeys) {
jjg@1397 130 for (String ck: codeKeys) {
jjg@1397 131 if (resourceKeys.contains(ck))
jjg@1397 132 continue;
jjg@1397 133 error("No resource for \"" + ck + "\"");
jjg@1397 134 }
jjg@1397 135 }
jjg@1397 136
jjg@1397 137 /**
jjg@1397 138 * Get the set of strings from (most of) the javadoc classfiles.
jjg@1397 139 */
jjg@1397 140 Set<String> getCodeKeys() throws IOException {
jjg@1397 141 Set<String> results = new TreeSet<String>();
jjg@1397 142 JavaCompiler c = ToolProvider.getSystemJavaCompiler();
jjg@1397 143 JavaFileManager fm = c.getStandardFileManager(null, null, null);
jjg@1397 144 JavaFileManager.Location javadocLoc = findJavadocLocation(fm);
jjg@1397 145 String[] pkgs = {
jjg@1397 146 "com.sun.tools.doclets",
jjg@1397 147 "com.sun.tools.javadoc"
jjg@1397 148 };
jjg@1397 149 for (String pkg: pkgs) {
jjg@1397 150 for (JavaFileObject fo: fm.list(javadocLoc,
jjg@1397 151 pkg, EnumSet.of(JavaFileObject.Kind.CLASS), true)) {
jjg@1397 152 String name = fo.getName();
jjg@1397 153 // ignore resource files
jjg@1402 154 if (name.matches(".*resources.[A-Za-z_0-9]+\\.class.*"))
jjg@1397 155 continue;
jjg@1397 156 scan(fo, results);
jjg@1397 157 }
jjg@1397 158 }
jjg@1397 159
jjg@1397 160 // special handling for code strings synthesized in
jjg@1397 161 // com.sun.tools.doclets.internal.toolkit.util.Util.getTypeName
jjg@1397 162 String[] extras = {
jjg@1397 163 "AnnotationType", "Class", "Enum", "Error", "Exception", "Interface"
jjg@1397 164 };
jjg@1397 165 for (String s: extras) {
jjg@1397 166 if (results.contains("doclet." + s))
jjg@1397 167 results.add("doclet." + s.toLowerCase());
jjg@1397 168 }
jjg@1397 169
jjg@1413 170 // special handling for code strings synthesized in
jjg@1413 171 // com.sun.tools.javadoc.Messager
jjg@1413 172 results.add("javadoc.error.msg");
jjg@1413 173 results.add("javadoc.note.msg");
jjg@1413 174 results.add("javadoc.note.pos.msg");
jjg@1413 175 results.add("javadoc.warning.msg");
jjg@1413 176
jjg@1397 177 return results;
jjg@1397 178 }
jjg@1397 179
jjg@1397 180 // depending on how the test is run, javadoc may be on bootclasspath or classpath
jjg@1397 181 JavaFileManager.Location findJavadocLocation(JavaFileManager fm) {
jjg@1397 182 JavaFileManager.Location[] locns =
jjg@1397 183 { StandardLocation.PLATFORM_CLASS_PATH, StandardLocation.CLASS_PATH };
jjg@1397 184 try {
jjg@1397 185 for (JavaFileManager.Location l: locns) {
jjg@1397 186 JavaFileObject fo = fm.getJavaFileForInput(l,
jjg@1397 187 "com.sun.tools.javadoc.Main", JavaFileObject.Kind.CLASS);
jjg@1397 188 if (fo != null) {
jjg@1397 189 System.err.println("found javadoc in " + l);
jjg@1397 190 return l;
jjg@1397 191 }
jjg@1397 192 }
jjg@1397 193 } catch (IOException e) {
jjg@1397 194 throw new Error(e);
jjg@1397 195 }
jjg@1397 196 throw new IllegalStateException("Cannot find javadoc");
jjg@1397 197 }
jjg@1397 198
jjg@1397 199 /**
jjg@1397 200 * Get the set of strings from a class file.
jjg@1397 201 * Only strings that look like they might be a resource key are returned.
jjg@1397 202 */
jjg@1397 203 void scan(JavaFileObject fo, Set<String> results) throws IOException {
jjg@1397 204 //System.err.println("scan " + fo.getName());
jjg@1397 205 InputStream in = fo.openInputStream();
jjg@1397 206 try {
jjg@1397 207 ClassFile cf = ClassFile.read(in);
jjg@1397 208 for (ConstantPool.CPInfo cpinfo: cf.constant_pool.entries()) {
jjg@1397 209 if (cpinfo.getTag() == ConstantPool.CONSTANT_Utf8) {
jjg@1397 210 String v = ((ConstantPool.CONSTANT_Utf8_info) cpinfo).value;
jjg@1397 211 if (v.matches("(doclet|main|javadoc|tag)\\.[A-Za-z0-9-_.]+"))
jjg@1397 212 results.add(v);
jjg@1397 213 }
jjg@1397 214 }
jjg@1397 215 } catch (ConstantPoolException ignore) {
jjg@1397 216 } finally {
jjg@1397 217 in.close();
jjg@1397 218 }
jjg@1397 219 }
jjg@1397 220
jjg@1397 221 /**
jjg@1397 222 * Get the set of keys from the javadoc resource bundles.
jjg@1397 223 */
jjg@1397 224 Set<String> getResourceKeys() {
jjg@1397 225 String[] names = {
jjg@1397 226 "com.sun.tools.doclets.formats.html.resources.standard",
jjg@1397 227 "com.sun.tools.doclets.internal.toolkit.resources.doclets",
jjg@1397 228 "com.sun.tools.javadoc.resources.javadoc",
jjg@1397 229 };
jjg@1397 230 Set<String> results = new TreeSet<String>();
jjg@1397 231 for (String name : names) {
jjg@1397 232 ResourceBundle b = ResourceBundle.getBundle(name);
jjg@1397 233 results.addAll(b.keySet());
jjg@1397 234 }
jjg@1397 235 return results;
jjg@1397 236 }
jjg@1397 237
jjg@1397 238 /**
jjg@1397 239 * Report an error.
jjg@1397 240 */
jjg@1397 241 void error(String msg) {
jjg@1397 242 System.err.println("Error: " + msg);
jjg@1397 243 errors++;
jjg@1397 244 }
jjg@1397 245
jjg@1397 246 int errors;
jjg@1397 247 }

mercurial