--- a/langtools/make/CompileInterim.gmk Thu Aug 25 22:35:51 2016 +0000
+++ b/langtools/make/CompileInterim.gmk Thu Aug 25 17:58:39 2016 -0700
@@ -32,7 +32,7 @@
include SetupJavaCompilers.gmk
################################################################################
-# Setup the rules to build interim langtools, which is compiled by the boot
+# Setup the rules to build interim langtools, which is compiled by the boot
# javac and can be run on the boot jdk. This will be used to compile
# the rest of the product. Each module is compiled separately to allow a modular
# boot jdk to override system classes using -Xoverride:.
@@ -45,7 +45,8 @@
DISABLE_SJAVAC := true, \
SRC := $(LANGTOOLS_TOPDIR)/src/$(strip $1)/share/classes \
$$(wildcard $(SUPPORT_OUTPUTDIR)/gensrc/$(strip $1)), \
- EXCLUDES := sun com/sun/tools/jdeps com/sun/tools/javap, \
+ EXCLUDES := sun com/sun/tools/jdeps com/sun/tools/javap \
+ com/sun/tools/jdeprscan, \
EXCLUDE_FILES := module-info.java, \
COPY := .gif .png .xml .css .js javax.tools.JavaCompilerTool, \
BIN := $(BUILDTOOLS_OUTPUTDIR)/override_modules/$(strip $1), \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/CSV.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Utility class for manipulating comma-separated-value (CSV) data.
+ */
+public class CSV {
+ static String quote(String input) {
+ String result;
+ boolean needQuote = input.contains(",");
+
+ if (input.contains("\"")) {
+ needQuote = true;
+ result = input.replace("\"", "\"\"");
+ } else {
+ result = input;
+ }
+
+ if (needQuote) {
+ return "\"" + result + "\"";
+ } else {
+ return result;
+ }
+ }
+
+ /**
+ * Writes the objects' string representations to the output as a line of CSV.
+ * The objects are converted to String, quoted if necessary, joined with commas,
+ * and are written to the output followed by the line separator string.
+ *
+ * @param out the output destination
+ * @param objs the objects to write
+ */
+ public static void write(PrintStream out, Object... objs) {
+ out.println(Arrays.stream(objs)
+ .map(Object::toString)
+ .map(CSV::quote)
+ .collect(Collectors.joining(",")));
+ }
+
+ /**
+ * The CSV parser state.
+ */
+ enum State {
+ START_FIELD, // the start of a field
+ IN_FIELD, // within an unquoted field
+ IN_QFIELD, // within a quoted field
+ END_QFIELD // after the end of a quoted field
+ }
+
+ /**
+ * Splits an input line into a list of strings, handling quoting.
+ *
+ * @param input the input line
+ * @return the resulting list of strings
+ */
+ public static List<String> split(String input) {
+ List<String> result = new ArrayList<>();
+ StringBuilder cur = new StringBuilder();
+ State state = State.START_FIELD;
+
+ for (int i = 0; i < input.length(); i++) {
+ char ch = input.charAt(i);
+ switch (ch) {
+ case ',':
+ switch (state) {
+ case IN_QFIELD:
+ cur.append(',');
+ break;
+ default:
+ result.add(cur.toString());
+ cur.setLength(0);
+ state = State.START_FIELD;
+ break;
+ }
+ break;
+ case '"':
+ switch (state) {
+ case START_FIELD:
+ state = State.IN_QFIELD;
+ break;
+ case IN_QFIELD:
+ state = State.END_QFIELD;
+ break;
+ case IN_FIELD:
+ throw new CSVParseException("unexpected quote", input, i);
+ case END_QFIELD:
+ cur.append('"');
+ state = State.IN_QFIELD;
+ break;
+ }
+ break;
+ default:
+ switch (state) {
+ case START_FIELD:
+ state = State.IN_FIELD;
+ break;
+ case IN_FIELD:
+ case IN_QFIELD:
+ break;
+ case END_QFIELD:
+ throw new CSVParseException("extra character after quoted string",
+ input, i);
+ }
+ cur.append(ch);
+ break;
+ }
+ }
+
+ if (state == State.IN_QFIELD) {
+ throw new CSVParseException("unclosed quote", input, input.length());
+ }
+
+ result.add(cur.toString());
+ return result;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/CSVParseException.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan;
+
+/**
+ * Exception representing an error encountered during CSV parsing.
+ */
+public class CSVParseException extends IllegalArgumentException {
+ private static final long serialVersionUID = 6822670269555409371L;
+ final String input;
+ final int index;
+
+ public CSVParseException(String msg, String input, int index) {
+ super(msg);
+ this.input = input;
+ this.index = index;
+ }
+
+ public String getInput() { return input; }
+
+ public int getIndex() { return index; }
+
+ /**
+ * Returns a string describing the parse error.
+ *
+ * @return a string describing the parse error
+ */
+ @Override
+ public String getMessage() {
+ return super.getMessage() + " at index " + index + ": " + input;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/DeprDB.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.lang.model.element.ElementKind;
+
+/**
+ * A database of deprecations (APIs declared to be deprecated),
+ * loaded from a JDK or from a class library.
+ */
+public class DeprDB {
+ /**
+ * Deprecated types.
+ * A map from deprecated type names to DeprData values.
+ * Types include classes, interfaces, enums, and annotation types.
+ */
+ final Map<String, DeprData> types = new HashMap<>();
+
+ /**
+ * Deprecated methods. Key is type name, value is map from method
+ * signatures in the form "methodname(parms)ret" to DeprData value.
+ */
+ final Map<String, Map<String, DeprData>> methods = new HashMap<>();
+
+ /**
+ * Deprecated fields. Key is type name, value is map from field name
+ * to forRemoval value.
+ */
+ final Map<String, Map<String, DeprData>> fields = new HashMap<>();
+
+ /**
+ * Set of valid ElementKind strings.
+ */
+ static final Set<String> validElementKinds =
+ Set.of(Arrays.stream(ElementKind.values())
+ .map(ElementKind::toString)
+ .toArray(String[]::new));
+
+
+ private DeprDB() { }
+
+ public static List<DeprData> loadFromFile(String filename) throws IOException {
+ List<DeprData> list = new ArrayList<>();
+
+ exit:
+ try (final BufferedReader br = Files.newBufferedReader(Paths.get(filename))) {
+ String line = br.readLine();
+ if (line == null || !line.equals("#jdepr1")) {
+ System.out.printf("ERROR: invalid first line %s%n", line);
+ break exit;
+ }
+ while ((line = br.readLine()) != null) {
+ if (line.startsWith("#")) {
+ continue;
+ }
+ List<String> tokens = CSV.split(line);
+ if (tokens.size() != 5) {
+ System.out.printf("ERROR: %s%n", line);
+ continue;
+ }
+ // kind,typeName,descOrName,since,forRemoval
+ String kindStr = tokens.get(0);
+ String type = tokens.get(1);
+ String detail = tokens.get(2);
+ String since = tokens.get(3);
+ boolean forRemoval = Boolean.parseBoolean(tokens.get(4));
+ ElementKind kind;
+
+ if (validElementKinds.contains(kindStr)) {
+ kind = ElementKind.valueOf(kindStr);
+ } else {
+ System.out.printf("ERROR: invalid element kind %s%n", kindStr);
+ continue;
+ }
+
+ DeprData data = new DeprData(kind, /*TypeElement*/null, type, detail, since, forRemoval);
+ list.add(data);
+ }
+ }
+ return list;
+ }
+
+ public static DeprDB loadFromList(List<DeprData> deprList) {
+ DeprDB db = new DeprDB();
+
+ for (DeprData dd : deprList) {
+ switch (dd.kind) {
+ case CLASS:
+ case INTERFACE:
+ case ENUM:
+ case ANNOTATION_TYPE:
+ db.types.put(dd.typeName, dd);
+ break;
+ case METHOD:
+ case CONSTRUCTOR:
+ db.methods.computeIfAbsent(dd.typeName, k -> new HashMap<>())
+ .put(dd.nameSig, dd);
+ break;
+ case ENUM_CONSTANT:
+ case FIELD:
+ db.fields.computeIfAbsent(dd.typeName, k -> new HashMap<>())
+ .put(dd.nameSig, dd);
+ break;
+ }
+ }
+
+ return db;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ Formatter f = new Formatter(sb, Locale.US);
+ f.format("=== Types ===%n");
+ f.format("%s%n", types.toString());
+ f.format("=== Methods ===%n");
+ f.format("%s%n", methods.toString());
+ f.format("=== Fields ===%n");
+ f.format("%s%n", fields.toString());
+ return sb.toString();
+ }
+
+ public DeprData getTypeDeprecated(String typeName) {
+ return types.get(typeName);
+ }
+
+ public DeprData getMethodDeprecated(String typeName, String methodName, String type) {
+ Map<String, DeprData> m = methods.get(typeName);
+ if (m == null) {
+ return null;
+ }
+ return m.get(methodName + type);
+ }
+
+ public DeprData getFieldDeprecated(String typeName, String fieldName) {
+ Map<String, DeprData> f = fields.get(typeName);
+ if (f == null) {
+ return null;
+ }
+ return f.get(fieldName);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/DeprData.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan;
+
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * A simple data class that contains language model data (TypeElement, etc.)
+ * about a deprecated API.
+ */
+public class DeprData {
+ final ElementKind kind;
+ final TypeElement type; // null if data loaded from file
+ final String typeName;
+ final String nameSig;
+ final String since;
+ final boolean forRemoval;
+
+ public DeprData(ElementKind kind, TypeElement type, String typeName, String nameSig,
+ String since, boolean forRemoval) {
+ this.kind = kind;
+ this.type = type;
+ this.typeName = typeName;
+ this.nameSig = nameSig;
+ this.since = since;
+ this.forRemoval = forRemoval;
+ }
+
+ public boolean isForRemoval() {
+ return forRemoval;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("DeprData(%s,%s,%s,%s,%s,%s)",
+ kind, type, typeName, nameSig, since, forRemoval);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/LoadProc.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan;
+
+import java.lang.annotation.IncompleteAnnotationException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Messager;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+
+import javax.tools.Diagnostic;
+
+import static javax.lang.model.SourceVersion.RELEASE_9;
+
+/**
+ * Annotation processor for the Deprecation Scanner tool.
+ * Examines APIs for deprecated elements and records information
+ *
+ */
+@SupportedAnnotationTypes("java.lang.Deprecated")
+@SupportedSourceVersion(RELEASE_9)
+public class LoadProc extends AbstractProcessor {
+ Elements elements;
+ Messager messager;
+ final List<DeprData> deprList = new ArrayList<>();
+
+ public LoadProc() {
+ }
+
+ @Override
+ public void init(ProcessingEnvironment pe) {
+ super.init(pe);
+ elements = pe.getElementUtils();
+ messager = pe.getMessager();
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (roundEnv.processingOver()) {
+ return false;
+ }
+
+ // Assume annotations contains only @Deprecated.
+ // Note: no way to get deprecated packages, since
+ // @Deprecated is ignored in package-info.java files.
+
+ Set<? extends Element> set = roundEnv.getElementsAnnotatedWith(Deprecated.class);
+ for (Element e : set) {
+ ElementKind kind = e.getKind();
+ Deprecated depr = e.getAnnotation(Deprecated.class);
+ switch (kind) {
+ case CLASS:
+ case INTERFACE:
+ case ENUM:
+ case ANNOTATION_TYPE:
+ addType(kind, (TypeElement)e, depr);
+ break;
+ case CONSTRUCTOR:
+ case ENUM_CONSTANT:
+ case FIELD:
+ case METHOD:
+ Element encl = e.getEnclosingElement();
+ ElementKind enclKind = encl.getKind();
+ switch (enclKind) {
+ case CLASS:
+ case INTERFACE:
+ case ENUM:
+ case ANNOTATION_TYPE:
+ String detail = getDetail(e);
+ addMember(kind, (TypeElement)encl, detail, depr);
+ break;
+ default:
+ messager.printMessage(Diagnostic.Kind.WARNING,
+ "element " + e +
+ " within unknown enclosing element " + encl +
+ " of kind " + enclKind, e);
+ break;
+ }
+ break;
+ default:
+ messager.printMessage(Diagnostic.Kind.WARNING,
+ "unknown element " + e +
+ " of kind " + kind +
+ " within " + e.getEnclosingElement(), e);
+ break;
+ }
+ }
+ return true;
+ }
+
+ public List<DeprData> getDeprecations() {
+ return deprList;
+ }
+
+ String getDetail(Element e) {
+ if (e.getKind().isField()) {
+ return e.getSimpleName().toString();
+ } else {
+ // method or constructor
+ ExecutableElement ee = (ExecutableElement) e;
+ String ret;
+ ret = desc(ee.getReturnType());
+ List<? extends TypeMirror> parameterTypes = ((ExecutableType)ee.asType()).getParameterTypes();
+ String parms = parameterTypes.stream()
+ .map(this::desc)
+ .collect(Collectors.joining());
+ return ee.getSimpleName().toString() + "(" + parms + ")" + ret;
+ }
+ }
+
+ String desc(TypeMirror tm) {
+ switch (tm.getKind()) {
+ case BOOLEAN:
+ return "Z";
+ case BYTE:
+ return "B";
+ case SHORT:
+ return "S";
+ case CHAR:
+ return "C";
+ case INT:
+ return "I";
+ case LONG:
+ return "J";
+ case FLOAT:
+ return "F";
+ case DOUBLE:
+ return "D";
+ case VOID:
+ return "V";
+ case DECLARED:
+ String s =
+ ((TypeElement)((DeclaredType)tm).asElement()).getQualifiedName().toString();
+ s = s.replace('.', '/');
+ return "L" + s + ";";
+ case ARRAY:
+ return "[" + desc(((ArrayType)tm).getComponentType());
+ default:
+ return tm.getKind().toString();
+ }
+ }
+
+ void addType(ElementKind kind, TypeElement type, Deprecated dep) {
+ addData(kind, type, "", dep);
+ }
+
+ void addMember(ElementKind kind, TypeElement type, String nameSig, Deprecated dep) {
+ addData(kind, type, nameSig, dep);
+ }
+
+ void addData(ElementKind kind, TypeElement type, String nameSig, Deprecated dep) {
+ String typeName = elements.getBinaryName(type).toString().replace('.', '/');
+
+ String since = "";
+ try {
+ since = dep.since();
+ } catch (IncompleteAnnotationException ignore) { }
+
+ boolean forRemoval = false;
+ try {
+ forRemoval = dep.forRemoval();
+ } catch (IncompleteAnnotationException ignore) { }
+
+ deprList.add(new DeprData(kind, type, typeName, nameSig, since, forRemoval));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,717 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.Queue;
+import java.util.stream.Stream;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+import com.sun.tools.javac.file.JavacFileManager;
+
+import com.sun.tools.jdeprscan.scan.Scan;
+
+import static java.util.stream.Collectors.*;
+
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * Deprecation Scanner tool. Loads API deprecation information from the
+ * JDK image, or optionally, from a jar file or class hierarchy. Then scans
+ * a class library for usages of those APIs.
+ *
+ * TODO:
+ * - audit error handling throughout, but mainly in scan package
+ * - handling of covariant overrides
+ * - handling of override of method found in multiple superinterfaces
+ * - convert type/method/field output to Java source like syntax, e.g.
+ * instead of java/lang/Runtime.runFinalizersOnExit(Z)V
+ * print void java.lang.Runtime.runFinalizersOnExit(boolean)
+ * - more example output in man page
+ * - more rigorous GNU style option parsing; use joptsimple?
+ *
+ * FUTURES:
+ * - add module support: -addmods, -modulepath, module arg
+ * - load deprecation declarations from a designated class library instead
+ * of the JDK
+ * - load deprecation declarations from a module
+ * - scan a module (but a modular jar can be treated just a like an ordinary jar)
+ * - multi-version jar
+ */
+public class Main implements DiagnosticListener<JavaFileObject> {
+ public static Main instance;
+
+ final PrintStream out;
+ final PrintStream err;
+ final List<File> bootClassPath = new ArrayList<>();
+ final List<File> classPath = new ArrayList<>();
+ final List<File> systemModules = new ArrayList<>();
+ final List<String> options = new ArrayList<>();
+ final List<String> comments = new ArrayList<>();
+
+ // Valid releases need to match what the compiler supports.
+ // Keep these updated manually until there's a compiler API
+ // that allows querying of supported releases.
+ final Set<String> releasesWithoutForRemoval = Set.of("6", "7", "8");
+ final Set<String> releasesWithForRemoval = Set.of("9");
+
+ final Set<String> validReleases;
+ {
+ Set<String> temp = new HashSet<>(releasesWithoutForRemoval);
+ temp.addAll(releasesWithForRemoval);
+ validReleases = Set.of(temp.toArray(new String[0]));
+ }
+
+ boolean verbose = false;
+ boolean forRemoval = false;
+
+ final JavaCompiler compiler;
+ final StandardJavaFileManager fm;
+
+ List<DeprData> deprList; // non-null after successful load phase
+
+ /**
+ * Processes a collection of class names. Names should fully qualified
+ * names in the form "pkg.pkg.pkg.classname".
+ *
+ * @param classNames collection of fully qualified classnames to process
+ * @return true for success, false for failure
+ * @throws IOException if an I/O error occurs
+ */
+ boolean doClassNames(Collection<String> classNames) throws IOException {
+ if (verbose) {
+ out.println("List of classes to process:");
+ classNames.forEach(out::println);
+ out.println("End of class list.");
+ }
+
+ // TODO: not sure this is necessary...
+ if (fm instanceof JavacFileManager) {
+ ((JavacFileManager)fm).setSymbolFileEnabled(false);
+ }
+
+ fm.setLocation(StandardLocation.CLASS_PATH, classPath);
+ if (!bootClassPath.isEmpty()) {
+ fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);
+ }
+
+ if (!systemModules.isEmpty()) {
+ fm.setLocation(StandardLocation.SYSTEM_MODULES, systemModules);
+ }
+
+ LoadProc proc = new LoadProc();
+ JavaCompiler.CompilationTask task =
+ compiler.getTask(null, fm, this, options, classNames, null);
+ task.setProcessors(List.of(proc));
+ boolean r = task.call();
+ if (r) {
+ if (forRemoval) {
+ deprList = proc.getDeprecations().stream()
+ .filter(DeprData::isForRemoval)
+ .collect(toList());
+ } else {
+ deprList = proc.getDeprecations();
+ }
+ }
+ return r;
+ }
+
+ /**
+ * Processes a stream of filenames (strings). The strings are in the
+ * form pkg/pkg/pkg/classname.class relative to the root of a package
+ * hierarchy.
+ *
+ * @param filenames a Stream of filenames to process
+ * @return true for success, false for failure
+ * @throws IOException if an I/O error occurs
+ */
+ boolean doFileNames(Stream<String> filenames) throws IOException {
+ return doClassNames(
+ filenames.filter(name -> name.endsWith(".class"))
+ .filter(name -> !name.endsWith("package-info.class"))
+ .filter(name -> !name.endsWith("module-info.class"))
+ .map(s -> s.replaceAll("\\.class$", ""))
+ .map(s -> s.replace('/', '.'))
+ .collect(toList()));
+ }
+
+ /**
+ * Replaces all but the first occurrence of '/' with '.'. Assumes
+ * that the name is in the format module/pkg/pkg/classname.class.
+ * That is, the name should contain at least one '/' character
+ * separating the module name from the package-class name.
+ *
+ * @param filename the input filename
+ * @return the modular classname
+ */
+ String convertModularFileName(String filename) {
+ int slash = filename.indexOf('/');
+ return filename.substring(0, slash)
+ + "/"
+ + filename.substring(slash+1).replace('/', '.');
+ }
+
+ /**
+ * Processes a stream of filenames (strings) including a module prefix.
+ * The strings are in the form module/pkg/pkg/pkg/classname.class relative
+ * to the root of a directory containing modules. The strings are processed
+ * into module-qualified class names of the form
+ * "module/pkg.pkg.pkg.classname".
+ *
+ * @param filenames a Stream of filenames to process
+ * @return true for success, false for failure
+ * @throws IOException if an I/O error occurs
+ */
+ boolean doModularFileNames(Stream<String> filenames) throws IOException {
+ return doClassNames(
+ filenames.filter(name -> name.endsWith(".class"))
+ .filter(name -> !name.endsWith("package-info.class"))
+ .filter(name -> !name.endsWith("module-info.class"))
+ .map(s -> s.replaceAll("\\.class$", ""))
+ .map(this::convertModularFileName)
+ .collect(toList()));
+ }
+
+ /**
+ * Processes named class files in the given directory. The directory
+ * should be the root of a package hierarchy. If classNames is
+ * empty, walks the directory hierarchy to find all classes.
+ *
+ * @param dirname the name of the directory to process
+ * @param classNames the names of classes to process
+ * @return true for success, false for failure
+ * @throws IOException if an I/O error occurs
+ */
+ boolean processDirectory(String dirname, Collection<String> classNames) throws IOException {
+ if (!Files.isDirectory(Paths.get(dirname))) {
+ err.printf("%s: not a directory%n", dirname);
+ return false;
+ }
+
+ classPath.add(0, new File(dirname));
+
+ if (classNames.isEmpty()) {
+ Path base = Paths.get(dirname);
+ int baseCount = base.getNameCount();
+ try (Stream<Path> paths = Files.walk(base)) {
+ Stream<String> files =
+ paths.filter(p -> p.getNameCount() > baseCount)
+ .map(p -> p.subpath(baseCount, p.getNameCount()))
+ .map(Path::toString);
+ return doFileNames(files);
+ }
+ } else {
+ return doClassNames(classNames);
+ }
+ }
+
+ /**
+ * Processes all class files in the given jar file.
+ *
+ * @param jarname the name of the jar file to process
+ * @return true for success, false for failure
+ * @throws IOException if an I/O error occurs
+ */
+ boolean doJarFile(String jarname) throws IOException {
+ try (JarFile jf = new JarFile(jarname)) {
+ Stream<String> files =
+ jf.stream()
+ .map(JarEntry::getName);
+ return doFileNames(files);
+ }
+ }
+
+ /**
+ * Processes named class files from the given jar file,
+ * or all classes if classNames is empty.
+ *
+ * @param jarname the name of the jar file to process
+ * @param classNames the names of classes to process
+ * @return true for success, false for failure
+ * @throws IOException if an I/O error occurs
+ */
+ boolean processJarFile(String jarname, Collection<String> classNames) throws IOException {
+ classPath.add(0, new File(jarname));
+
+ if (classNames.isEmpty()) {
+ return doJarFile(jarname);
+ } else {
+ return doClassNames(classNames);
+ }
+ }
+
+ /**
+ * Processes named class files from rt.jar of a JDK version 7 or 8.
+ * If classNames is empty, processes all classes.
+ *
+ * @param jdkHome the path to the "home" of the JDK to process
+ * @param classNames the names of classes to process
+ * @return true for success, false for failure
+ * @throws IOException if an I/O error occurs
+ */
+ boolean processOldJdk(String jdkHome, Collection<String> classNames) throws IOException {
+ String RTJAR = jdkHome + "/jre/lib/rt.jar";
+ String CSJAR = jdkHome + "/jre/lib/charsets.jar";
+
+ bootClassPath.add(0, new File(RTJAR));
+ bootClassPath.add(1, new File(CSJAR));
+ options.add("-source");
+ options.add("8");
+
+ if (classNames.isEmpty()) {
+ return doJarFile(RTJAR);
+ } else {
+ return doClassNames(classNames);
+ }
+ }
+
+ /**
+ * Processes listed classes given a JDK 9 home.
+ */
+ boolean processJdk9(String jdkHome, Collection<String> classes) throws IOException {
+ systemModules.add(new File(jdkHome));
+ return doClassNames(classes);
+ }
+
+ /**
+ * Processes the class files from the currently running JDK,
+ * using the jrt: filesystem.
+ *
+ * @return true for success, false for failure
+ * @throws IOException if an I/O error occurs
+ */
+ boolean processSelf(Collection<String> classes) throws IOException {
+ options.add("-addmods");
+ options.add("java.se.ee,jdk.xml.bind"); // TODO why jdk.xml.bind?
+
+ if (classes.isEmpty()) {
+ Path modules = FileSystems.getFileSystem(URI.create("jrt:/"))
+ .getPath("/modules");
+
+ // names are /modules/<modulename>/pkg/.../Classname.class
+ try (Stream<Path> paths = Files.walk(modules)) {
+ Stream<String> files =
+ paths.filter(p -> p.getNameCount() > 2)
+ .map(p -> p.subpath(1, p.getNameCount()))
+ .map(Path::toString);
+ return doModularFileNames(files);
+ }
+ } else {
+ return doClassNames(classes);
+ }
+ }
+
+ /**
+ * Process classes from a particular JDK release, using only information
+ * in this JDK.
+ *
+ * @param release "6", "7", "8", or "9"
+ * @param classes collection of classes to process, may be empty
+ * @return success value
+ */
+ boolean processRelease(String release, Collection<String> classes) throws IOException {
+ options.addAll(List.of("-release", release));
+
+ if (release.equals("9")) {
+ List<String> rootMods = List.of("java.se", "java.se.ee");
+ TraverseProc proc = new TraverseProc(rootMods);
+ JavaCompiler.CompilationTask task =
+ compiler.getTask(null, fm, this,
+ // options
+ List.of("-addmods", String.join(",", rootMods)),
+ // classes
+ List.of("java.lang.Object"),
+ null);
+ task.setProcessors(List.of(proc));
+ if (!task.call()) {
+ return false;
+ }
+ Map<PackageElement, List<TypeElement>> types = proc.getPublicTypes();
+ options.add("-addmods");
+ options.add(String.join(",", rootMods));
+ return doClassNames(
+ types.values().stream()
+ .flatMap(List::stream)
+ .map(TypeElement::toString)
+ .collect(toList()));
+ } else {
+ // TODO: kind of a hack...
+ // Create a throwaway compilation task with options "-release N"
+ // which has the side effect of setting the file manager's
+ // PLATFORM_CLASS_PATH to the right value.
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fm =
+ compiler.getStandardFileManager(this, null, StandardCharsets.UTF_8);
+ JavaCompiler.CompilationTask task =
+ compiler.getTask(null, fm, this, List.of("-release", release), null, null);
+ List<Path> paths = new ArrayList<>();
+ for (Path p : fm.getLocationAsPaths(StandardLocation.PLATFORM_CLASS_PATH)) {
+ try (Stream<Path> str = Files.walk(p)) {
+ str.forEachOrdered(paths::add);
+ }
+ }
+
+ options.add("-Xlint:-options");
+
+ return doClassNames(
+ paths.stream()
+ .filter(path -> path.toString().endsWith(".sig"))
+ .map(path -> path.subpath(1, path.getNameCount()))
+ .map(Path::toString)
+ .map(s -> s.replaceAll("\\.sig$", ""))
+ .map(s -> s.replace('/', '.'))
+ .collect(toList()));
+ }
+ }
+
+ /**
+ * Prints a usage message to the err stream.
+ */
+ void usage() {
+
+ }
+
+ /**
+ * An enum denoting the mode in which the tool is running.
+ * Different modes correspond to the different process* methods.
+ * The exception is UNKNOWN, which indicates that a mode wasn't
+ * specified on the command line, which is an error.
+ */
+ static enum LoadMode {
+ CLASSES, DIR, JAR, OLD_JDK, JDK9, SELF, RELEASE, LOAD_CSV
+ }
+
+ static enum ScanMode {
+ ARGS, LIST, PRINT_CSV
+ }
+
+ /**
+ * A checked exception that's thrown if a command-line syntax error
+ * is detected.
+ */
+ static class UsageException extends Exception {
+ private static final long serialVersionUID = 3611828659572908743L;
+ }
+
+ /**
+ * Convenience method to throw UsageException if a condition is false.
+ *
+ * @param cond the condition that's required to be true
+ * @throws UsageException
+ */
+ void require(boolean cond) throws UsageException {
+ if (!cond) {
+ throw new UsageException();
+ }
+ }
+
+ /**
+ * Constructs an instance of the finder tool.
+ *
+ * @param out the stream to which the tool's output is sent
+ * @param err the stream to which error messages are sent
+ */
+ Main(PrintStream out, PrintStream err) {
+ this.out = out;
+ this.err = err;
+ compiler = ToolProvider.getSystemJavaCompiler();
+ fm = compiler.getStandardFileManager(this, null, StandardCharsets.UTF_8);
+ }
+
+ /**
+ * Prints the diagnostic to the err stream.
+ *
+ * Specified by the DiagnosticListener interface.
+ *
+ * @param diagnostic the tool diagnostic to print
+ */
+ @Override
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ err.println(diagnostic);
+ }
+
+ /**
+ * Parses arguments and performs the requested processing.
+ *
+ * @param argArray command-line arguments
+ * @return true on success, false on error
+ */
+ boolean run(String... argArray) {
+ Queue<String> args = new ArrayDeque<>(Arrays.asList(argArray));
+ LoadMode loadMode = LoadMode.RELEASE;
+ ScanMode scanMode = ScanMode.ARGS;
+ String dir = null;
+ String jar = null;
+ String jdkHome = null;
+ String release = "9";
+ List<String> loadClasses = new ArrayList<>();
+ String csvFile = null;
+
+ try {
+ while (!args.isEmpty()) {
+ String a = args.element();
+ if (a.startsWith("-")) {
+ args.remove();
+ switch (a) {
+ case "--class-path":
+ case "-cp":
+ classPath.clear();
+ Arrays.stream(args.remove().split(File.pathSeparator))
+ .map(File::new)
+ .forEachOrdered(classPath::add);
+ break;
+ case "--for-removal":
+ forRemoval = true;
+ break;
+ case "--full-version":
+ out.println(System.getProperty("java.vm.version"));
+ return false;
+ case "--help":
+ case "-h":
+ out.println(Messages.get("main.usage"));
+ out.println();
+ out.println(Messages.get("main.help"));
+ return false;
+ case "-l":
+ case "--list":
+ require(scanMode == ScanMode.ARGS);
+ scanMode = ScanMode.LIST;
+ break;
+ case "--release":
+ loadMode = LoadMode.RELEASE;
+ release = args.remove();
+ if (!validReleases.contains(release)) {
+ throw new UsageException();
+ }
+ break;
+ case "-v":
+ case "--verbose":
+ verbose = true;
+ break;
+ case "--version":
+ out.println(System.getProperty("java.version"));
+ return false;
+ case "--Xcompiler-arg":
+ options.add(args.remove());
+ break;
+ case "--Xcsv-comment":
+ comments.add(args.remove());
+ break;
+ case "--Xhelp":
+ out.println(Messages.get("main.xhelp"));
+ return false;
+ case "--Xload-class":
+ loadMode = LoadMode.CLASSES;
+ loadClasses.add(args.remove());
+ break;
+ case "--Xload-csv":
+ loadMode = LoadMode.LOAD_CSV;
+ csvFile = args.remove();
+ break;
+ case "--Xload-dir":
+ loadMode = LoadMode.DIR;
+ dir = args.remove();
+ break;
+ case "--Xload-jar":
+ loadMode = LoadMode.JAR;
+ jar = args.remove();
+ break;
+ case "--Xload-jdk9":
+ loadMode = LoadMode.JDK9;
+ jdkHome = args.remove();
+ break;
+ case "--Xload-old-jdk":
+ loadMode = LoadMode.OLD_JDK;
+ jdkHome = args.remove();
+ break;
+ case "--Xload-self":
+ loadMode = LoadMode.SELF;
+ break;
+ case "--Xprint-csv":
+ require(scanMode == ScanMode.ARGS);
+ scanMode = ScanMode.PRINT_CSV;
+ break;
+ default:
+ throw new UsageException();
+ }
+ } else {
+ break;
+ }
+ }
+
+ if ((scanMode == ScanMode.ARGS) == args.isEmpty()) {
+ throw new UsageException();
+ }
+
+ if ( forRemoval && loadMode == LoadMode.RELEASE &&
+ releasesWithoutForRemoval.contains(release)) {
+ throw new UsageException();
+ }
+
+ boolean success = false;
+
+ switch (loadMode) {
+ case CLASSES:
+ success = doClassNames(loadClasses);
+ break;
+ case DIR:
+ success = processDirectory(dir, loadClasses);
+ break;
+ case JAR:
+ success = processJarFile(jar, loadClasses);
+ break;
+ case JDK9:
+ require(!args.isEmpty());
+ success = processJdk9(jdkHome, loadClasses);
+ break;
+ case LOAD_CSV:
+ deprList = DeprDB.loadFromFile(csvFile);
+ success = true;
+ break;
+ case OLD_JDK:
+ success = processOldJdk(jdkHome, loadClasses);
+ break;
+ case RELEASE:
+ success = processRelease(release, loadClasses);
+ break;
+ case SELF:
+ success = processSelf(loadClasses);
+ break;
+ default:
+ throw new UsageException();
+ }
+
+ if (!success) {
+ return false;
+ }
+ } catch (NoSuchElementException | UsageException ex) {
+ err.println(Messages.get("main.usage"));
+ return false;
+ } catch (IOException ioe) {
+ if (verbose) {
+ ioe.printStackTrace(err);
+ } else {
+ err.println(ioe);
+ }
+ return false;
+ }
+
+ // now the scanning phase
+
+ switch (scanMode) {
+ case LIST:
+ for (DeprData dd : deprList) {
+ if (!forRemoval || dd.isForRemoval()) {
+ out.println(Pretty.print(dd));
+ }
+ }
+ break;
+ case PRINT_CSV:
+ out.println("#jdepr1");
+ comments.forEach(s -> out.println("# " + s));
+ for (DeprData dd : deprList) {
+ CSV.write(out, dd.kind, dd.typeName, dd.nameSig, dd.since, dd.forRemoval);
+ }
+ break;
+ case ARGS:
+ DeprDB db = DeprDB.loadFromList(deprList);
+ List<String> cp = classPath.stream()
+ .map(File::toString)
+ .collect(toList());
+ Scan scan = new Scan(out, err, cp, db, verbose);
+
+ for (String a : args) {
+ boolean success;
+
+ if (a.endsWith(".jar")) {
+ success = scan.scanJar(a);
+ } else if (Files.isDirectory(Paths.get(a))) {
+ success = scan.scanDir(a);
+ } else {
+ success = scan.processClassName(a.replace('.', '/'));
+ }
+
+ if (!success) {
+ return false;
+ }
+ }
+ break;
+ }
+
+ return true;
+ }
+
+ /**
+ * Programmatic main entry point: initializes the tool instance to
+ * use stdout and stderr; runs the tool, passing command-line args;
+ * returns an exit status.
+ *
+ * @return true on success, false otherwise
+ */
+ public static boolean call(PrintStream out, PrintStream err, String... args) {
+ try {
+ instance = new Main(out, err);
+ return instance.run(args);
+ } finally {
+ instance = null;
+ }
+ }
+
+ /**
+ * Calls the main entry point and exits the JVM with an exit
+ * status determined by the return status.
+ */
+ public static void main(String[] args) {
+ System.exit(call(System.out, System.err, args) ? 0 : 1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Messages.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Message handling class for localization.
+ */
+public class Messages {
+ static final ResourceBundle bundle;
+
+ static {
+ Locale locale = Locale.getDefault();
+ try {
+ bundle = ResourceBundle.getBundle("com.sun.tools.jdeprscan.resources.jdeprscan", locale);
+ } catch (MissingResourceException e) {
+ throw new InternalError("Cannot find jdeps resource bundle for locale " + locale, e);
+ }
+ }
+
+ public static String get(String key, Object... args) {
+ try {
+ return MessageFormat.format(bundle.getString(key), args);
+ } catch (MissingResourceException e) {
+ throw new InternalError("Missing message: " + key, e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Pretty.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Utility class for pretty-printing various bits of API syntax.
+ */
+public class Pretty {
+ /**
+ * Converts deprecation information into an {@code @Deprecated} annotation.
+ * The output is minimized: an empty since string is omitted, a forRemoval
+ * value of false is omitted; and if both are omitted, the trailing parentheses
+ * are also omitted.
+ *
+ * @param since the since value
+ * @param forRemoval the forRemoval value
+ * @return string containing an annotation
+ */
+ static String depr(String since, boolean forRemoval) {
+ String d = "@Deprecated";
+
+ if (since.isEmpty() && !forRemoval) {
+ return d;
+ }
+
+ StringBuilder sb = new StringBuilder(d).append('(');
+
+ if (!since.isEmpty()) {
+ sb.append("since=\"")
+ .append(since.replace("\"", "\\\""))
+ .append('"');
+ }
+
+ if (forRemoval) {
+ if (!since.isEmpty()) {
+ sb.append(", ");
+ }
+ sb.append("forRemoval=true");
+ }
+
+ sb.append(')');
+
+ return sb.toString();
+ }
+
+ /**
+ * Converts a slash-$ style name into a dot-separated name.
+ *
+ * @param n the input name
+ * @return the result name
+ */
+ static String unslashify(String n) {
+ return n.replace("/", ".")
+ .replace("$", ".");
+ }
+
+ /**
+ * Converts a type descriptor to a readable string.
+ *
+ * @param desc the input descriptor
+ * @return the result string
+ */
+ static String desc(String desc) {
+ return desc(desc, new int[] { 0 });
+ }
+
+ /**
+ * Converts one type descriptor to a readable string, starting
+ * from position {@code pos_inout[0]}, and updating it to the
+ * location following the descriptor just parsed. A type descriptor
+ * mostly corresponds to a FieldType in JVMS 4.3.2. It can be one of a
+ * BaseType (a single character denoting a primitive, plus void),
+ * an object type ("Lname;"), or an array type (one more more '[' followed
+ * by a base or object type).
+ *
+ * @param desc a string possibly containing several descriptors
+ * @param pos_inout on input, the start position; on return, the position
+ * following the just-parsed descriptor
+ * @return the result string
+ */
+ static String desc(String desc, int[] pos_inout) {
+ int dims = 0;
+ int pos = pos_inout[0];
+ final int len = desc.length();
+
+ while (pos < len && desc.charAt(pos) == '[') {
+ pos++;
+ dims++;
+ }
+
+ String name;
+
+ if (pos >= len) {
+ return null;
+ }
+
+ char c = desc.charAt(pos++);
+ switch (c) {
+ case 'Z':
+ name = "boolean";
+ break;
+ case 'B':
+ name = "byte";
+ break;
+ case 'S':
+ name = "short";
+ break;
+ case 'C':
+ name = "char";
+ break;
+ case 'I':
+ name = "int";
+ break;
+ case 'J':
+ name = "long";
+ break;
+ case 'F':
+ name = "float";
+ break;
+ case 'D':
+ name = "double";
+ break;
+ case 'V':
+ name = "void";
+ break;
+ case 'L':
+ int semi = desc.indexOf(';', pos);
+ if (semi == -1) {
+ return null;
+ }
+ name = unslashify(desc.substring(pos, semi));
+ pos = semi + 1;
+ break;
+ default:
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder(name);
+ for (int i = 0; i < dims; i++) {
+ sb.append("[]");
+ }
+ pos_inout[0] = pos;
+ return sb.toString();
+ }
+
+ /**
+ * Converts a series of type descriptors into a comma-separated,
+ * readable string. This is used for the parameter types of a
+ * method descriptor.
+ *
+ * @param types the parameter types
+ * @return the readable string
+ */
+ static String parms(String types) {
+ int[] pos = new int[] { 0 };
+ StringBuilder sb = new StringBuilder();
+
+ boolean first = true;
+
+ String t;
+
+ while ((t = desc(types, pos)) != null) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(',');
+ }
+ sb.append(t);
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Pattern for matching a method descriptor. Match results can
+ * be retrieved from named capture groups as follows: "name(params)return".
+ */
+ static final Pattern DESC_PAT = Pattern.compile("(?<name>.*)\\((?<args>.*)\\)(?<return>.*)");
+
+ /**
+ * Pretty-prints the data contained in the given DeprData object.
+ *
+ * @param dd the deprecation data object
+ * @return the formatted string
+ */
+ public static String print(DeprData dd) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(depr(dd.since, dd.forRemoval))
+ .append(' ');
+
+ switch (dd.kind) {
+ case ANNOTATION_TYPE:
+ sb.append("@interface ");
+ sb.append(unslashify(dd.typeName));
+ break;
+ case CLASS:
+ sb.append("class ");
+ sb.append(unslashify(dd.typeName));
+ break;
+ case ENUM:
+ sb.append("enum ");
+ sb.append(unslashify(dd.typeName));
+ break;
+ case INTERFACE:
+ sb.append("interface ");
+ sb.append(unslashify(dd.typeName));
+ break;
+
+ case ENUM_CONSTANT:
+ case FIELD:
+ sb.append(unslashify(dd.typeName))
+ .append('.')
+ .append(dd.nameSig);
+ break;
+ case CONSTRUCTOR:
+ Matcher cons = DESC_PAT.matcher(dd.nameSig);
+ sb.append(unslashify(dd.typeName));
+ if (cons.matches()) {
+ sb.append('(')
+ .append(parms(cons.group("args")))
+ .append(')');
+ } else {
+ sb.append('.')
+ .append(dd.nameSig);
+ }
+ break;
+ case METHOD:
+ Matcher meth = DESC_PAT.matcher(dd.nameSig);
+ if (meth.matches()) {
+ sb.append(desc(meth.group("return")))
+ .append(' ')
+ .append(unslashify(dd.typeName))
+ .append('.')
+ .append(meth.group("name"))
+ .append('(')
+ .append(parms(meth.group("args")))
+ .append(')');
+ } else {
+ sb.append(unslashify(dd.typeName))
+ .append('.')
+ .append(dd.nameSig);
+ }
+ break;
+ }
+
+ return sb.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/TraverseProc.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Messager;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
+
+import static javax.lang.model.SourceVersion.RELEASE_9;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.PackageElement;
+import javax.tools.Diagnostic;
+
+@SupportedSourceVersion(RELEASE_9)
+@SupportedAnnotationTypes("*")
+public class TraverseProc extends AbstractProcessor {
+ Elements elements;
+ Messager messager;
+ final List<String> moduleRoots;
+ Map<PackageElement, List<TypeElement>> publicTypes;
+
+ TraverseProc(List<String> roots) {
+ moduleRoots = roots;
+ }
+
+ @Override
+ public void init(ProcessingEnvironment pe) {
+ super.init(pe);
+ elements = pe.getElementUtils();
+ messager = pe.getMessager();
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (roundEnv.processingOver()) {
+ return false;
+ }
+
+ Set<ModuleElement> modules = new HashSet<>();
+ for (String mname : moduleRoots) {
+ ModuleElement me = elements.getModuleElement(mname);
+ if (me == null) {
+ messager.printMessage(Diagnostic.Kind.ERROR,
+ String.format("module %s not found%n", mname));
+ } else {
+ modules.addAll(findModules(me));
+ }
+ }
+
+ Set<PackageElement> packages = findPackages(modules);
+
+ publicTypes = findPublicTypes(packages);
+
+ return true;
+ }
+
+ void printPublicTypes() {
+ printPublicTypes(publicTypes);
+ }
+
+ public Map<PackageElement, List<TypeElement>> getPublicTypes() {
+ return publicTypes;
+ }
+
+ void printPublicTypes(Map<PackageElement, List<TypeElement>> types) {
+ System.out.println("All public types:");
+ types.entrySet().stream()
+ .sorted(Comparator.comparing(e -> e.getKey().toString()))
+ .forEach(e -> {
+ System.out.println(" " + e.getKey());
+ e.getValue().stream()
+ .sorted(Comparator.comparing(TypeElement::toString))
+ .forEach(t -> System.out.println(" " + t));
+ });
+ System.out.println();
+ System.out.flush();
+ }
+
+ Set<ModuleElement> findModules(ModuleElement root) {
+ return findModules0(root, new HashSet<>(), 0);
+ }
+
+ Set<ModuleElement> findModules0(ModuleElement m, Set<ModuleElement> set, int nesting) {
+ set.add(m);
+ for (ModuleElement.Directive dir : m.getDirectives()) {
+ if (dir.getKind() == ModuleElement.DirectiveKind.REQUIRES) {
+ ModuleElement.RequiresDirective req = (ModuleElement.RequiresDirective)dir;
+ findModules0(req.getDependency(), set, nesting + 1);
+ }
+ }
+ return set;
+ }
+
+ Set<PackageElement> findPackages(Collection<ModuleElement> mods) {
+ Set<PackageElement> set = new HashSet<>();
+ for (ModuleElement m : mods) {
+ for (ModuleElement.Directive dir : m.getDirectives()) {
+ if (dir.getKind() == ModuleElement.DirectiveKind.EXPORTS) {
+ ModuleElement.ExportsDirective exp = (ModuleElement.ExportsDirective)dir;
+ if (exp.getTargetModules() == null) {
+ set.add(exp.getPackage());
+ }
+ }
+ }
+ }
+ return set;
+ }
+
+ Map<PackageElement, List<TypeElement>> findPublicTypes(Collection<PackageElement> pkgs) {
+ Map<PackageElement, List<TypeElement>> map = new HashMap<>();
+ for (PackageElement pkg : pkgs) {
+ List<TypeElement> enclosed = new ArrayList<>();
+ for (Element e : pkg.getEnclosedElements()) {
+ addPublicTypes(enclosed, e);
+ }
+ map.put(pkg, enclosed);
+ }
+ return map;
+ }
+
+ void addPublicTypes(List<TypeElement> list, Element e) {
+ ElementKind kind = e.getKind();
+ if ((kind.isClass() || kind.isInterface())
+ && e.getModifiers().contains(Modifier.PUBLIC)) {
+ list.add((TypeElement)e);
+ for (Element enc : e.getEnclosedElements()) {
+ addPublicTypes(list, enc);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/internals.md Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,215 @@
+<!--
+
+Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation. Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-->
+
+
+JDeprScan Internals
+-----
+
+**EXPERIMENTAL OPTIONS**
+
+ --Xload-class CLASSNAME
+
+ Loads deprecation data from the class named CLASSNAME instead of from
+ the JDK image.
+
+ --Xload-csv CVSFILE
+
+ Loads deprecation data from file CSVFILE.
+
+ --Xload-dir DIR
+
+ Loads deprecation data from the class hierarchy rooted
+ at the directory named DIR.
+
+ --Xload-jar JARFILE
+
+ Loads deprecation data from the classes contained in the
+ jar file named JARFILE.
+
+ --Xload-jdk9 JAVA_HOME
+
+ Loads deprecation data from a modular JDK whose home
+ directory is at JAVA_HOME. This essentially adds the given
+ path to the system-modules location.
+
+ --Xload-old-jdk JAVA_HOME
+
+ Loads deprecation data from an old (non-modular) JDK whose
+ home directory is at JAVA_HOME. This essentially scans the
+ rt.jar file from that JDK.
+
+ --Xload-self
+
+ Loads deprecation data from the running JDK image by
+ traversing the entire jrt: filesystem. This differs from
+ -release 9, which traverses modules, packages, and classes by
+ starting from a set of root modules and using javax.lang.model
+ mechanisms (as opposed to filesystem mechanisms) for
+ traversing contained elements recursively.
+
+ --Xcompiler-arg ARG
+
+ Adds ARG to the list of arguments passed to the compiler.
+
+ --Xcsv-comment COMMENT
+
+ Adds a comment line containing COMMENT to the top of the CSV
+ that is emitted. Valid only when --Xprint-csv is
+ specified. More than one --Xcsv-comment option is permitted,
+ which will cause a corresponding number of comment lines to be
+ emitted to the CSV file.
+
+ --Xprint-csv
+
+ Prints out the loaded deprecation information in CSV format
+ to standard output. In this mode, no scanning is done, so
+ there must not be any additional directory, jar, or classname
+ arguments.
+
+**CSV FILE SYNTAX**
+
+The `-Xprint-csv` option causes **jdeprscan** to emit the loaded
+deprecation data in CSV (comma-separated value) format. The general
+syntax of CSV is documented in [RFC 4180][RFC] with supplemental
+information in a [Wikipedia article][wiki].
+
+The file is encoded in UTF-8.
+
+The file consists of a series of lines. Any of the standard line
+separators CR (U+000D), LF (U+000A), or a CR immediately followed by
+LF, are supported. Newlines are only supported between records and
+are not supported within field values.
+
+Comment lines start with a `#` (U+0023) character in the first
+column. The entire line is ignored up until the next line separator
+sequence.
+
+Each line is divided into fields separated by the comma `,` (U+002C)
+character. Horizontal whitespace is not treated specially; that is,
+it is considered part of a field's value. An empty line is considered
+to have one field which is the empty string.
+
+A field value that contains a comma or a quote quotation mark `"`
+(U+0022) must be surrounded by quotation marks. The surrounding
+quotation marks are not considered part of the field value. Any
+quotation marks that are part of a field value must be repeated in
+addition to being surrounded by quotation marks.
+
+It is a syntax error if a quotation mark appears within an unquoted field;
+if a quoted field isn't immediately followed by a comma or line
+separator; or if a quoted field is left unclosed at the end of the line.
+
+For example, a record with the following four fields:
+
+1. abcd
+2. ef,gh
+3. ij"kl
+4. mnop
+
+would be encoded as follows:
+
+ abcd,"ef,gh","ij""kl",mnop
+
+**CSV FILE DATA**
+
+The first line of output must be the following:
+
+ #jdepr1
+
+This is strictly a comment line, but it serves as a file
+identifier. The "1" indicates version 1 of this file.
+
+Zero or more comment lines follow, containing text that is specified
+by the `-Xcsv-comment` options.
+
+Subsequent non-comment lines must have the following five fields:
+
+ kind,typeName,descOrName,since,forRemoval
+
+Fields are defined as follows:
+
+ * _kind_ - one of CONSTRUCTOR, FIELD, METHOD, ENUM\_CONSTANT,
+ CLASS, INTERFACE, ENUM, or ANNOTATION\_TYPE. These correspond to
+ enumeration constants from the `javax.lang.model.element.ElementKind`
+ enum.
+
+ * _typeName_ - the fully qualified name of the type (if *kind* is
+ CLASS, INTERFACE, ENUM, or ANNOTATION\_TYPE) or of the enclosing
+ type (if _kind_ is CONSTRUCTOR, FIELD, METHOD, or
+ ENUM\_CONSTANT). This value is a _binary name_ [JLS 13.1][jls131]
+ using a slash character `/` (U+002F) to separate package and
+ top-level name components, and a dollar sign `$` (U+0024) to
+ separate nested name components. For example, the `Thread.State`
+ enum that appears in Java SE would have the following typeName:
+
+ java/lang/Thread$State
+
+ * _descOrName_ - if _kind_ is METHOD or CONSTRUCTOR, this is the method's
+ or constructor's descriptor [JVMS 4.3.3][jvms433]; if _kind_ is FIELD or
+ ENUM\_CONSTANT, this is its name; otherwise this field is empty.
+ A method's descriptor includes its name, parameter types, and return
+ type. For example, the method
+
+ public void String.getBytes(int srcBegin,
+ int srcEnd,
+ byte[] dst,
+ int dstBegin)
+
+ has the descriptor
+
+ getBytes(II[BI)V
+
+ * _since_ - the value of the `since` element of the `@Deprecated`
+ annotation, or empty if this element is not present.
+
+ * _forRemoval_ - the value of the `forRemoval` element of the
+ `@Deprecated` annotation, a boolean, either "true" or "false".
+
+Note that the _since_ field can have arbitrary text (excluding
+line separators) and is thus subject to quoting.
+
+**EXAMPLE OUTPUT**
+
+Given the following method declaration and annotation from the
+`java.lang.Runtime` class,
+
+ @Deprecated(since="1.2",
+ forRemoval=true)
+ public static void runFinalizersOnExit(boolean value)
+
+the following line will be emitted from **jdeprscan -Xprint-csv**:
+
+ METHOD,java/lang/Runtime,runFinalizersOnExit(Z)V,1.2,true
+
+
+[RFC]: https://www.ietf.org/rfc/rfc4180.txt
+
+[wiki]: https://en.wikipedia.org/wiki/Comma-separated_values
+
+[jls131]: http://docs.oracle.com/javase/specs/jls/se8/html/jls-13.html#jls-13.1
+
+[jvms433]: http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/readme.md Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,180 @@
+<!--
+
+Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation. Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-->
+
+
+JDeprScan Tool Command Reference
+-----
+
+**NAME**
+
+ jdeprscan - Java deprecation scanner
+
+**SYNOPSIS**
+
+ jdeprscan [options] {dir | jar | class} ...
+
+**OPTIONS**
+
+ -cp PATH
+ --class-path PATH
+
+ Sets the classpath to PATH.
+
+ --for-removal
+
+ Limit reporting to deprecations whose forRemoval element
+ is true.
+
+ --full-version
+
+ Prints the full version string of the tool and exits.
+
+ -h
+ --help
+
+ Prints a help message and exits.
+
+ -l
+ --list
+
+ Prints out the set of deprecated APIs.
+
+ --release 6|7|8|9
+
+ Specifies the Java SE release that is the source of
+ the list of deprecated APIs. If no --release option is
+ provided, the latest release is used.
+
+ -v
+ --verbose
+
+ Enables additional output.
+
+ --version
+
+ Prints the version string of the tool and exits.
+
+**DESCRIPTION**
+
+**jdeprscan** scans a class library for uses of deprecated APIs.
+**jdeprscan** processes one or more arguments, which can be any
+combination of a directory, a jar file, or a class name.
+
+A directory argument must specify a path to a directory hierarchy that
+reflects the Java package hierarchy of the classes it contains.
+**jdeprscan** will scan each class found in the directory hierarchy
+and report information about how those classes use deprecated APIs.
+
+Given a jar file, **jdeprscan** will scan the classes found within
+that jar file and report information about how those classes use
+deprecated APIs.
+
+Given a class name, **jdeprscan** will search for that class on the
+classpath, scan that class, and report information about how that
+class uses deprecated APIs. The class name must use the fully
+qualified binary name of the class, as described in the
+[Java Language Specification, section 13.1][jls131]. This form uses
+the '$' character instead of '.' as the separator for nested class names.
+For example, the `Thread.State` enum would be specified using the string
+
+ java.lang.Thread$State
+
+The `--class-path` and `-cp` options specify the classpath used for
+class searching. The classpath is used for classes named on the
+command line, as well as for dependencies of the classes in jar file
+or directory hierarchy to be scanned.
+
+The `--for-removal` option limits output to uses of deprecated APIs
+whose `@Deprecated` annotation includes the `forRemoval` element with
+the value `true`. Note: the `forRemoval` attribute of the
+`@Deprecated` annotation did not exist prior to Java SE 9, so this
+option cannot be used with a release value of 6, 7, or 8.
+
+The `--release` option specifies the Java SE specification version
+that determines the set of deprecated APIs for which scanning is
+done. This is useful if a deprecation report is desired that lists
+uses of deprecated APIs as of a particular release in the past. If no
+`--release` option is given, the latest release is used.
+
+The `--list` and `-l` options will list the known set of deprecated
+APIs instead of doing any scanning. Since no scanning is done,
+no directory, jar, or class arguments should be provided. The set
+of deprecated APIs listed is affected by the `--release` and the
+`--for-removal` options.
+
+
+**EXAMPLE OUTPUT**
+
+The output is a report that lists program elements that use deprecated
+APIs. Output is subject to change.
+
+Consider the following declarations from Java SE 9:
+
+ // java.lang.Boolean
+
+ @Deprecated(since="9")
+ public Boolean(boolean value)
+
+ // java.lang.Runtime
+
+ @Deprecated(since="1.2", forRemoval=true)
+ public static void runFinalizersOnExit(boolean value)
+
+Running **jdeprscan** over a class that calls these methods will result
+in output something like the following:
+
+ class Example uses method java/lang/Boolean.<init>(Z)V deprecated
+ class Example uses method java/lang/Runtime.runFinalizersOnExit(Z)V deprecated for removal
+
+Running **jdeprscan** with the `--list` option will result in output
+including something like the following:
+
+ ...
+ @Deprecated(since="9") java.lang.Boolean(boolean)
+ @Deprecated(since="1.2", forRemoval=true) void java.lang.Runtime.runFinalizersOnExit(boolean)
+ ...
+
+**NOTES**
+
+The **jdeprscan** tool operates by opening Java class files and
+reading their structures directly, particularly the constant
+pool. Because of this, **jdeprscan** can tell _that_ a deprecated API
+is used, but it often cannot tell _where_ in the class that API is
+used.
+
+The **jdeprscan** tool doesn't follow the same set of rules for
+emitting warnings as specified for Java compilers in [JLS section
+9.6.4.6][jls9646]. In particular, **jdeprscan** does not respond to
+the `@SuppressWarnings` annotation, as that is significant only in
+source code, not in class files. In addition, **jdeprscan** emits
+warnings even if the usage is within the API element that is
+deprecated and when the use and declaration are within the same
+outermost class.
+
+[jls9646]: http://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.4.6
+
+[jls131]: http://docs.oracle.com/javase/specs/jls/se8/html/jls-13.html#jls-13.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/resources/jdeprscan.properties Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,96 @@
+main.usage=\
+Usage: jdeprscan [options] '{dir|jar|class}' ...\n\
+\n\
+options:\n\
+\ -cp --class-path PATH\n\
+\ --for-removal\n\
+\ --full-version\n\
+\ -h --help\n\
+\ -l --list\n\
+\ --release 6|7|8|9\n\
+\ -v --verbose\n\
+\ --version
+
+main.help=\
+Scans each argument for usages of deprecated APIs. An argument\n\
+may be a directory specifying the root of a package hierarchy,\n\
+a JAR file, or a class name. The class name must be specified\n\
+using a fully qualified class name using the $ separator character\n\
+for nested classes, for example,\n\
+\n\
+\ java.lang.Thread$State\n\
+\n\
+The --class-path (-cp) option provides a search path for resolution\n\
+of dependent classes.\n\
+\n\
+The --for-removal option limits scanning or listing to APIs that are\n\
+deprecated for removal. Cannot be used with a release value of 6, 7, or 8.\n\
+\n\
+The --full-version option prints out the full version string of the tool.\n\
+\n\
+The --help option prints out a full help message.\n\
+\n\
+The --list (-l) option prints out the set of deprecated APIs. No scanning is done,\n\
+so no directory, jar, or class arguments should be provided.\n\
+\n\
+The --release option specifies the Java SE release that provides the set\n\
+of deprecated APIs for scanning.\n\
+\n\
+The --verbose (-v) option enables additional message output during processing.\n\
+\n\
+The --version option prints out the abbreviated version string of the tool.
+
+main.xhelp=\
+Unsupported options:\n\
+\n\
+\ --Xload-class CLASS\n\
+\ Loads deprecation information from the named class.\n\
+\ --Xload-csv CSVFILE\n\
+\ Loads deprecation information from the named CSV file.\n\
+\ --Xload-dir DIR\n\
+\ Loads deprecation information from the class hierarchy\n\
+\ at the named directory.\n\
+\ --Xload-jar JARFILE\n\
+\ Loads deprecation information from the named JAR file.\n\
+\ --Xload-jdk9 JAVA_HOME\n\
+\ Loads deprecation information from the JDK located at\n\
+\ JAVA_HOME, which must be a modular JDK.\n\
+\ --Xload-old-jdk JAVA_HOME\n\
+\ Loads deprecation information from the JDK located at\n\
+\ JAVA_HOME, which must not be a modular JDK. Instead, the\n\
+\ named JDK must be a "classic" JDK with an rt.jar file.\n\
+\ --Xload-self\n\
+\ Loads deprecation information by traversing the jrt:\n\
+\ filesystem of the running JDK image.\n\
+\ --Xcompiler-arg ARG\n\
+\ Adds ARG to the list of compiler arguments.\n\
+\ --Xcsv-comment COMMENT\n\
+\ Adds COMMENT as a comment line to the output CSV file.\n\
+\ Only effective if -Xprint-csv is also supplied.\n\
+\ --Xhelp\n\
+\ Prints this message.\n\
+\ --Xprint-csv\n\
+\ Prints a CSV file containing the loaded deprecation information\n\
+\ instead of scanning any classes or JAR files.
+
+error.prefix=Error:
+
+scan.process.class=Processing class {0}...
+
+scan.dep.normal=deprecated
+scan.dep.removal=deprecated FOR REMOVAL
+
+scan.out.extends={0} {1} extends class {2} {3}
+scan.out.implements={0} {1} implements interface {2} {3}
+scan.out.usestype={0} {1} uses type {2} {3}
+scan.out.usesmethodintype={0} {1} uses method in type {2} {3}
+scan.out.usesmethod={0} {1} uses method {2} {3} {4} {5}
+scan.out.usesintfmethodintype={0} {1} uses interface method in type {2} {3}
+scan.out.usesintfmethod={0} {1} uses interface method {2} {3} {4} {5}
+scan.out.usesfieldintype={0} {1} uses field in type {2} {3}
+scan.out.usesfield={0} {1} uses field {2} {3} {4}
+scan.out.usesfieldoftype={0} {1} uses field of type {2} {3} {4} {5}
+scan.out.hasfield={0} {1} has field {2} of type {3} {4}
+scan.out.methodparmtype={0} {1} method {2} has parameter type {3} {4}
+scan.out.methodrettype={0} {1} method {2} has return type {3} {4}
+scan.out.methodoverride={0} {1} overrides method {2} {3} {4} {5}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/scan/CPEntries.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan.scan;
+
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.List;
+import java.util.Locale;
+
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPool;
+
+import static com.sun.tools.classfile.ConstantPool.CPInfo;
+
+/**
+ * A container for selected constant pool entries. There are currently
+ * lists that contain the following types of CP entries:
+ *
+ * - CONSTANT_Class_info
+ * - CONSTANT_Fieldref_info
+ * - CONSTANT_Methodref_info
+ * - CONSTANT_InterfaceMethodref_info
+ */
+class CPEntries {
+ final List<ConstantPool.CONSTANT_Class_info> classes = new ArrayList<>();
+ final List<ConstantPool.CONSTANT_Fieldref_info> fieldRefs = new ArrayList<>();
+ final List<ConstantPool.CONSTANT_Methodref_info> methodRefs = new ArrayList<>();
+ final List<ConstantPool.CONSTANT_InterfaceMethodref_info> intfMethodRefs = new ArrayList<>();
+
+ public static CPEntries loadFrom(ClassFile cf) {
+ CPEntries entries = new CPEntries();
+ for (CPInfo cpi : cf.constant_pool.entries()) {
+ cpi.accept(new CPSelector(), entries);
+ }
+ return entries;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ Formatter f = new Formatter(sb, Locale.getDefault());
+ f.format("Classes:%n");
+ f.format("%s%n", classes);
+ f.format("FieldRefs:%n");
+ f.format("%s%n", fieldRefs);
+ f.format("MethodRefs:%n");
+ f.format("%s%n", methodRefs);
+ f.format("InterfaceMethodRefs:%n");
+ f.format("%s%n", intfMethodRefs);
+ f.flush();
+ return sb.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/scan/CPSelector.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan.scan;
+
+import com.sun.tools.classfile.ConstantPool;
+
+/**
+ * A visitor that selects constant pool entries by type and adds
+ * them to the given CPEntries object.
+ */
+class CPSelector implements ConstantPool.Visitor<Void,CPEntries> {
+ @Override
+ public Void visitClass(ConstantPool.CONSTANT_Class_info info, CPEntries p) {
+ p.classes.add(info);
+ return null;
+ }
+
+ @Override
+ public Void visitDouble(ConstantPool.CONSTANT_Double_info info, CPEntries p) {
+ return null;
+ }
+
+ @Override
+ public Void visitFieldref(ConstantPool.CONSTANT_Fieldref_info info, CPEntries p) {
+ p.fieldRefs.add(info);
+ return null;
+ }
+
+ @Override
+ public Void visitFloat(ConstantPool.CONSTANT_Float_info info, CPEntries p) {
+ return null;
+ }
+
+ @Override
+ public Void visitInteger(ConstantPool.CONSTANT_Integer_info info, CPEntries p) {
+ return null;
+ }
+
+ @Override
+ public Void visitInterfaceMethodref(ConstantPool.CONSTANT_InterfaceMethodref_info info, CPEntries p) {
+ p.intfMethodRefs.add(info);
+ return null;
+ }
+
+ @Override
+ public Void visitInvokeDynamic(ConstantPool.CONSTANT_InvokeDynamic_info info, CPEntries p) {
+ return null;
+ }
+
+ @Override
+ public Void visitLong(ConstantPool.CONSTANT_Long_info info, CPEntries p) {
+ return null;
+ }
+
+ @Override
+ public Void visitNameAndType(ConstantPool.CONSTANT_NameAndType_info info, CPEntries p) {
+ return null;
+ }
+
+ @Override
+ public Void visitMethodref(ConstantPool.CONSTANT_Methodref_info info, CPEntries p) {
+ p.methodRefs.add(info);
+ return null;
+ }
+
+ @Override
+ public Void visitMethodHandle(ConstantPool.CONSTANT_MethodHandle_info info, CPEntries p) {
+ return null;
+ }
+
+ @Override
+ public Void visitMethodType(ConstantPool.CONSTANT_MethodType_info info, CPEntries p) {
+ return null;
+ }
+
+ @Override
+ public Void visitString(ConstantPool.CONSTANT_String_info info, CPEntries p) {
+ return null;
+ }
+
+ @Override
+ public Void visitUtf8(ConstantPool.CONSTANT_Utf8_info info, CPEntries p) {
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/scan/ClassFinder.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan.scan;
+
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Stream;
+
+/**
+ * A simple search path for classes.
+ */
+public class ClassFinder {
+ final List<PathEntry> list = new ArrayList<>();
+ final boolean verbose;
+
+ public ClassFinder(boolean verbose) {
+ this.verbose = verbose;
+ }
+
+ /**
+ * Adds a directory to this finder's search path, ignoring errors.
+ *
+ * @param dirName the directory to add
+ */
+ public void addDir(String dirName) {
+ Path dir = Paths.get(dirName);
+
+ if (Files.isDirectory(dir)) {
+ list.add(new DirPathEntry(dir));
+ }
+ }
+
+ /**
+ * Adds a jar file to this finder's search path, ignoring errors.
+ *
+ * @param jarName the jar file name to add
+ */
+ public void addJar(String jarName) {
+ try {
+ list.add(new JarPathEntry(new JarFile(jarName)));
+ } catch (IOException ignore) { }
+ }
+
+ /**
+ * Adds the JRT filesystem to this finder's search path.
+ */
+ public void addJrt() {
+ list.add(new JrtPathEntry());
+ }
+
+ /**
+ * Searches the class path for a class with the given name,
+ * returning a ClassFile for it. Returns null if not found.
+ *
+ * @param className the class to search for
+ * @return a ClassFile instance, or null if not found
+ */
+ public ClassFile find(String className) {
+ for (PathEntry pe : list) {
+ ClassFile cf = pe.find(className);
+ if (cf != null) {
+ return cf;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * An entry in this finder's class path.
+ */
+ interface PathEntry {
+ /**
+ * Returns a ClassFile instance corresponding to this name,
+ * or null if it's not present in this entry.
+ *
+ * @param className the class to search for
+ * @return a ClassFile instance, or null if not found
+ */
+ ClassFile find(String className);
+ }
+
+ /**
+ * An entry that represents a jar file.
+ */
+ class JarPathEntry implements PathEntry {
+ final JarFile jarFile;
+
+ JarPathEntry(JarFile jf) {
+ jarFile = jf;
+ }
+
+ @Override
+ public ClassFile find(String className) {
+ JarEntry entry = jarFile.getJarEntry(className + ".class");
+ if (entry == null) {
+ return null;
+ }
+ try {
+ return ClassFile.read(jarFile.getInputStream(entry));
+ } catch (IOException | ConstantPoolException ex) {
+ if (verbose) {
+ ex.printStackTrace();
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * An entry that represents a directory containing a class hierarchy.
+ */
+ class DirPathEntry implements PathEntry {
+ final Path dir;
+
+ DirPathEntry(Path dir) {
+ this.dir = dir;
+ }
+
+ @Override
+ public ClassFile find(String className) {
+ Path classFileName = dir.resolve(className + ".class");
+ try {
+ return ClassFile.read(classFileName);
+ } catch (NoSuchFileException nsfe) {
+ // not found, return silently
+ } catch (IOException | ConstantPoolException ex) {
+ if (verbose) {
+ ex.printStackTrace();
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * An entry that represents the JRT filesystem in the running image.
+ *
+ * JRT filesystem structure is:
+ * /packages/<dotted-pkgname>/<modlink>
+ * where modlink is a symbolic link to /modules/<modname> which is
+ * the top of the usual package-class hierarchy
+ */
+ class JrtPathEntry implements PathEntry {
+ final FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+
+ @Override
+ public ClassFile find(String className) {
+ int end = className.lastIndexOf('/');
+ if (end < 0) {
+ return null;
+ }
+ String pkg = "/packages/" + className.substring(0, end)
+ .replace('/', '.');
+ try (Stream<Path> mods = Files.list(fs.getPath(pkg))) {
+ Optional<Path> opath =
+ mods.map(path -> path.resolve(className + ".class"))
+ .filter(Files::exists)
+ .findFirst();
+ if (opath.isPresent()) {
+ return ClassFile.read(opath.get());
+ } else {
+ return null;
+ }
+ } catch (NoSuchFileException nsfe) {
+ // not found, return silently
+ } catch (IOException | ConstantPoolException ex) {
+ if (verbose) {
+ ex.printStackTrace();
+ }
+ }
+ return null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/scan/MethodSig.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan.scan;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Represents a method's signature, that is, its parameter types
+ * and its return type.
+ */
+public class MethodSig {
+ final List<String> parameters;
+ final String returnType;
+
+ /**
+ * Parses the method descriptor and returns a MethodSig instance.
+ *
+ * @param desc the descriptor to parse
+ * @return the new MethodSig instance
+ */
+ public static MethodSig fromDesc(String desc) {
+ return parse(desc, 0, desc.length());
+ }
+
+ /**
+ * Returns this method's return type.
+ *
+ * @return the return type
+ */
+ public String getReturnType() {
+ return returnType;
+ }
+
+ /**
+ * Returns a list of parameters of this method.
+ *
+ * @return the parameter list
+ */
+ public List<String> getParameters() {
+ return parameters;
+ }
+
+ /**
+ * Returns a string describing this method.
+ *
+ * @return the string description
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("parameters");
+ if (parameters.isEmpty()) {
+ sb.append(" none");
+ } else {
+ int i = 0;
+ for (String p : parameters) {
+ sb.append(String.format(" %d=%s", i++, p));
+ }
+ }
+ sb.append(String.format(" return %s", returnType));
+ return sb.toString();
+ }
+
+ private MethodSig(List<String> parameters, String returnType) {
+ this.parameters = Collections.unmodifiableList(parameters);
+ this.returnType = returnType;
+ }
+
+ private static IllegalArgumentException ex(String desc, int pos) {
+ return new IllegalArgumentException(String.format(
+ "illegal descriptor \"%s\" at position %d", desc, pos));
+ }
+
+ private static MethodSig parse(String desc, int start, int end)
+ throws IllegalArgumentException {
+ int p = start;
+ int dims = 0;
+ boolean inReturnType = false;
+ String returnType = null;
+ List<String> parameters = new ArrayList<>();
+
+ while (p < end) {
+ String type;
+ char ch;
+ switch (ch = desc.charAt(p)) {
+ case '(':
+ p++;
+ continue;
+
+ case ')':
+ p++;
+ inReturnType = true;
+ continue;
+
+ case '[':
+ p++;
+ dims++;
+ continue;
+
+ case 'B': // byte
+ case 'C': // char
+ case 'D': // double
+ case 'F': // float
+ case 'I': // int
+ case 'J': // long
+ case 'S': // short
+ case 'Z': // boolean
+ case 'V': // void
+ type = Character.toString(ch);
+ p++;
+ break;
+
+ case 'L':
+ int sep = desc.indexOf(';', p);
+ if (sep == -1 || sep >= end)
+ throw ex(desc, p);
+ type = desc.substring(p, ++sep);
+ p = sep;
+ break;
+
+ default:
+ throw ex(desc, p);
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for ( ; dims > 0; dims-- )
+ sb.append("[");
+ sb.append(type);
+ if (inReturnType) {
+ returnType = sb.toString();
+ } else {
+ parameters.add(sb.toString());
+ }
+ }
+
+ if (returnType == null) {
+ throw ex(desc, end);
+ }
+
+ return new MethodSig(parameters, returnType);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/scan/Scan.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,614 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeprscan.scan;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.jdeprscan.DeprData;
+import com.sun.tools.jdeprscan.DeprDB;
+import com.sun.tools.jdeprscan.Messages;
+
+import static com.sun.tools.classfile.AccessFlags.*;
+import static com.sun.tools.classfile.ConstantPool.*;
+
+/**
+ * An object that represents the scanning phase of deprecation usage checking.
+ * Given a deprecation database, scans the targeted directory hierarchy, jar
+ * file, or individual class for uses of deprecated APIs.
+ */
+public class Scan {
+ final PrintStream out;
+ final PrintStream err;
+ final List<String> classPath;
+ final DeprDB db;
+ final boolean verbose;
+
+ final ClassFinder finder;
+ boolean error = false;
+
+ public Scan(PrintStream out,
+ PrintStream err,
+ List<String> classPath,
+ DeprDB db,
+ boolean verbose) {
+ this.out = out;
+ this.err = err;
+ this.classPath = classPath;
+ this.db = db;
+ this.verbose = verbose;
+
+ ClassFinder f = new ClassFinder(verbose);
+
+ // TODO: this isn't quite right. If we've specified a release other than the current
+ // one, we should instead add a reference to the symbol file for that release instead
+ // of the current image. The problems are a) it's unclear how to get from a release
+ // to paths that reference the symbol files, as this might be internal to the file
+ // manager; and b) the symbol file includes .sig files, not class files, which ClassFile
+ // might not be able to handle.
+ f.addJrt();
+
+ for (String name : classPath) {
+ if (name.endsWith(".jar")) {
+ f.addJar(name);
+ } else {
+ f.addDir(name);
+ }
+ }
+
+ finder = f;
+ }
+
+ Pattern typePattern = Pattern.compile("\\[*L(.*);");
+
+ // "flattens" an array type name to its component type
+ // and a reference type "Lpkg/pkg/pkg/name;" to its base name
+ // "pkg/pkg/pkg/name".
+ // TODO: deal with primitive types
+ String flatten(String typeName) {
+ Matcher matcher = typePattern.matcher(typeName);
+ if (matcher.matches()) {
+ return matcher.group(1);
+ } else {
+ return typeName;
+ }
+ }
+
+ String typeKind(ClassFile cf) {
+ AccessFlags flags = cf.access_flags;
+ if (flags.is(ACC_ENUM)) {
+ return "enum";
+ } else if (flags.is(ACC_ANNOTATION)) {
+ return "@interface";
+ } else if (flags.is(ACC_INTERFACE)) {
+ return "interface";
+ } else {
+ return "class";
+ }
+ }
+
+ void printType(String key, ClassFile cf, String cname, boolean forRemoval)
+ throws ConstantPoolException {
+ String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
+ out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, dep));
+ }
+
+ void printMethod(String key, ClassFile cf, String cname, String mname, String rtype,
+ boolean forRemoval) throws ConstantPoolException {
+ String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
+ out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, mname, rtype, dep));
+ }
+
+ void printField(String key, ClassFile cf, String cname, String fname,
+ boolean forRemoval) throws ConstantPoolException {
+ String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
+ out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, fname, dep));
+ }
+
+ void printFieldType(String key, ClassFile cf, String cname, String fname, String type,
+ boolean forRemoval) throws ConstantPoolException {
+ String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
+ out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, fname, type, dep));
+ }
+
+ void printHasField(ClassFile cf, String fname, String type, boolean forRemoval)
+ throws ConstantPoolException {
+ String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
+ out.println(Messages.get("scan.out.hasfield", typeKind(cf), cf.getName(), fname, type, dep));
+ }
+
+ void printHasMethodParmType(ClassFile cf, String mname, String parmType, boolean forRemoval)
+ throws ConstantPoolException {
+ String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
+ out.println(Messages.get("scan.out.methodparmtype", typeKind(cf), cf.getName(), mname, parmType, dep));
+ }
+
+ void printHasMethodRetType(ClassFile cf, String mname, String retType, boolean forRemoval)
+ throws ConstantPoolException {
+ String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
+ out.println(Messages.get("scan.out.methodrettype", typeKind(cf), cf.getName(), mname, retType, dep));
+ }
+
+ void printHasOverriddenMethod(ClassFile cf, String overridden, String mname, String desc, boolean forRemoval)
+ throws ConstantPoolException {
+ String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
+ out.println(Messages.get("scan.out.methodoverride", typeKind(cf), cf.getName(), overridden,
+ mname, desc, dep));
+ }
+
+ // format should not have a newline
+ void err(String format, Object... args) {
+ error = true;
+ err.print("error: ");
+ err.printf(format, args);
+ err.println();
+ }
+
+ void printException(Exception ex) {
+ err.print(Messages.get("error.prefix"));
+ err.print(" ");
+ if (verbose) {
+ ex.printStackTrace(err);
+ } else {
+ err.print(ex);
+ }
+ }
+
+ /**
+ * Checks whether a member (method or field) is present in a class.
+ * The checkMethod parameter determines whether this checks for a method
+ * or for a field.
+ *
+ * @param targetClass the ClassFile of the class to search
+ * @param targetName the method or field's name
+ * @param targetDesc the methods descriptor (ignored if checkMethod is false)
+ * @param checkMethod true if checking for method, false if checking for field
+ * @return boolean indicating whether the member is present
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ boolean isMemberPresent(ClassFile targetClass,
+ String targetName,
+ String targetDesc,
+ boolean checkMethod)
+ throws ConstantPoolException {
+ if (checkMethod) {
+ for (Method m : targetClass.methods) {
+ String mname = m.getName(targetClass.constant_pool);
+ String mdesc = targetClass.constant_pool.getUTF8Value(m.descriptor.index);
+ if (targetName.equals(mname) && targetDesc.equals(mdesc)) {
+ return true;
+ }
+ }
+ } else {
+ for (Field f : targetClass.fields) {
+ String fname = f.getName(targetClass.constant_pool);
+ if (targetName.equals(fname)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Adds all interfaces from this class to the deque of interfaces.
+ *
+ * @param intfs the deque of interfaces
+ * @param cf the ClassFile of this class
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ void addInterfaces(Deque<String> intfs, ClassFile cf)
+ throws ConstantPoolException {
+ int count = cf.interfaces.length;
+ for (int i = 0; i < count; i++) {
+ intfs.addLast(cf.getInterfaceName(i));
+ }
+ }
+
+ /**
+ * Resolves a member by searching this class and all its superclasses and
+ * implemented interfaces.
+ *
+ * TODO: handles a few too many cases; needs cleanup.
+ *
+ * TODO: refine error handling
+ *
+ * @param cf the ClassFile of this class
+ * @param startClassName the name of the class at which to start searching
+ * @param findName the member name to search for
+ * @param findDesc the method descriptor to search for (ignored for fields)
+ * @param resolveMethod true if resolving a method, false if resolving a field
+ * @param checkStartClass true if the start class should be searched, false if
+ * it should be skipped
+ * @return the name of the class where the member resolved, or null
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ String resolveMember(
+ ClassFile cf, String startClassName, String findName, String findDesc,
+ boolean resolveMethod, boolean checkStartClass)
+ throws ConstantPoolException {
+ ClassFile startClass;
+
+ if (cf.getName().equals(startClassName)) {
+ startClass = cf;
+ } else {
+ startClass = finder.find(startClassName);
+ if (startClass == null) {
+ err("can't find class %s", startClassName);
+ return startClassName;
+ }
+ }
+
+ // follow super_class until it's 0, meaning we've reached Object
+ // accumulate interfaces of superclasses as we go along
+
+ ClassFile curClass = startClass;
+ Deque<String> intfs = new ArrayDeque<>();
+ while (true) {
+ if ((checkStartClass || curClass != startClass) &&
+ isMemberPresent(curClass, findName, findDesc, resolveMethod)) {
+ break;
+ }
+
+ if (curClass.super_class == 0) { // reached Object
+ curClass = null;
+ break;
+ }
+
+ String superName = curClass.getSuperclassName();
+ curClass = finder.find(superName);
+ if (curClass == null) {
+ err("can't find class %s", superName);
+ break;
+ }
+ addInterfaces(intfs, curClass);
+ }
+
+ // search interfaces: add all interfaces and superinterfaces to queue
+ // search until it's empty
+
+ if (curClass == null) {
+ addInterfaces(intfs, startClass);
+ while (intfs.size() > 0) {
+ String intf = intfs.removeFirst();
+ curClass = finder.find(intf);
+ if (curClass == null) {
+ err("can't find interface %s", intf);
+ break;
+ }
+
+ if (isMemberPresent(curClass, findName, findDesc, resolveMethod)) {
+ break;
+ }
+
+ addInterfaces(intfs, curClass);
+ }
+ }
+
+ if (curClass == null) {
+ if (checkStartClass) {
+ err("can't resolve methodref %s %s %s",
+ startClassName, findName, findDesc);
+ return startClassName;
+ } else {
+ // TODO: refactor this
+ // checkStartClass == false means we're checking for overrides
+ // so not being able to resolve a method simply means there's
+ // no overriding, which isn't an error
+ return null;
+ }
+ } else {
+ String foundClassName = curClass.getName();
+ return foundClassName;
+ }
+ }
+
+ /**
+ * Checks the superclass of this class.
+ *
+ * @param cf the ClassFile of this class
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ void checkSuper(ClassFile cf) throws ConstantPoolException {
+ String sname = cf.getSuperclassName();
+ DeprData dd = db.getTypeDeprecated(sname);
+ if (dd != null) {
+ printType("scan.out.extends", cf, sname, dd.isForRemoval());
+ }
+ }
+
+ /**
+ * Checks the interfaces of this class.
+ *
+ * @param cf the ClassFile of this class
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ void checkInterfaces(ClassFile cf) throws ConstantPoolException {
+ int ni = cf.interfaces.length;
+ for (int i = 0; i < ni; i++) {
+ String iname = cf.getInterfaceName(i);
+ DeprData dd = db.getTypeDeprecated(iname);
+ if (dd != null) {
+ printType("scan.out.implements", cf, iname, dd.isForRemoval());
+ }
+ }
+ }
+
+ /**
+ * Checks types referred to from the constant pool.
+ *
+ * @param cf the ClassFile of this class
+ * @param entries constant pool entries collected from this class
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ void checkTypes(ClassFile cf, CPEntries entries) throws ConstantPoolException {
+ for (ConstantPool.CONSTANT_Class_info ci : entries.classes) {
+ String typeName = ci.getName();
+ DeprData dd = db.getTypeDeprecated(flatten(typeName));
+ if (dd != null) {
+ printType("scan.out.usestype", cf, typeName, dd.isForRemoval());
+ }
+ }
+ }
+
+ /**
+ * Checks methods referred to from the constant pool.
+ *
+ * @param cf the ClassFile of this class
+ * @param nti the NameAndType_info from a MethodRef or InterfaceMethodRef entry
+ * @param clname the class name
+ * @param typeKey key for the type message
+ * @param methKey key for the method message
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ void checkMethodRef(ClassFile cf,
+ CONSTANT_NameAndType_info nti,
+ String clname,
+ String typeKey,
+ String methKey) throws ConstantPoolException {
+ DeprData dd = db.getTypeDeprecated(flatten(clname));
+ if (dd != null) {
+ printType(typeKey, cf, clname, dd.isForRemoval());
+ }
+
+ String name = nti.getName();
+ String type = nti.getType();
+ clname = resolveMember(cf, flatten(clname), name, type, true, true);
+ dd = db.getMethodDeprecated(clname, name, type);
+ if (dd != null) {
+ printMethod(methKey, cf, clname, name, type, dd.isForRemoval());
+ }
+ }
+
+ /**
+ * Checks fields referred to from the constant pool.
+ *
+ * @param cf the ClassFile of this class
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ void checkFieldRef(ClassFile cf,
+ ConstantPool.CONSTANT_Fieldref_info fri) throws ConstantPoolException {
+ CONSTANT_NameAndType_info nti = fri.getNameAndTypeInfo();
+ String clname = fri.getClassName();
+ String name = nti.getName();
+ String type = nti.getType();
+ DeprData dd = db.getTypeDeprecated(clname);
+
+ if (dd != null) {
+ printType("scan.out.usesfieldintype", cf, clname, dd.isForRemoval());
+ }
+
+ clname = resolveMember(cf, flatten(clname), name, type, false, true);
+ dd = db.getFieldDeprecated(clname, name);
+ if (dd != null) {
+ printField("scan.out.usesfield", cf, clname, name, dd.isForRemoval());
+ }
+
+ dd = db.getTypeDeprecated(flatten(type));
+ if (dd != null) {
+ printFieldType("scan.out.usesfieldoftype", cf, clname, name, type, dd.isForRemoval());
+ }
+ }
+
+ /**
+ * Checks the fields declared in this class.
+ *
+ * @param cf the ClassFile of this class
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ void checkFields(ClassFile cf) throws ConstantPoolException {
+ for (Field f : cf.fields) {
+ String type = cf.constant_pool.getUTF8Value(f.descriptor.index);
+ DeprData dd = db.getTypeDeprecated(flatten(type));
+ if (dd != null) {
+ printHasField(cf, f.getName(cf.constant_pool), type, dd.isForRemoval());
+ }
+ }
+ }
+
+ /**
+ * Checks the methods declared in this class.
+ *
+ * @param cf the ClassFile object of this class
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ void checkMethods(ClassFile cf) throws ConstantPoolException {
+ for (Method m : cf.methods) {
+ String mname = m.getName(cf.constant_pool);
+ String desc = cf.constant_pool.getUTF8Value(m.descriptor.index);
+ MethodSig sig = MethodSig.fromDesc(desc);
+ DeprData dd;
+
+ for (String parm : sig.getParameters()) {
+ dd = db.getTypeDeprecated(flatten(parm));
+ if (dd != null) {
+ printHasMethodParmType(cf, mname, parm, dd.isForRemoval());
+ }
+ }
+
+ String ret = sig.getReturnType();
+ dd = db.getTypeDeprecated(flatten(ret));
+ if (dd != null) {
+ printHasMethodRetType(cf, mname, ret, dd.isForRemoval());
+ }
+
+ // check overrides
+ String overridden = resolveMember(cf, cf.getName(), mname, desc, true, false);
+ if (overridden != null) {
+ dd = db.getMethodDeprecated(overridden, mname, desc);
+ if (dd != null) {
+ printHasOverriddenMethod(cf, overridden, mname, desc, dd.isForRemoval());
+ }
+ }
+ }
+ }
+
+ /**
+ * Processes a single class file.
+ *
+ * @param cf the ClassFile of the class
+ * @throws ConstantPoolException if a constant pool entry cannot be found
+ */
+ void processClass(ClassFile cf) throws ConstantPoolException {
+ if (verbose) {
+ out.println(Messages.get("scan.process.class", cf.getName()));
+ }
+
+ CPEntries entries = CPEntries.loadFrom(cf);
+
+ checkSuper(cf);
+ checkInterfaces(cf);
+ checkTypes(cf, entries);
+
+ for (ConstantPool.CONSTANT_Methodref_info mri : entries.methodRefs) {
+ CONSTANT_NameAndType_info nti = mri.getNameAndTypeInfo();
+ String clname = mri.getClassName();
+ checkMethodRef(cf, nti, clname, "scan.out.usesmethodintype", "scan.out.usesmethod");
+ }
+
+ for (ConstantPool.CONSTANT_InterfaceMethodref_info imri : entries.intfMethodRefs) {
+ CONSTANT_NameAndType_info nti = imri.getNameAndTypeInfo();
+ String clname = imri.getClassName();
+ checkMethodRef(cf, nti, clname, "scan.out.usesintfmethodintype", "scan.out.usesintfmethod");
+ }
+
+ for (ConstantPool.CONSTANT_Fieldref_info fri : entries.fieldRefs) {
+ checkFieldRef(cf, fri);
+ }
+
+ checkFields(cf);
+ checkMethods(cf);
+ }
+
+ /**
+ * Scans a jar file for uses of deprecated APIs.
+ *
+ * @param jarname the jar file to process
+ * @return true on success, false on failure
+ */
+ public boolean scanJar(String jarname) {
+ try (JarFile jf = new JarFile(jarname)) {
+ finder.addJar(jarname);
+ Enumeration<JarEntry> entries = jf.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry entry = entries.nextElement();
+ String name = entry.getName();
+ if (name.endsWith(".class")
+ && !name.endsWith("package-info.class")
+ && !name.endsWith("module-info.class")) {
+ processClass(ClassFile.read(jf.getInputStream(entry)));
+ }
+ }
+ return true;
+ } catch (IOException | ConstantPoolException ex) {
+ printException(ex);
+ return false;
+ }
+ }
+
+ /**
+ * Scans class files in the named directory hierarchy for uses of deprecated APIs.
+ *
+ * @param dirname the directory hierarchy to process
+ * @return true on success, false on failure
+ */
+ public boolean scanDir(String dirname) {
+ Path base = Paths.get(dirname);
+ int baseCount = base.getNameCount();
+ finder.addDir(dirname);
+ try (Stream<Path> paths = Files.walk(Paths.get(dirname))) {
+ List<Path> classes =
+ paths.filter(p -> p.getNameCount() > baseCount)
+ .filter(path -> path.toString().endsWith(".class"))
+ .filter(path -> !path.toString().endsWith("package-info.class"))
+ .filter(path -> !path.toString().endsWith("module-info.class"))
+ .collect(Collectors.toList());
+ for (Path p : classes) {
+ processClass(ClassFile.read(p));
+ }
+ return true;
+ } catch (IOException | ConstantPoolException ex) {
+ printException(ex);
+ return false;
+ }
+ }
+
+ /**
+ * Scans the named class for uses of deprecated APIs.
+ *
+ * @param className the class to scan
+ * @return true on success, false on failure
+ */
+ public boolean processClassName(String className) {
+ try {
+ ClassFile cf = finder.find(className);
+ if (cf == null) {
+ err("can't find class %s", className);
+ return false;
+ } else {
+ processClass(cf);
+ return true;
+ }
+ } catch (ConstantPoolException ex) {
+ printException(ex);
+ return false;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/members/ExampleAnnotation.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.members;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+
+@Retention(value=RetentionPolicy.RUNTIME)
+@Target({TYPE, METHOD, FIELD})
+public @interface ExampleAnnotation {
+ String file();
+ @Deprecated String name() default "";
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/members/ExampleClass.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.members;
+
+public class ExampleClass {
+ public ExampleClass() { }
+
+ @Deprecated
+ public ExampleClass(boolean deprecatedConstructor) { }
+
+ @Deprecated
+ public void method1() { }
+
+ @Deprecated
+ public void method2() { }
+
+ @Deprecated
+ public int field1 = 0;
+
+ @Deprecated
+ public int field2 = 0;
+
+ @Deprecated
+ public static void staticmethod1() { }
+
+ @Deprecated
+ public static int staticfield3 = 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/members/ExampleElements.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.members;
+
+public class ExampleElements {
+ @Deprecated
+ Object emptyFalse;
+
+ @Deprecated(since="xyzzy")
+ Object sinceFalse;
+
+ @Deprecated(forRemoval=true)
+ Object emptyTrue;
+
+ @Deprecated(since="plugh", forRemoval=true)
+ Object sinceTrue;
+
+ @Deprecated(since="123,456")
+ Object sinceWithComma;
+
+ @Deprecated(since="7.9 \"pre-beta\" snapshot")
+ Object sinceWithQuote;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/members/ExampleEnum.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.members;
+
+public enum ExampleEnum {
+ ONE,
+ TWO {
+ @Override
+ public void deprMethod1() { }
+ @Override @Deprecated
+ public void deprMethod2() { }
+ },
+ @Deprecated THREE,
+ FOUR,
+ @Deprecated FIVE;
+
+ @Deprecated
+ public void deprMethod1() { }
+
+ public void deprMethod2() { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/members/ExampleInterface.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.members;
+
+public interface ExampleInterface {
+ @Deprecated
+ static final int DEP_FIELD1 = 1;
+
+ @Deprecated
+ static final int DEP_FIELD2 = 2;
+
+ @Deprecated
+ void interfaceMethod1();
+
+ @Deprecated
+ void interfaceMethod2();
+
+ @Deprecated
+ default void defaultMethod() { }
+
+ @Deprecated
+ static void staticmethod2() { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/members/ExampleSubclass.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.members;
+
+public abstract class ExampleSubclass extends ExampleClass implements ExampleInterface {
+ @Override
+ public void method1() { }
+
+ // hides ExampleClass.field1
+ public Object field1 = null;
+
+ @Override
+ public void interfaceMethod2() {
+ }
+
+ // hides ExampleInterface.DEP_FIELD1
+ public Object DEP_FIELD1 = null;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/types/DeprecatedAnnotation.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.types;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+
+@Retention(value=RetentionPolicy.RUNTIME)
+@Target({TYPE, METHOD, FIELD})
+@Deprecated
+public @interface DeprecatedAnnotation {
+ String file() default "x";
+ String value() default "y";
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/types/DeprecatedClass.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.types;
+
+@Deprecated
+public class DeprecatedClass {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/types/DeprecatedEnum.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.types;
+
+@Deprecated
+public enum DeprecatedEnum {
+ FIRST,
+ SECOND,
+ THIRD
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/types/DeprecatedException.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.types;
+
+@Deprecated
+public class DeprecatedException extends RuntimeException {
+ private static final long serialVersionUID = 0L;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/cases/jdk/deprcases/types/DeprecatedInterface.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.deprcases.types;
+
+@Deprecated
+public interface DeprecatedInterface {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/tests/jdk/jdeprscan/TestCSV.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Basic tests CSV printing and parsing
+ * @modules jdk.jdeps/com.sun.tools.jdeprscan
+ * @build TestCSV
+ * @run testng jdk.jdeprscan.TestCSV
+ */
+
+package jdk.jdeprscan;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+
+import java.util.List;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import com.sun.tools.jdeprscan.CSV;
+import com.sun.tools.jdeprscan.CSVParseException;
+
+@Test
+public class TestCSV {
+ static String NL = System.lineSeparator();
+ ByteArrayOutputStream baos;
+ PrintStream out;
+
+ @BeforeMethod
+ public void setup() throws UnsupportedEncodingException {
+ baos = new ByteArrayOutputStream();
+ out = new PrintStream(baos, true, "UTF-8");
+ }
+
+ String result() {
+ out.flush();
+ return new String(baos.toByteArray(), java.nio.charset.StandardCharsets.UTF_8);
+ }
+
+ /**
+ * Asserts string equality after checking for and removing a trailing line separator.
+ *
+ * @param expected expected result
+ */
+ void checkString(String expected) {
+ String actual = result();
+ assertTrue(actual.endsWith(NL));
+ assertEquals(actual.substring(0, actual.length() - NL.length()), expected);
+ }
+
+ @DataProvider(name = "csvdata")
+ public Object[][] getCSVData() {
+ return new Object[][] {
+ { "", List.of("") },
+ { "a", List.of("a") },
+ { "a,b", List.of("a", "b") },
+ { "a,b,c", List.of("a", "b", "c") },
+ { ",a,b", List.of("", "a", "b") },
+ { "a,b,", List.of("a", "b", "") },
+ { ",a,b,", List.of("", "a", "b", "") },
+ { ",a,,b,", List.of("", "a", "", "b", "") },
+ { ",", List.of("", "") },
+ { ",,", List.of("", "", "") },
+ { ",,,", List.of("", "", "", "") },
+ { " a , b ", List.of(" a ", " b ") },
+ { "a,\",\",b", List.of("a", ",", "b") },
+ { "a,\"b\"\"c\",d", List.of("a", "b\"c", "d") },
+ { "a,\"b,c\",d", List.of("a", "b,c", "d") },
+
+ // from https://en.wikipedia.org/wiki/Comma-separated_values
+ // slightly modified to enable round-tripping
+
+ { "Year,Make,Model,Description,Price",
+ List.of("Year", "Make", "Model", "Description", "Price") },
+ { "1997,Ford,E350,\"ac, abs, moon\",3000.00",
+ List.of("1997", "Ford", "E350", "ac, abs, moon", "3000.00") },
+ { "1999,Chevy,\"Venture \"\"Extended Edition\"\"\",,4900.00",
+ List.of("1999", "Chevy", "Venture \"Extended Edition\"", "", "4900.00") },
+ { "1999,Chevy,\"Venture \"\"Extended Edition, Very Large\"\"\",,5000.00",
+ List.of("1999", "Chevy", "Venture \"Extended Edition, Very Large\"", "", "5000.00") },
+ { "1996,Jeep,Grand Cherokee,\"MUST SELL!\nair, moon roof, loaded\",4799.00",
+ List.of("1996", "Jeep", "Grand Cherokee", "MUST SELL!\nair, moon roof, loaded", "4799.00") }
+ };
+ }
+
+ @Test(dataProvider = "csvdata")
+ public void roundTrip(String input, List<String> parsed) {
+ List<String> actual = CSV.split(input);
+ assertEquals(actual, parsed);
+ CSV.write(out, actual.toArray());
+ checkString(input);
+ }
+
+ // won't round-trip
+ public void testExtraQuote() {
+ assertEquals(CSV.split("a,\"b\",c"), List.of("a", "b", "c"));
+ }
+
+ // won't round-trip
+ public void testEmptyQuote() {
+ assertEquals(CSV.split("a,\"\",b"), List.of("a", "", "b"));
+ }
+
+ @Test(expectedExceptions=CSVParseException.class)
+ public void errorUnexpectedQuote() {
+ CSV.split("ab\"cd");
+ }
+
+ @Test(expectedExceptions=CSVParseException.class)
+ public void errorCharacterAfterQuote() {
+ CSV.split("a,\"b\"c,d");
+ }
+
+ @Test(expectedExceptions=CSVParseException.class)
+ public void errorUnclosedQuote() {
+ CSV.split("a,\"b");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/tests/jdk/jdeprscan/TestLoad.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test of jdeprscan tool loading and printing to aCSV file.
+ * @modules jdk.jdeps/com.sun.tools.jdeprscan
+ * @library ../../../cases
+ * @build jdk.deprcases.members.* jdk.deprcases.types.*
+ * @build jdk.jdeprscan.TestLoad
+ * @run testng jdk.jdeprscan.TestLoad
+ */
+
+package jdk.jdeprscan;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.sun.tools.jdeprscan.Main;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertEquals;
+
+
+public class TestLoad {
+ static final String UTF8 = "UTF-8";
+ static final String EXPECTED = "TestLoadExpected.csv";
+
+ @Test
+ public void test1() throws IOException, UnsupportedEncodingException {
+ String testclasses = System.getProperty("test.classes");
+ String deprcases = testclasses + "/../../../cases";
+ boolean rval;
+
+ System.out.println("test.src = " + System.getProperty("test.src"));
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ByteArrayOutputStream berr = new ByteArrayOutputStream();
+
+ try (PrintStream prout = new PrintStream(bout, true, UTF8);
+ PrintStream prerr = new PrintStream(berr, true, UTF8)) {
+ System.out.println("Calling JDeprScan --Xprint-csv --Xload-dir " + deprcases);
+ rval = Main.call(prout, prerr, "--Xprint-csv", "--Xload-dir", deprcases);
+ System.out.println("JDeprScan returns " + rval);
+ }
+
+ System.out.println("----- stdout");
+ new ByteArrayInputStream(bout.toByteArray()).transferTo(System.out);
+ System.out.println("----- end stdout");
+ System.out.println("----- stderr");
+ new ByteArrayInputStream(berr.toByteArray()).transferTo(System.out);
+ System.out.println("----- end stderr");
+
+ List<String> actualList;
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bout.toByteArray());
+ InputStreamReader isr = new InputStreamReader(bais);
+ BufferedReader br = new BufferedReader(isr)) {
+ actualList = br.lines().collect(Collectors.toList());
+ }
+
+ Path expfile = Paths.get(System.getProperty("test.src"), EXPECTED);
+ List<String> expectedList = Files.readAllLines(expfile);
+
+ Set<String> actual = new HashSet<>(actualList.subList(1, actualList.size()));
+ Set<String> expected = new HashSet<>(expectedList.subList(1, expectedList.size()));
+
+ Set<String> diff1 = new HashSet<>(actual);
+ diff1.removeAll(expected);
+ Set<String> diff2 = new HashSet<>(expected);
+ diff2.removeAll(actual);
+ if (diff1.size() > 0) {
+ System.out.println("Extra lines in output:");
+ diff1.forEach(System.out::println);
+ }
+
+ if (diff2.size() > 0) {
+ System.out.println("Lines missing from output:");
+ diff2.forEach(System.out::println);
+ }
+
+ assertTrue(rval);
+ assertEquals(berr.toByteArray().length, 0);
+ assertEquals(actual.size(), actualList.size() - 1);
+ assertEquals(diff1.size(), 0);
+ assertEquals(diff2.size(), 0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/tests/jdk/jdeprscan/TestLoadExpected.csv Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,30 @@
+#jdepr 1
+METHOD,jdk/deprcases/members/ExampleAnnotation,name()Ljava/lang/String;,,false
+FIELD,jdk/deprcases/members/ExampleClass,field1,,false
+FIELD,jdk/deprcases/members/ExampleClass,field2,,false
+FIELD,jdk/deprcases/members/ExampleClass,staticfield3,,false
+CONSTRUCTOR,jdk/deprcases/members/ExampleClass,<init>(Z)V,,false
+METHOD,jdk/deprcases/members/ExampleClass,method1()V,,false
+METHOD,jdk/deprcases/members/ExampleClass,method2()V,,false
+METHOD,jdk/deprcases/members/ExampleClass,staticmethod1()V,,false
+METHOD,jdk/deprcases/members/ExampleEnum$1,deprMethod2()V,,false
+ENUM_CONSTANT,jdk/deprcases/members/ExampleEnum,THREE,,false
+ENUM_CONSTANT,jdk/deprcases/members/ExampleEnum,FIVE,,false
+METHOD,jdk/deprcases/members/ExampleEnum,deprMethod1()V,,false
+FIELD,jdk/deprcases/members/ExampleInterface,DEP_FIELD1,,false
+FIELD,jdk/deprcases/members/ExampleInterface,DEP_FIELD2,,false
+METHOD,jdk/deprcases/members/ExampleInterface,interfaceMethod1()V,,false
+METHOD,jdk/deprcases/members/ExampleInterface,interfaceMethod2()V,,false
+METHOD,jdk/deprcases/members/ExampleInterface,defaultMethod()V,,false
+METHOD,jdk/deprcases/members/ExampleInterface,staticmethod2()V,,false
+ANNOTATION_TYPE,jdk/deprcases/types/DeprecatedAnnotation,,,false
+CLASS,jdk/deprcases/types/DeprecatedClass,,,false
+ENUM,jdk/deprcases/types/DeprecatedEnum,,,false
+CLASS,jdk/deprcases/types/DeprecatedException,,,false
+INTERFACE,jdk/deprcases/types/DeprecatedInterface,,,false
+FIELD,jdk/deprcases/members/ExampleElements,emptyFalse,,false
+FIELD,jdk/deprcases/members/ExampleElements,sinceFalse,xyzzy,false
+FIELD,jdk/deprcases/members/ExampleElements,emptyTrue,,true
+FIELD,jdk/deprcases/members/ExampleElements,sinceTrue,plugh,true
+FIELD,jdk/deprcases/members/ExampleElements,sinceWithComma,"123,456",false
+FIELD,jdk/deprcases/members/ExampleElements,sinceWithQuote,"7.9 ""pre-beta"" snapshot",false
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/tests/jdk/jdeprscan/TestMethodSig.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Simple tests for method signature parsing
+ * @modules jdk.jdeps/com.sun.tools.jdeprscan.scan
+ * @build TestMethodSig
+ * @run testng jdk.jdeprscan.TestMethodSig
+ */
+
+package jdk.jdeprscan;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static com.sun.tools.jdeprscan.scan.MethodSig.fromDesc;
+
+public class TestMethodSig {
+ @Test
+ public void testSimple() {
+ assertEquals(fromDesc("(Ljava/rmi/RMISecurityManager;)Ljava/lang/Object;").toString(),
+ "parameters 0=Ljava/rmi/RMISecurityManager; return Ljava/lang/Object;");
+ }
+
+ @Test
+ public void testMultParamVoidReturn() {
+ assertEquals(fromDesc("([[IZLjava/lang/String;B[J)V").toString(),
+ "parameters 0=[[I 1=Z 2=Ljava/lang/String; 3=B 4=[J return V");
+ }
+
+ @Test
+ public void testNoParams() {
+ assertEquals(fromDesc("()J").toString(),
+ "parameters none return J");
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testMissingReturnType() {
+ fromDesc("(ISJZ)");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/tests/jdk/jdeprscan/TestScan.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Basic test of jdeprscan's scanning phase.
+ * @modules jdk.jdeps/com.sun.tools.jdeprscan
+ * @library ../../../cases
+ * @library ../../../usage
+ * @build jdk.deprcases.members.* jdk.deprcases.types.*
+ * @build jdk.deprusage.*
+ * @build jdk.jdeprscan.TestScan
+ * @run testng jdk.jdeprscan.TestScan
+ */
+
+package jdk.jdeprscan;
+
+import com.sun.tools.jdeprscan.Main;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.testng.Assert;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+
+public class TestScan {
+ Set<String> loadExpected() throws IOException {
+ Path expFile = Paths.get(System.getProperty("test.src"), "TestScanExpected.txt");
+ return new HashSet<>(Files.readAllLines(expFile, StandardCharsets.UTF_8));
+ }
+
+ @Test
+ public void testScanAgainstReferenceFile() throws IOException {
+ String testclasses = System.getProperty("test.classes");
+ String deprcases = testclasses + "/../../../cases";
+ String deprusage = testclasses + "/../../../usage";
+
+ Set<String> expected = loadExpected();
+ System.out.println("expected = " + expected);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (PrintStream out = new PrintStream(baos, false, "UTF-8")) {
+ boolean r = Main.call(out, System.err,
+ "-cp", deprcases, "--Xload-dir", deprcases, deprusage);
+ assertTrue(r);
+ }
+ byte[] bytes = baos.toByteArray();
+
+ System.out.println("--- output ---");
+ ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ bais.transferTo(System.out);
+ System.out.println("--- end output ---");
+
+ Set<String> actual =
+ new BufferedReader(
+ new InputStreamReader(
+ new ByteArrayInputStream(bytes), StandardCharsets.UTF_8))
+ .lines()
+ .map(line -> line.split(" +"))
+ .map(array -> array[1])
+ .collect(Collectors.toSet());
+ System.out.println("actual = " + actual);
+
+ Set<String> diff1 = new HashSet<>(expected);
+ diff1.removeAll(actual);
+ Set<String> diff2 = new HashSet<>(actual);
+ diff2.removeAll(expected);
+
+ if (diff1.size() > 0 || diff2.size() > 0) {
+ System.out.println("missing items: " + diff1);
+ System.out.println("extra items: " + diff2);
+ }
+
+ Assert.assertEquals(diff1.size(), 0);
+ Assert.assertEquals(diff2.size(), 0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/tests/jdk/jdeprscan/TestScanExpected.txt Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,47 @@
+jdk/jdeprusage/UseClass$ArrayCreation
+jdk/jdeprusage/UseClass$ArrayFieldUsage
+jdk/jdeprusage/UseClass$ArrayMethodCall
+jdk/jdeprusage/UseClass$Cast
+jdk/jdeprusage/UseClass$ClassLiteral
+jdk/jdeprusage/UseClass$Construct
+jdk/jdeprusage/UseClass$Extends
+jdk/jdeprusage/UseClass$FieldType
+jdk/jdeprusage/UseClass$InstanceOf
+jdk/jdeprusage/UseClass$MethodParameter
+jdk/jdeprusage/UseClass$MethodReturn
+jdk/jdeprusage/UseEnum$ClassObject
+jdk/jdeprusage/UseEnum$EnumConstant
+jdk/jdeprusage/UseEnum$FieldType
+jdk/jdeprusage/UseEnum$MethodParameter
+jdk/jdeprusage/UseEnum$ReturnValue
+jdk/jdeprusage/UseEnum$ValueOfMethod
+jdk/jdeprusage/UseEnum$ValuesMethod
+jdk/jdeprusage/UseEnumMembers$1
+jdk/jdeprusage/UseEnumMembers$MethodInEnum1
+jdk/jdeprusage/UseEnumMembers$MethodOnConstant1
+jdk/jdeprusage/UseEnumMembers$ReturnValue
+jdk/jdeprusage/UseException$Catch
+jdk/jdeprusage/UseException$Throws
+jdk/jdeprusage/UseField$Direct
+jdk/jdeprusage/UseField$FromSubclass
+jdk/jdeprusage/UseField$Inherited
+jdk/jdeprusage/UseField$StaticField
+jdk/jdeprusage/UseField$SuperFromSubclass
+jdk/jdeprusage/UseInterface$ClassImplements
+jdk/jdeprusage/UseInterface$InterfaceExtends
+jdk/jdeprusage/UseMethod$ClassStatic
+jdk/jdeprusage/UseMethod$Constructor
+jdk/jdeprusage/UseMethod$ConstructorFromSubclass
+jdk/jdeprusage/UseMethod$Direct
+jdk/jdeprusage/UseMethod$Inherited
+jdk/jdeprusage/UseMethod$InheritedDefault
+jdk/jdeprusage/UseMethod$InheritedFromSubclass
+jdk/jdeprusage/UseMethod$InheritedInterface
+jdk/jdeprusage/UseMethod$InheritedInterfaceDefault
+jdk/jdeprusage/UseMethod$InterfaceDefault
+jdk/jdeprusage/UseMethod$InterfaceDirect
+jdk/jdeprusage/UseMethod$InterfaceStatic
+jdk/jdeprusage/UseMethod$OverrideClassMethod
+jdk/jdeprusage/UseMethod$OverrideDefaultMethod
+jdk/jdeprusage/UseMethod$OverrideInterfaceMethod
+jdk/jdeprusage/UseMethod$SuperFromSubclass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/usage/jdk/deprusage/UseAnnotation.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jdeprusage;
+
+import jdk.deprcases.types.DeprecatedAnnotation;
+
+public class UseAnnotation {
+ @DeprecatedAnnotation
+ static class AnnotatedClass { }
+
+ static class AnnotatedMethod {
+ @DeprecatedAnnotation
+ void foo() { }
+ }
+
+ static class AnnotatedField {
+ @DeprecatedAnnotation
+ int foo = 1;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/usage/jdk/deprusage/UseClass.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jdeprusage;
+
+import jdk.deprcases.types.DeprecatedClass;
+
+public class UseClass {
+ static class Extends extends DeprecatedClass {
+ }
+
+ static class ClassLiteral {
+ Class<?> clazz = DeprecatedClass.class;
+ }
+
+ static class FieldType {
+ DeprecatedClass obj = null;
+ }
+
+ static class MethodParameter {
+ void foo(DeprecatedClass x) { }
+ }
+
+ static class MethodReturn {
+ DeprecatedClass foo() { return null; }
+ }
+
+ static class ArrayCreation {
+ Object foo() {
+ return new DeprecatedClass[1];
+ }
+ }
+
+ static class ArrayFieldUsage {
+ int foo(Object o) {
+ return ((DeprecatedClass[])o).length;
+ }
+ }
+
+ static class ArrayMethodCall {
+ Object foo(Object o) {
+ return ((DeprecatedClass[])o).clone();
+ }
+ }
+
+ static class InstanceOf {
+ boolean foo(Object o) {
+ return o instanceof DeprecatedClass;
+ }
+ }
+
+ static class Cast {
+ Object foo(Object o) {
+ return (DeprecatedClass)o;
+ }
+ }
+
+ static class Generic<T> {
+ static <U> void g() { }
+ }
+
+ static class ClassTypeArg extends Generic<DeprecatedClass> { }
+
+ static class MethodTypeArg {
+ void foo() {
+ Generic.<DeprecatedClass>g();
+ }
+ }
+
+ static class ConstructorTypeArg {
+ Object foo() {
+ return new Generic<DeprecatedClass>();
+ }
+ }
+
+ static class Construct {
+ Object foo() {
+ return new DeprecatedClass();
+ }
+ }
+
+ static class Local {
+ void foo() {
+ DeprecatedClass obj = null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/usage/jdk/deprusage/UseEnum.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jdeprusage;
+
+import jdk.deprcases.types.DeprecatedEnum;
+
+public class UseEnum {
+ static class ReturnValue {
+ static DeprecatedEnum returnValue() { return null; }
+ }
+
+ static class MethodParameter {
+ static void methodParameterType(DeprecatedEnum e) { }
+ }
+
+ static class FieldType {
+ static DeprecatedEnum field;
+ }
+
+ static class EnumConstant {
+ static Object field2 = DeprecatedEnum.FIRST;
+ }
+
+ static class ValuesMethod {
+ static Object[] valuesMethod() {
+ return DeprecatedEnum.values();
+ }
+ }
+
+ static class ValueOfMethod {
+ static Object valueOfMethod(String s) {
+ return DeprecatedEnum.valueOf(s);
+ }
+ }
+
+ static class ClassObject {
+ static Object classObject() {
+ return DeprecatedEnum.class;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/usage/jdk/deprusage/UseEnumMembers.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jdeprusage;
+
+import jdk.deprcases.members.ExampleEnum;
+
+public class UseEnumMembers {
+ static class ReturnValue {
+ static ExampleEnum returnValue() {
+ return ExampleEnum.FIVE;
+ }
+ }
+
+ static class UseInSwitch {
+ // enum switch generates inner class UseEnumMembers$UseInSwitch$1
+ static void useInSwitch(ExampleEnum e) {
+ switch (e) {
+ case ONE:
+ case TWO:
+ case FOUR:
+ // no deprecation
+ break;
+ case THREE:
+ // deprecated
+ break;
+ }
+ }
+ }
+
+ static class MethodInEnum1 {
+ static void methodInEnum1(ExampleEnum e) {
+ e.deprMethod1();
+ }
+ }
+
+ static class MethodOnConstant1 {
+ static void methodOnConstant1() {
+ // surprising that there is a warning here;
+ // the method deprMethod1 is overridden in TWO
+ ExampleEnum.TWO.deprMethod1();
+ }
+ }
+
+ static void methodInEnum2(ExampleEnum e) {
+ e.deprMethod2();
+ }
+
+ static void methodOnConstant2() {
+ // surprising there is no warning here;
+ // the method is deprecated in TWO
+ ExampleEnum.TWO.deprMethod2();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/usage/jdk/deprusage/UseException.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jdeprusage;
+
+import jdk.deprcases.types.DeprecatedException;
+
+public class UseException {
+ static class Throws {
+ static void foo() throws DeprecatedException { }
+ }
+
+ static class Catch {
+ void foo() {
+ try {
+ Throws.foo();
+ } catch (DeprecatedException de) { }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/usage/jdk/deprusage/UseField.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jdeprusage;
+
+import jdk.deprcases.members.ExampleClass;
+import jdk.deprcases.members.ExampleInterface;
+import jdk.deprcases.members.ExampleSubclass;
+
+public class UseField {
+ static class Direct {
+ int f(ExampleClass ec) {
+ return ec.field1;
+ }
+ }
+
+ static class Inherited {
+ int f(ExampleSubclass esc) {
+ return esc.field2;
+ }
+ }
+
+ static class InterfaceInherited {
+ int f(ExampleSubclass esc) {
+ return esc.DEP_FIELD2;
+ }
+ }
+
+ static class InterfaceDirect {
+ int f(ExampleInterface ei) {
+ return ei.DEP_FIELD1;
+ }
+ }
+
+ static class FromSubclass extends ExampleClass {
+ int f() {
+ return field1;
+ }
+ }
+
+ static class SuperFromSubclass extends ExampleClass {
+ int f() {
+ return super.field1;
+ }
+ }
+
+ static class StaticField {
+ int f() {
+ return ExampleClass.staticfield3;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/usage/jdk/deprusage/UseInterface.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jdeprusage;
+
+import jdk.deprcases.types.DeprecatedInterface;
+
+public class UseInterface {
+ static class ClassImplements implements DeprecatedInterface {
+
+ }
+
+ interface InterfaceExtends extends DeprecatedInterface {
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeprscan/usage/jdk/deprusage/UseMethod.java Thu Aug 25 17:58:39 2016 -0700
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jdeprusage;
+
+import jdk.deprcases.members.ExampleClass;
+import jdk.deprcases.members.ExampleInterface;
+import jdk.deprcases.members.ExampleSubclass;
+
+public class UseMethod {
+ static class Direct {
+ void m(ExampleClass ec) {
+ ec.method1();
+ }
+ }
+
+ static class Inherited {
+ void m(ExampleSubclass esc) {
+ esc.method2();
+ }
+ }
+
+ static class InheritedDefault {
+ void m(ExampleSubclass esc) {
+ esc.defaultMethod();
+ }
+ }
+
+ static class InterfaceDirect {
+ void m(ExampleInterface ei) {
+ ei.interfaceMethod1();
+ }
+ }
+
+ static class InterfaceDefault {
+ void m(ExampleInterface ei) {
+ ei.defaultMethod();
+ }
+ }
+
+ static class ClassStatic {
+ void m() {
+ ExampleClass.staticmethod1();
+ }
+ }
+
+ static class InterfaceStatic {
+ void m() {
+ ExampleInterface.staticmethod2();
+ }
+ }
+
+ static class SuperFromSubclass extends ExampleClass {
+ void m() {
+ super.method1();
+ }
+ }
+
+ static class InheritedFromSubclass extends ExampleClass {
+ void m() {
+ method1();
+ }
+ }
+
+ static class Constructor {
+ Object m() {
+ return new ExampleClass(true);
+ }
+ }
+
+ static class ConstructorFromSubclass extends ExampleClass {
+ public ConstructorFromSubclass() {
+ super(true);
+ }
+ }
+
+ abstract static class InheritedInterfaceDefault extends ExampleSubclass {
+ void m() {
+ defaultMethod();
+ }
+ }
+
+ abstract static class InheritedInterface extends ExampleSubclass {
+ void m() {
+ interfaceMethod1();
+ }
+ }
+
+ static class OverrideClassMethod extends ExampleClass {
+ @Override
+ public void method1() { }
+ }
+
+ abstract static class OverrideInterfaceMethod implements ExampleInterface {
+ @Override
+ public void interfaceMethod1() { }
+ }
+
+ abstract static class OverrideDefaultMethod implements ExampleInterface {
+ @Override
+ public void defaultMethod() { }
+ }
+}