Skip to content

Commit b95a724

Browse files
authored
Merge pull request #140 from /issues/83
Fix for issue #83: Tone down warnings by missing classes in signatures files
2 parents fbe7a3e + 63bae01 commit b95a724

File tree

3 files changed

+57
-18
lines changed

3 files changed

+57
-18
lines changed

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

+51-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,30 @@ 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+
return;
452+
}
453+
logger.warn("Some signatures were ignored because the following classes were not found on classpath:");
454+
final StringBuilder sb = new StringBuilder();
455+
int count = 0;
456+
for (String s : missingClasses) {
457+
sb.append(count == 0 ? " " : ", ").append(s);
458+
count++;
459+
if (sb.length() >= 70) {
460+
sb.append(",... (and ").append(missingClasses.size() - count).append(" more).");
461+
break;
462+
}
463+
}
464+
logger.warn(sb.toString());
465+
}
436466

437467
/** Reads a list of bundled API signatures from classpath. */
438468
public void addBundledSignatures(String name, String jdkTargetVersion) throws IOException,ParseException {
439-
addBundledSignatures(name, jdkTargetVersion, true);
469+
final Set<String> missingClasses = new TreeSet<String>();
470+
addBundledSignatures(name, jdkTargetVersion, true, missingClasses);
471+
reportMissingSignatureClasses(missingClasses);
440472
}
441473

442474
public static String fixTargetVersion(String name) throws ParseException {
@@ -465,7 +497,7 @@ public static String fixTargetVersion(String name) throws ParseException {
465497
return name;
466498
}
467499

468-
private void addBundledSignatures(String name, String jdkTargetVersion, boolean logging) throws IOException,ParseException {
500+
private void addBundledSignatures(String name, String jdkTargetVersion, boolean logging, Set<String> missingClasses) throws IOException,ParseException {
469501
if (!name.matches("[A-Za-z0-9\\-\\.]+")) {
470502
throw new ParseException("Invalid bundled signature reference: " + name);
471503
}
@@ -487,13 +519,15 @@ private void addBundledSignatures(String name, String jdkTargetVersion, boolean
487519
throw new FileNotFoundException("Bundled signatures resource not found: " + name);
488520
}
489521
if (logging) logger.info("Reading bundled API signatures: " + name);
490-
parseSignaturesFile(in, true);
522+
parseSignaturesStream(in, true, missingClasses);
491523
}
492524

493525
/** Reads a list of API signatures. Closes the Reader when done (on Exception, too)! */
494526
public void parseSignaturesFile(InputStream in, String name) throws IOException,ParseException {
495527
logger.info("Reading API signatures: " + name);
496-
parseSignaturesFile(in, false);
528+
final Set<String> missingClasses = new TreeSet<String>();
529+
parseSignaturesStream(in, false, missingClasses);
530+
reportMissingSignatureClasses(missingClasses);
497531
}
498532

499533
/** Reads a list of API signatures from the given URL. */
@@ -509,18 +543,20 @@ public void parseSignaturesFile(File f) throws IOException,ParseException {
509543
/** Reads a list of API signatures from a String. */
510544
public void parseSignaturesString(String signatures) throws IOException,ParseException {
511545
logger.info("Reading inline API signatures...");
512-
parseSignaturesFile(new StringReader(signatures), false);
546+
final Set<String> missingClasses = new TreeSet<String>();
547+
parseSignaturesFile(new StringReader(signatures), false, missingClasses);
548+
reportMissingSignatureClasses(missingClasses);
513549
}
514550

515-
private void parseSignaturesFile(InputStream in, boolean allowBundled) throws IOException,ParseException {
516-
parseSignaturesFile(new InputStreamReader(in, "UTF-8"), allowBundled);
551+
private void parseSignaturesStream(InputStream in, boolean allowBundled, Set<String> missingClasses) throws IOException,ParseException {
552+
parseSignaturesFile(new InputStreamReader(in, "UTF-8"), allowBundled, missingClasses);
517553
}
518554

519555
private static final String BUNDLED_PREFIX = "@includeBundled ";
520556
private static final String DEFAULT_MESSAGE_PREFIX = "@defaultMessage ";
521557
private static final String IGNORE_UNRESOLVABLE_LINE = "@ignoreUnresolvable";
522558

523-
private void parseSignaturesFile(Reader reader, boolean isBundled) throws IOException,ParseException {
559+
private void parseSignaturesFile(Reader reader, boolean isBundled, Set<String> missingClasses) throws IOException,ParseException {
524560
final BufferedReader r = new BufferedReader(reader);
525561
try {
526562
String line, defaultMessage = null;
@@ -532,7 +568,7 @@ private void parseSignaturesFile(Reader reader, boolean isBundled) throws IOExce
532568
if (line.startsWith("@")) {
533569
if (isBundled && line.startsWith(BUNDLED_PREFIX)) {
534570
final String name = line.substring(BUNDLED_PREFIX.length()).trim();
535-
addBundledSignatures(name, null, false);
571+
addBundledSignatures(name, null, false, missingClasses);
536572
} else if (line.startsWith(DEFAULT_MESSAGE_PREFIX)) {
537573
defaultMessage = line.substring(DEFAULT_MESSAGE_PREFIX.length()).trim();
538574
if (defaultMessage.length() == 0) defaultMessage = null;
@@ -542,7 +578,7 @@ private void parseSignaturesFile(Reader reader, boolean isBundled) throws IOExce
542578
throw new ParseException("Invalid line in signature file: " + line);
543579
}
544580
} else {
545-
addSignature(line, defaultMessage, reporter);
581+
addSignature(line, defaultMessage, reporter, missingClasses);
546582
}
547583
}
548584
} finally {

src/test/antunit/TestInlineSignatures.xml

+4-2
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@
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:"/>
101+
<au:assertLogContains level="warning" text=" foo.bar.ForbiddenApis"/>
101102
<au:assertLogContains level="warning" text="Method not found while parsing signature: java.lang.String#forbiddenFoobarMethod() [signature ignored]"/>
102103
<au:assertLogContains level="warning" text="Field not found while parsing signature: java.lang.String#forbiddenFoobarField [signature ignored]"/>
103104
</target>
@@ -110,7 +111,8 @@
110111
java.lang.String#forbiddenFoobarField @ should be ignored
111112
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)
112113
</forbiddenapis>
113-
<au:assertLogContains level="warning" text="Class 'foo.bar.ForbiddenApis' not found on classpath while parsing signature: foo.bar.ForbiddenApis#testMethod() [signature ignored]"/>
114+
<au:assertLogContains level="warning" text="Some signatures were ignored because the following classes were not found on classpath:"/>
115+
<au:assertLogContains level="warning" text=" foo.bar.ForbiddenApis"/>
114116
<au:assertLogContains level="warning" text="Method not found while parsing signature: java.lang.String#forbiddenFoobarMethod() [signature ignored]"/>
115117
<au:assertLogContains level="warning" text="Field not found while parsing signature: java.lang.String#forbiddenFoobarField [signature ignored]"/>
116118
</target>

src/test/antunit/TestMavenMojo.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@
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:"/>
88+
<au:assertLogContains text=" foo.bar.ForbiddenApis"/>
8889
<au:assertLogContains text="Method not found while parsing signature: java.lang.String#forbiddenFoobarMethod() [signature ignored]"/>
8990
<au:assertLogContains text="Field not found while parsing signature: java.lang.String#forbiddenFoobarField [signature ignored]"/>
9091
</target>

0 commit comments

Comments
 (0)