Skip to content

Commit 3a19ec9

Browse files
committed
When signatures are using classes that are not found on classpath, the option to ignore those warnings is no longer so noisy: It only lists all failed signatures separately where methods/fields do not exit, but the missing classes are reported only with a single line.
1 parent fbe7a3e commit 3a19ec9

File tree

3 files changed

+49
-18
lines changed

3 files changed

+49
-18
lines changed

src/main/java/de/thetaphi/forbiddenapis/Checker.java

+46-15
Original file line numberDiff line numberDiff line change
@@ -94,25 +94,30 @@ public static enum Option {
9494
final Set<String> suppressAnnotations = new LinkedHashSet<String>();
9595

9696
private static enum UnresolvableReporting {
97-
FAIL() {
97+
FAIL(true) {
9898
@Override
9999
public void parseFailed(Logger logger, String message, String signature) throws ParseException {
100100
throw new ParseException(String.format(Locale.ENGLISH, "%s while parsing signature: %s", message, signature));
101101
}
102102
},
103-
WARNING() {
103+
WARNING(false) {
104104
@Override
105105
public void parseFailed(Logger logger, String message, String signature) throws ParseException {
106106
logger.warn(String.format(Locale.ENGLISH, "%s while parsing signature: %s [signature ignored]", message, signature));
107107
}
108108
},
109-
SILENT() {
109+
SILENT(true) {
110110
@Override
111111
public void parseFailed(Logger logger, String message, String signature) throws ParseException {
112112
// keep silent
113113
}
114114
};
115115

116+
private UnresolvableReporting(boolean reportClassNotFound) {
117+
this.reportClassNotFound = reportClassNotFound;
118+
}
119+
120+
public final boolean reportClassNotFound;
116121
public abstract void parseFailed(Logger logger, String message, String signature) throws ParseException;
117122
}
118123

@@ -348,7 +353,7 @@ public ClassSignature lookupRelatedClass(String internalName) {
348353
}
349354

350355
/** Adds the method signature to the list of disallowed methods. The Signature is checked against the given ClassLoader. */
351-
private void addSignature(final String line, final String defaultMessage, final UnresolvableReporting report) throws ParseException,IOException {
356+
private void addSignature(final String line, final String defaultMessage, final UnresolvableReporting report, final Set<String> missingClasses) throws ParseException,IOException {
352357
final String clazz, field, signature;
353358
String message = null;
354359
final Method method;
@@ -360,6 +365,9 @@ private void addSignature(final String line, final String defaultMessage, final
360365
signature = line;
361366
message = defaultMessage;
362367
}
368+
if (line.isEmpty()) {
369+
throw new ParseException("Empty signature");
370+
}
363371
p = signature.indexOf('#');
364372
if (p >= 0) {
365373
clazz = signature.substring(0, p);
@@ -401,7 +409,11 @@ private void addSignature(final String line, final String defaultMessage, final
401409
try {
402410
c = getClassFromClassLoader(clazz);
403411
} catch (ClassNotFoundException cnfe) {
404-
report.parseFailed(logger, String.format(Locale.ENGLISH, "Class '%s' not found on classpath", cnfe.getMessage()), signature);
412+
if (report.reportClassNotFound) {
413+
report.parseFailed(logger, String.format(Locale.ENGLISH, "Class '%s' not found on classpath", cnfe.getMessage()), signature);
414+
} else {
415+
missingClasses.add(clazz);
416+
}
405417
return;
406418
}
407419
if (method != null) {
@@ -433,10 +445,25 @@ private void addSignature(final String line, final String defaultMessage, final
433445
}
434446
}
435447
}
448+
449+
private void reportMissingSignatureClasses(Set<String> missingClasses) {
450+
if (!missingClasses.isEmpty()) {
451+
final StringBuilder sb = new StringBuilder("Some signatures were ignored because the following classes were not found on classpath: ");
452+
boolean comma = false;
453+
for (String s : missingClasses) {
454+
if (comma) sb.append(", ");
455+
comma = true;
456+
sb.append(s);
457+
}
458+
logger.warn(sb.toString());
459+
}
460+
}
436461

437462
/** Reads a list of bundled API signatures from classpath. */
438463
public void addBundledSignatures(String name, String jdkTargetVersion) throws IOException,ParseException {
439-
addBundledSignatures(name, jdkTargetVersion, true);
464+
final Set<String> missingClasses = new TreeSet<String>();
465+
addBundledSignatures(name, jdkTargetVersion, true, missingClasses);
466+
reportMissingSignatureClasses(missingClasses);
440467
}
441468

442469
public static String fixTargetVersion(String name) throws ParseException {
@@ -465,7 +492,7 @@ public static String fixTargetVersion(String name) throws ParseException {
465492
return name;
466493
}
467494

468-
private void addBundledSignatures(String name, String jdkTargetVersion, boolean logging) throws IOException,ParseException {
495+
private void addBundledSignatures(String name, String jdkTargetVersion, boolean logging, Set<String> missingClasses) throws IOException,ParseException {
469496
if (!name.matches("[A-Za-z0-9\\-\\.]+")) {
470497
throw new ParseException("Invalid bundled signature reference: " + name);
471498
}
@@ -487,13 +514,15 @@ private void addBundledSignatures(String name, String jdkTargetVersion, boolean
487514
throw new FileNotFoundException("Bundled signatures resource not found: " + name);
488515
}
489516
if (logging) logger.info("Reading bundled API signatures: " + name);
490-
parseSignaturesFile(in, true);
517+
parseSignaturesStream(in, true, missingClasses);
491518
}
492519

493520
/** Reads a list of API signatures. Closes the Reader when done (on Exception, too)! */
494521
public void parseSignaturesFile(InputStream in, String name) throws IOException,ParseException {
495522
logger.info("Reading API signatures: " + name);
496-
parseSignaturesFile(in, false);
523+
final Set<String> missingClasses = new TreeSet<String>();
524+
parseSignaturesStream(in, false, missingClasses);
525+
reportMissingSignatureClasses(missingClasses);
497526
}
498527

499528
/** Reads a list of API signatures from the given URL. */
@@ -509,18 +538,20 @@ public void parseSignaturesFile(File f) throws IOException,ParseException {
509538
/** Reads a list of API signatures from a String. */
510539
public void parseSignaturesString(String signatures) throws IOException,ParseException {
511540
logger.info("Reading inline API signatures...");
512-
parseSignaturesFile(new StringReader(signatures), false);
541+
final Set<String> missingClasses = new TreeSet<String>();
542+
parseSignaturesFile(new StringReader(signatures), false, missingClasses);
543+
reportMissingSignatureClasses(missingClasses);
513544
}
514545

515-
private void parseSignaturesFile(InputStream in, boolean allowBundled) throws IOException,ParseException {
516-
parseSignaturesFile(new InputStreamReader(in, "UTF-8"), allowBundled);
546+
private void parseSignaturesStream(InputStream in, boolean allowBundled, Set<String> missingClasses) throws IOException,ParseException {
547+
parseSignaturesFile(new InputStreamReader(in, "UTF-8"), allowBundled, missingClasses);
517548
}
518549

519550
private static final String BUNDLED_PREFIX = "@includeBundled ";
520551
private static final String DEFAULT_MESSAGE_PREFIX = "@defaultMessage ";
521552
private static final String IGNORE_UNRESOLVABLE_LINE = "@ignoreUnresolvable";
522553

523-
private void parseSignaturesFile(Reader reader, boolean isBundled) throws IOException,ParseException {
554+
private void parseSignaturesFile(Reader reader, boolean isBundled, Set<String> missingClasses) throws IOException,ParseException {
524555
final BufferedReader r = new BufferedReader(reader);
525556
try {
526557
String line, defaultMessage = null;
@@ -532,7 +563,7 @@ private void parseSignaturesFile(Reader reader, boolean isBundled) throws IOExce
532563
if (line.startsWith("@")) {
533564
if (isBundled && line.startsWith(BUNDLED_PREFIX)) {
534565
final String name = line.substring(BUNDLED_PREFIX.length()).trim();
535-
addBundledSignatures(name, null, false);
566+
addBundledSignatures(name, null, false, missingClasses);
536567
} else if (line.startsWith(DEFAULT_MESSAGE_PREFIX)) {
537568
defaultMessage = line.substring(DEFAULT_MESSAGE_PREFIX.length()).trim();
538569
if (defaultMessage.length() == 0) defaultMessage = null;
@@ -542,7 +573,7 @@ private void parseSignaturesFile(Reader reader, boolean isBundled) throws IOExce
542573
throw new ParseException("Invalid line in signature file: " + line);
543574
}
544575
} else {
545-
addSignature(line, defaultMessage, reporter);
576+
addSignature(line, defaultMessage, reporter, missingClasses);
546577
}
547578
}
548579
} finally {

src/test/antunit/TestInlineSignatures.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
java.lang.String#forbiddenFoobarField @ should be ignored
9898
java.awt.Color @ Color is disallowed, thats not bad, because ANT has no colors... (this was just added to don't fail because of missing signatures)
9999
</forbiddenapis>
100-
<au:assertLogContains level="warning" text="Class 'foo.bar.ForbiddenApis' not found on classpath while parsing signature: foo.bar.ForbiddenApis#testMethod() [signature ignored]"/>
100+
<au:assertLogContains level="warning" text="Some signatures were ignored because the following classes were not found on classpath: foo.bar.ForbiddenApis"/>
101101
<au:assertLogContains level="warning" text="Method not found while parsing signature: java.lang.String#forbiddenFoobarMethod() [signature ignored]"/>
102102
<au:assertLogContains level="warning" text="Field not found while parsing signature: java.lang.String#forbiddenFoobarField [signature ignored]"/>
103103
</target>
@@ -110,7 +110,7 @@
110110
java.lang.String#forbiddenFoobarField @ should be ignored
111111
java.awt.Color @ Color is disallowed, thats not bad, because ANT has no colors... (this was just added to don't fail because of missing signatures)
112112
</forbiddenapis>
113-
<au:assertLogContains level="warning" text="Class 'foo.bar.ForbiddenApis' not found on classpath while parsing signature: foo.bar.ForbiddenApis#testMethod() [signature ignored]"/>
113+
<au:assertLogContains level="warning" text="Some signatures were ignored because the following classes were not found on classpath: foo.bar.ForbiddenApis"/>
114114
<au:assertLogContains level="warning" text="Method not found while parsing signature: java.lang.String#forbiddenFoobarMethod() [signature ignored]"/>
115115
<au:assertLogContains level="warning" text="Field not found while parsing signature: java.lang.String#forbiddenFoobarField [signature ignored]"/>
116116
</target>

src/test/antunit/TestMavenMojo.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
<sysproperty key="antunit.signatures" value="foo.bar.ForbiddenApis#testMethod()&#10;java.lang.String#forbiddenFoobarMethod()&#10;java.lang.String#forbiddenFoobarField"/>
8585
<sysproperty key="antunit.failOnUnresolvableSignatures" value="false"/>
8686
</artifact:mvn>
87-
<au:assertLogContains text="Class 'foo.bar.ForbiddenApis' not found on classpath while parsing signature: foo.bar.ForbiddenApis#testMethod() [signature ignored]"/>
87+
<au:assertLogContains text="Some signatures were ignored because the following classes were not found on classpath: foo.bar.ForbiddenApis"/>
8888
<au:assertLogContains text="Method not found while parsing signature: java.lang.String#forbiddenFoobarMethod() [signature ignored]"/>
8989
<au:assertLogContains text="Field not found while parsing signature: java.lang.String#forbiddenFoobarField [signature ignored]"/>
9090
</target>

0 commit comments

Comments
 (0)