From f1be3a1234919913a04944b9664a2672cd0a16f2 Mon Sep 17 00:00:00 2001 From: Uwe Schindler Date: Wed, 2 Apr 2025 19:48:00 +0200 Subject: [PATCH 1/2] Fix severity override in Ant task by using child elements (see #253) --- src/main/docs/ant-task.html | 19 ++--- .../de/thetaphi/forbiddenapis/Signatures.java | 8 +- .../thetaphi/forbiddenapis/ant/AntTask.java | 42 +++++----- .../ant/SeverityOverrideType.java | 50 ++++++++++++ .../ant/SignaturesResources.java | 5 ++ src/test/antunit/TestSeverityOverrides.xml | 76 +++++++++++++++++++ 6 files changed, 160 insertions(+), 40 deletions(-) create mode 100644 src/main/java/de/thetaphi/forbiddenapis/ant/SeverityOverrideType.java create mode 100644 src/test/antunit/TestSeverityOverrides.xml diff --git a/src/main/docs/ant-task.html b/src/main/docs/ant-task.html index bd78c069..d669eff9 100644 --- a/src/main/docs/ant-task.html +++ b/src/main/docs/ant-task.html @@ -73,20 +73,6 @@

Parameters

Name of a built-in signatures file. - - signaturesWithSeveritySuppress - String - - A forbidden API signature for which violations should not be reported at all (i.e. neither fail the build nor appear in the logs). This takes precedence overfailOnViolation and signaturesWithSeverityWarn. - - - - signaturesWithSeverityWarn - String - - A forbidden API signature for which violations should be reported as warnings (i.e. not fail the build). This takes precedence overfailOnViolation. - - classpath Path @@ -217,6 +203,11 @@

Parameters specified as nested elements

RetentionPolicy#CLASS. They can be applied to classes, their methods, or fields. By default, @de.thetaphi.forbiddenapis.SuppressForbidden can always be used, but needs the forbidden-apis.jar file in classpath of compiled project, which may not be wanted. Instead of a full class name, a glob pattern may be used (e.g., **.SuppressForbidden).

+ +

You can include multiple <severityOverride severity="(ERROR|WARNING|INFO|DEBUG|SUPPRESS)">...signature...<severityOverride> elements to +override problem severity of certain signatures (i.e. not fail the build). This takes precedence over failOnViolation. If several signatures should get the same +severity you can separate them by newlines. It is also possible to separate them into different elements. Each signature must be specified in exactly the same way like in the +original signatures files!

\ No newline at end of file diff --git a/src/main/java/de/thetaphi/forbiddenapis/Signatures.java b/src/main/java/de/thetaphi/forbiddenapis/Signatures.java index e32c91e1..0399ce9f 100644 --- a/src/main/java/de/thetaphi/forbiddenapis/Signatures.java +++ b/src/main/java/de/thetaphi/forbiddenapis/Signatures.java @@ -173,7 +173,7 @@ private void addSignature(final String line, final String defaultMessage, final } } -private Collection getKeys(final UnresolvableReporting report, final boolean localIgnoreMissingClasses, final Set missingClasses, + private Collection getKeys(final UnresolvableReporting report, final boolean localIgnoreMissingClasses, final Set missingClasses, final String signature) throws ParseException, IOException { final String clazz; final String field; @@ -374,9 +374,9 @@ public boolean noSignaturesFilesParsed() { return numberOfFiles == 0; } - public void setSignaturesSeverity(Collection signature, ViolationSeverity severity) throws ParseException, IOException { - logger.info("Adjusting severity to " + severity + " for signatures..."); - for (String s : signature) { + public void setSignaturesSeverity(Collection signatures, ViolationSeverity severity) throws ParseException, IOException { + logger.info("Adjusting severity to " + severity + " for " + signatures.size() + " signatures..."); + for (String s : signatures) { setSignatureSeverity(s, severity); } } diff --git a/src/main/java/de/thetaphi/forbiddenapis/ant/AntTask.java b/src/main/java/de/thetaphi/forbiddenapis/ant/AntTask.java index 3a527556..d0635b05 100644 --- a/src/main/java/de/thetaphi/forbiddenapis/ant/AntTask.java +++ b/src/main/java/de/thetaphi/forbiddenapis/ant/AntTask.java @@ -23,10 +23,10 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Collection; import java.util.EnumSet; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.Locale; import org.apache.tools.ant.AntClassLoader; @@ -60,10 +60,9 @@ public class AntTask extends Task implements Constants { private final Union classFiles = new Union(); private final Union apiSignatures = new Union(); - private final Collection bundledSignatures = new LinkedHashSet<>(); - private final Collection suppressAnnotations = new LinkedHashSet<>(); - private final Collection signaturesWithSeverityWarn = new LinkedHashSet<>();; - private final Collection signaturesWithSeveritySuppress = new LinkedHashSet<>();; + private final Collection bundledSignatures = new ArrayList<>(); + private final Collection suppressAnnotations = new ArrayList<>(); + private final Collection severityOverrides = new ArrayList<>(); private Path classpath = null; @@ -178,11 +177,12 @@ public void debug(String msg) { checker.parseSignaturesFile(r.getInputStream(), r.toString()); } } - if (!signaturesWithSeverityWarn.isEmpty()) { - checker.setSignaturesSeverity(signaturesWithSeverityWarn, Checker.ViolationSeverity.WARNING); - } - if (!signaturesWithSeveritySuppress.isEmpty()) { - checker.setSignaturesSeverity(signaturesWithSeveritySuppress, Checker.ViolationSeverity.SUPPRESS); + + for (SeverityOverrideType override : severityOverrides) { + if (override.severity == null) { + throw new BuildException("Severity must be given as argument of element."); + } + checker.setSignaturesSeverity(override.getSignatures(), override.severity); } } catch (IOException ioe) { throw new BuildException("IO problem while reading files with API signatures: " + ioe.getMessage(), ioe); @@ -302,20 +302,18 @@ public void setBundledSignatures(String name) { } /** - * A list of forbidden API signatures for which violations should not be reported at all (i.e. neither fail the build nor appear in the logs). This takes precedence over {@link #failOnViolation} and {@link #signaturesWithSeverityWarn}. - * In order to be effective the signature must be given in either {@link #bundledSignatures}, {@link #signaturesFiles}, {@link #signaturesArtifacts}, or {@link #signatures}. + * Adds an override for forbidden API signatures for which violations should not be reported at all (i.e. neither fail the build nor appear in the logs). + * Each signature must be listed in a separate XML element (in text) and a {@code priority} attribute. + * This takes precedence over {@link #failOnViolation}. + * In order to be effective the signature must be given in one of the signatures elements (e.g., it can be used to disable a bundled signature which + * is not yet ready to be enforced). * @since 3.9 */ - public void setSignaturesWithSeverityWarn(String signature) { - signaturesWithSeverityWarn.add(signature); - } - - /** A list of forbidden API signatures for which violations should not be reported at all (i.e. neither fail the build nor appear in the logs). This takes precedence over {@link #failOnViolation} and {@link #signaturesWithSeverityWarn}. - * In order to be effective the signature must be given in either {@link #bundledSignatures}, {@link #signaturesFiles}, {@link #signaturesArtifacts}, or {@link #signatures}. - * @since 3.9 - */ - public void setSignaturesWithSeveritySuppress(String signature) { - signaturesWithSeveritySuppress.add(signature); + public SeverityOverrideType createSeverityOverride() { + final SeverityOverrideType s = new SeverityOverrideType(); + s.setProject(getProject()); + severityOverrides.add(s); + return s; } /** Creates a instance of an annotation class name that suppresses error reporting in classes/methods/fields. */ diff --git a/src/main/java/de/thetaphi/forbiddenapis/ant/SeverityOverrideType.java b/src/main/java/de/thetaphi/forbiddenapis/ant/SeverityOverrideType.java new file mode 100644 index 00000000..26e49df2 --- /dev/null +++ b/src/main/java/de/thetaphi/forbiddenapis/ant/SeverityOverrideType.java @@ -0,0 +1,50 @@ +/* + * (C) Copyright Uwe Schindler (Generics Policeman) and others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.thetaphi.forbiddenapis.ant; + +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.ProjectComponent; + +import de.thetaphi.forbiddenapis.Checker.ViolationSeverity; + +public final class SeverityOverrideType extends ProjectComponent { + + private final StringBuilder signatures = new StringBuilder(); + + ViolationSeverity severity = null; + + List getSignatures() { + return Arrays.asList(signatures.toString().trim().split("\\s*[\r\n]+\\s*")); + } + + public void addText(String signature) { + this.signatures.append('\n').append(signature); + } + + public void setSeverity(String severity) { + try { + this.severity = ViolationSeverity.valueOf(severity.toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException iae) { + throw new BuildException("Severity is not a valid enum value, use one of " + Arrays.toString(ViolationSeverity.values())); + } + } + +} diff --git a/src/main/java/de/thetaphi/forbiddenapis/ant/SignaturesResources.java b/src/main/java/de/thetaphi/forbiddenapis/ant/SignaturesResources.java index 2b065f2d..03c44bd7 100644 --- a/src/main/java/de/thetaphi/forbiddenapis/ant/SignaturesResources.java +++ b/src/main/java/de/thetaphi/forbiddenapis/ant/SignaturesResources.java @@ -31,4 +31,9 @@ public BundledSignaturesType createBundled() { return task.createBundledSignatures(); } + // we also allow to add a severity override in the element. Cool ne? + public SeverityOverrideType createSeverityOverride() { + return task.createSeverityOverride(); + } + } diff --git a/src/test/antunit/TestSeverityOverrides.xml b/src/test/antunit/TestSeverityOverrides.xml new file mode 100644 index 00000000..3750c680 --- /dev/null +++ b/src/test/antunit/TestSeverityOverrides.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + java.util.Locale#ENGLISH @ We are speaking chinese here! + java.lang.** @ You are crazy that you disallow all java.lang + java.io.** @ You are crazy that you disallow all java.io + java.util.Locale#ENGLISH + + java.lang.** + java.io.** + + + + + + + + + + + + + + + + + java.util.Locale#ENGLISH @ We are speaking chinese here! + java.lang.** @ You are crazy that you disallow all java.lang + + java.util.Locale#ENGLISH + java.lang.** + + + + + + + + + + + + + + + + java.lang.String#substring(int,int) @ You are crazy that you disallow substrings + java.lang.String#substring(int,int) + + + + + + + \ No newline at end of file From 5778ede7b97fafef046ed645b68970f1093e4794 Mon Sep 17 00:00:00 2001 From: Uwe Schindler Date: Wed, 2 Apr 2025 20:01:53 +0200 Subject: [PATCH 2/2] fix indent --- src/main/java/de/thetaphi/forbiddenapis/Checker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/thetaphi/forbiddenapis/Checker.java b/src/main/java/de/thetaphi/forbiddenapis/Checker.java index 0c9d06e9..47526a22 100644 --- a/src/main/java/de/thetaphi/forbiddenapis/Checker.java +++ b/src/main/java/de/thetaphi/forbiddenapis/Checker.java @@ -60,7 +60,7 @@ public static enum Option { } public enum ViolationSeverity { - ERROR, WARNING, INFO, DEBUG, SUPPRESS + ERROR, WARNING, INFO, DEBUG, SUPPRESS } public final boolean isSupportedJDK;