Skip to content

Commit

Permalink
Add DEBUG level logging and report classpath and JDK type to allow de…
Browse files Browse the repository at this point in the history
…bugging od classpath/JDK related problems. This closes #202
  • Loading branch information
uschindler committed Sep 24, 2022
1 parent 500e8cc commit c39f06a
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 10 deletions.
19 changes: 15 additions & 4 deletions src/main/java/de/thetaphi/forbiddenapis/Checker.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public static enum Option {
final Logger logger;

final ClassLoader loader;
final String humanClasspath;
final java.lang.reflect.Method method_Class_getModule, method_Module_getName;
final EnumSet<Option> options;

Expand All @@ -79,13 +80,14 @@ public static enum Option {
/** descriptors (not internal names) of all annotations that suppress */
final Set<String> suppressAnnotations = new LinkedHashSet<>();

public Checker(Logger logger, ClassLoader loader, Option... options) {
this(logger, loader, (options.length == 0) ? EnumSet.noneOf(Option.class) : EnumSet.copyOf(Arrays.asList(options)));
public Checker(Logger logger, ClassLoader loader, String humanClasspath, Option... options) {
this(logger, loader, humanClasspath, (options.length == 0) ? EnumSet.noneOf(Option.class) : EnumSet.copyOf(Arrays.asList(options)));
}

public Checker(Logger logger, ClassLoader loader, EnumSet<Option> options) {
public Checker(Logger logger, ClassLoader loader, String humanClasspath, EnumSet<Option> options) {
this.logger = logger;
this.loader = loader;
this.humanClasspath = (humanClasspath == null || humanClasspath.isEmpty()) ? null : humanClasspath;
this.options = options;
this.start = System.currentTimeMillis();

Expand All @@ -101,6 +103,7 @@ public Checker(Logger logger, ClassLoader loader, EnumSet<Option> options) {
method_Module_getName = method_Class_getModule
.getReturnType().getMethod("getName");
isSupportedJDK = true;
logger.debug("Detected Java 9 or later with module system.");
} catch (NoSuchMethodException e) {
method_Class_getModule = method_Module_getName = null;
}
Expand All @@ -116,6 +119,7 @@ public Checker(Logger logger, ClassLoader loader, EnumSet<Option> options) {
if (objectClassURL != null && "jrt".equalsIgnoreCase(objectClassURL.getProtocol())) {
// this is Java 9+ allowing direct access to .class file resources - we do not need to deal with modules!
isSupportedJDK = true;
logger.debug("Detected Java 9 or later with JRT file system.");
} else {
String javaHome = System.getProperty("java.home");
if (javaHome != null) {
Expand Down Expand Up @@ -146,7 +150,9 @@ public Checker(Logger logger, ClassLoader loader, EnumSet<Option> options) {
}
}
isSupportedJDK = !runtimePaths.isEmpty();
if (!isSupportedJDK) {
if (isSupportedJDK) {
logger.debug("Detected classical classpath-based JDK @ " + runtimePaths);
} else {
logger.warn("Boot classpath appears to be empty or ${java.home} not defined; marking runtime as not suppported.");
}
}
Expand Down Expand Up @@ -317,6 +323,11 @@ public ClassMetadata lookupRelatedClass(String internalName, String internalName
}
}

@Override
public String getHumanClasspath() {
return humanClasspath;
}

/** Reads a list of bundled API signatures from classpath. */
public void addBundledSignatures(String name, String jdkTargetVersion) throws IOException,ParseException {
forbiddenSignatures.addBundledSignatures(name, jdkTargetVersion);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/de/thetaphi/forbiddenapis/Logger.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ public interface Logger {
void error(String msg);
void warn(String msg);
void info(String msg);
void debug(String msg);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@
public interface RelatedClassLookup {
ClassMetadata lookupRelatedClass(String internalName, String internalNameOrig);
ClassMetadata getClassFromClassLoader(String clazz) throws ClassNotFoundException,IOException;
String getHumanClasspath();
}
6 changes: 6 additions & 0 deletions src/main/java/de/thetaphi/forbiddenapis/Signatures.java
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ private void addSignature(final String line, final String defaultMessage, final
return;
}
if (report.reportClassNotFound) {
if (report != UnresolvableReporting.SILENT && lookup.getHumanClasspath() != null) {
logger.debug("Classpath: " + lookup.getHumanClasspath());
}
report.parseFailed(logger, String.format(Locale.ENGLISH, "Class '%s' not found on classpath", cnfe.getMessage()), signature);
} else {
missingClasses.add(clazz);
Expand Down Expand Up @@ -231,6 +234,9 @@ private void reportMissingSignatureClasses(Set<String> missingClasses) {
if (missingClasses.isEmpty()) {
return;
}
if (lookup.getHumanClasspath() != null) {
logger.debug("Classpath: " + lookup.getHumanClasspath());
}
logger.warn("Some signatures were ignored because the following classes were not found on classpath:");
final StringBuilder sb = new StringBuilder();
int count = 0;
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/de/thetaphi/forbiddenapis/StdIoLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,9 @@ public void info(String msg) {
System.out.println(msg);
}

@Override
public void debug(String msg) {
// no reporting of debug messages
}

}
7 changes: 6 additions & 1 deletion src/main/java/de/thetaphi/forbiddenapis/ant/AntTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ public void warn(String msg) {
public void info(String msg) {
log(msg, Project.MSG_INFO);
}

@Override
public void debug(String msg) {
log(msg, Project.MSG_DEBUG);
}
};

AntClassLoader antLoader = null;
Expand All @@ -116,7 +121,7 @@ public void info(String msg) {
}
if (ignoreSignaturesOfMissingClasses) options.add(IGNORE_SIGNATURES_OF_MISSING_CLASSES);
if (disableClassloadingCache) options.add(DISABLE_CLASSLOADING_CACHE);
final Checker checker = new Checker(log, loader, options);
final Checker checker = new Checker(log, loader, (classpath == null) ? null : classpath.toString(), options);

if (!checker.isSupportedJDK) {
final String msg = String.format(Locale.ENGLISH,
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/de/thetaphi/forbiddenapis/cli/CliMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -196,16 +196,22 @@ public void run() throws ExitException {
// parse classpath given as argument; add -d to classpath, too
final String[] classpath = cmd.getOptionValues(classpathOpt.getLongOpt());
final URL[] urls;
final CharSequence humanClasspath;
try {
if (classpath == null) {
urls = new URL[] { classesDirectory.toURI().toURL() };
humanClasspath = classesDirectory.toString();
} else {
urls = new URL[classpath.length + 1];
int i = 0;
final StringBuilder sb = new StringBuilder();
for (final String cpElement : classpath) {
urls[i++] = new File(cpElement).toURI().toURL();
sb.append(cpElement).append(File.pathSeparatorChar);
}
urls[i++] = classesDirectory.toURI().toURL();
sb.append(classesDirectory.toString());
humanClasspath = sb;
assert i == urls.length;
}
} catch (MalformedURLException mfue) {
Expand All @@ -222,7 +228,7 @@ public void run() throws ExitException {
options.add(FAIL_ON_UNRESOLVABLE_SIGNATURES);
}
if (cmd.hasOption(ignoresignaturesofmissingclassesOpt.getLongOpt())) options.add(IGNORE_SIGNATURES_OF_MISSING_CLASSES);
final Checker checker = new Checker(LOG, loader, options);
final Checker checker = new Checker(LOG, loader, humanClasspath.toString(), options);

if (!checker.isSupportedJDK) {
throw new ExitException(EXIT_UNSUPPORTED_JDK, String.format(Locale.ENGLISH,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,16 +498,26 @@ public void warn(String msg) {
public void info(String msg) {
getLogger().info(msg);
}

@Override
public void debug(String msg) {
getLogger().debug(msg);
}
};

final Set<File> cpElements = new LinkedHashSet<>();
cpElements.addAll(classpath.getFiles());
cpElements.addAll(classesDirs.getFiles());
final URL[] urls = new URL[cpElements.size()];
final StringBuilder humanClasspath = new StringBuilder();
try {
int i = 0;
for (final File cpElement : cpElements) {
urls[i++] = cpElement.toURI().toURL();
if (humanClasspath.length() > 0) {
humanClasspath.append(File.pathSeparatorChar);
}
humanClasspath.append(cpElement);
}
assert i == urls.length;
} catch (MalformedURLException mfue) {
Expand All @@ -530,7 +540,7 @@ public void info(String msg) {
}
if (getIgnoreSignaturesOfMissingClasses()) options.add(IGNORE_SIGNATURES_OF_MISSING_CLASSES);
if (getDisableClassloadingCache()) options.add(DISABLE_CLASSLOADING_CACHE);
final Checker checker = new Checker(log, loader, options);
final Checker checker = new Checker(log, loader, humanClasspath.toString(), options);

if (!checker.isSupportedJDK) {
final String msg = String.format(Locale.ENGLISH,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ public void warn(String msg) {
public void info(String msg) {
getLog().info(msg);
}

@Override
public void debug(String msg) {
getLog().debug(msg);
}
};

if (skip) {
Expand All @@ -323,10 +328,15 @@ public void info(String msg) {

final List<String> cp = getClassPathElements();
final URL[] urls = new URL[cp.size()];
final StringBuilder humanClasspath = new StringBuilder();
try {
int i = 0;
for (final String cpElement : cp) {
urls[i++] = new File(cpElement).toURI().toURL();
if (humanClasspath.length() > 0) {
humanClasspath.append(File.pathSeparatorChar);
}
humanClasspath.append(cpElement);
}
assert i == urls.length;
} catch (MalformedURLException e) {
Expand All @@ -349,7 +359,7 @@ public void info(String msg) {
}
if (ignoreSignaturesOfMissingClasses) options.add(IGNORE_SIGNATURES_OF_MISSING_CLASSES);
if (disableClassloadingCache) options.add(DISABLE_CLASSLOADING_CACHE);
final Checker checker = new Checker(log, loader, options);
final Checker checker = new Checker(log, loader, humanClasspath.toString(), options);

if (!checker.isSupportedJDK) {
final String msg = String.format(Locale.ENGLISH,
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/de/thetaphi/forbiddenapis/CheckerSetupTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public final class CheckerSetupTest {

@Before
public void setUp() {
checker = new Checker(StdIoLogger.INSTANCE, ClassLoader.getSystemClassLoader(), FAIL_ON_MISSING_CLASSES, FAIL_ON_VIOLATION, FAIL_ON_UNRESOLVABLE_SIGNATURES);
checker = new Checker(StdIoLogger.INSTANCE, ClassLoader.getSystemClassLoader(), null, FAIL_ON_MISSING_CLASSES, FAIL_ON_VIOLATION, FAIL_ON_UNRESOLVABLE_SIGNATURES);
assumeTrue("This test only works with a supported JDK (see docs)", checker.isSupportedJDK);
assertEquals(EnumSet.of(FAIL_ON_MISSING_CLASSES, FAIL_ON_VIOLATION, FAIL_ON_UNRESOLVABLE_SIGNATURES), checker.options);
forbiddenSignatures = checker.forbiddenSignatures;
Expand Down Expand Up @@ -146,7 +146,7 @@ public void testWildcardMethodSignatureNotExist() throws Exception {

@Test
public void testEmptyCtor() throws Exception {
Checker chk = new Checker(StdIoLogger.INSTANCE, ClassLoader.getSystemClassLoader());
Checker chk = new Checker(StdIoLogger.INSTANCE, ClassLoader.getSystemClassLoader(), null);
assertEquals(EnumSet.noneOf(Checker.Option.class), chk.options);
}

Expand Down

0 comments on commit c39f06a

Please sign in to comment.