Skip to content

Commit 6f406dc

Browse files
committed
Addon for #81: Better parsing and fixing of JDK versions to 1.x style.
Add support for targetVersion in Ant task. This closes #101
1 parent 49d3a7c commit 6f406dc

13 files changed

+148
-33
lines changed

build.xml

+7-7
Original file line numberDiff line numberDiff line change
@@ -466,14 +466,14 @@
466466
</target>
467467

468468
<target name="-check-myself" depends="compile,compile-tools,compile-test,-install-forbiddenapi-task">
469-
<forbiddenapis failOnUnsupportedJava="false">
469+
<forbiddenapis failOnUnsupportedJava="false" targetVersion="${jdk.version}">
470470
<classpath refid="path.all"/>
471471
<fileset dir="build/main"/>
472472
<fileset dir="build/tools"/>
473473
<fileset dir="build/test"/>
474474
<signatures>
475-
<bundled name="jdk-unsafe-${jdk.version}"/>
476-
<bundled name="jdk-deprecated-${jdk.version}"/>
475+
<bundled name="jdk-unsafe"/>
476+
<bundled name="jdk-deprecated"/>
477477
<bundled name="jdk-non-portable"/>
478478
<bundled name="jdk-system-out"/>
479479
<bundled name="jdk-reflection"/>
@@ -482,11 +482,11 @@
482482
</target>
483483

484484
<target name="-check-bundled-signatures" depends="-install-forbiddenapi-task" if="tests.supported">
485-
<forbiddenapis failOnUnsupportedJava="true" ignoreEmptyFileset="true">
485+
<forbiddenapis failOnUnsupportedJava="true" ignoreEmptyFileset="true" targetVersion="${build.java.runtime}">
486486
<signatures>
487-
<bundled name="jdk-unsafe-${build.java.runtime}"/>
488-
<bundled name="jdk-deprecated-${build.java.runtime}"/>
489-
<bundled name="jdk-internal-${build.java.runtime}"/>
487+
<bundled name="jdk-unsafe"/>
488+
<bundled name="jdk-deprecated"/>
489+
<bundled name="jdk-internal"/>
490490
<bundled name="jdk-system-out"/>
491491
<bundled name="jdk-reflection"/>
492492
</signatures>

src/main/docs/ant-task.html

+11-2
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,15 @@ <h2>Parameters</h2>
151151
pattern may be used (e.g., <code>**.SuppressForbidden</code>).</td>
152152
</tr>
153153

154+
<tr>
155+
<td>targetVersion</td>
156+
<td><code>String</code></td>
157+
<td></td>
158+
<td>The compiler target version used to expand references to bundled JDK signatures.
159+
E.g., if you use &quot;jdk-deprecated&quot;, it will expand to this version.
160+
This setting should be identical to the target version used when invoking <tt>javac</tt>.</td>
161+
</tr>
162+
154163
</table>
155164

156165
<h2>Parameters specified as nested elements</h2>
@@ -165,8 +174,8 @@ <h2>Parameters specified as nested elements</h2>
165174
<p>To pass in signatures, you have several possibilities:</p>
166175

167176
<ul>
168-
<li>Use <code>bundledSignatures</code> element to pass a <a href="bundled-signatures.html">built-in signatures</a> file, e.g. <code>&lt;bundledsignatures name=&quot;jdk-unsafe-1.7&quot;/&gt;</code></li>
169-
<li>Use <code>signatures</code> element to wrap any valid <a href="https://ant.apache.org/manual/Types/resources.html">Ant resource</a> type (filesets,..). May also be used to wrap <code>&lt;bundled name=&quot;jdk-unsafe-1.7&quot;/&gt;</code></li>
177+
<li>Use <code>bundledSignatures</code> element to pass a <a href="bundled-signatures.html">built-in signatures</a> file, e.g. <code>&lt;bundledsignatures name=&quot;jdk-unsafe&quot; targetVersion=&quot;1.7&quot;/&gt;</code></li>
178+
<li>Use <code>signatures</code> element to wrap any valid <a href="https://ant.apache.org/manual/Types/resources.html">Ant resource</a> type (filesets,..). May also be used to wrap <code>&lt;bundled name=&quot;jdk-unsafe&quot; targetVersion=&quot;1.7&quot;/&gt;</code></li>
170179
<li>Alternatively, use <code>signaturesFileSet</code>, <code>signaturesFileList</code>, <code>signaturesFile</code> elements to pass in collections of signatures files. Those elements behave like the corresponding standard Ant types.</li>
171180
<li>Place signatures as plain text (use CDATA sections) inside the <code>forbiddenapis</code> element.</li>
172181
</ul>

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

+21-4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import java.util.Set;
4747
import java.util.StringTokenizer;
4848
import java.util.TreeSet;
49+
import java.util.regex.Matcher;
4950
import java.util.regex.Pattern;
5051
import java.lang.annotation.Annotation;
5152
import java.lang.management.ManagementFactory;
@@ -426,6 +427,24 @@ public void addBundledSignatures(String name, String jdkTargetVersion) throws IO
426427
addBundledSignatures(name, jdkTargetVersion, true);
427428
}
428429

430+
public static String fixTargetVersion(String name) throws ParseException {
431+
final Matcher m = JDK_SIG_PATTERN.matcher(name);
432+
if (m.matches()) {
433+
if (m.group(4) == null) {
434+
// rewrite version number if it does not start with "1"
435+
if ("1".equals(m.group(2)) && m.group(3) != null) {
436+
return name;
437+
} else {
438+
if (".0".equals(m.group(3)) || m.group(3) == null) {
439+
return m.group(1) + "1." + m.group(2);
440+
}
441+
}
442+
}
443+
throw new ParseException("Invalid bundled signature reference (JDK version is invalid): " + name);
444+
}
445+
return name;
446+
}
447+
429448
private void addBundledSignatures(String name, String jdkTargetVersion, boolean logging) throws IOException,ParseException {
430449
if (!name.matches("[A-Za-z0-9\\-\\.]+")) {
431450
throw new ParseException("Invalid bundled signature reference: " + name);
@@ -435,15 +454,13 @@ private void addBundledSignatures(String name, String jdkTargetVersion, boolean
435454
forbidNonPortableRuntime = true;
436455
return;
437456
}
457+
name = fixTargetVersion(name);
438458
// use Checker.class hardcoded (not getClass) so we have a fixed package name:
439459
InputStream in = Checker.class.getResourceAsStream("signatures/" + name + ".txt");
440460
// automatically expand the compiler version in here (for jdk-* signatures without version):
441461
if (in == null && jdkTargetVersion != null && name.startsWith("jdk-") && !name.matches(".*?\\-\\d\\.\\d")) {
442-
// convert the "new" version number "major.0" to old-style "1.major" (as this matches our resources):
443-
if (!jdkTargetVersion.startsWith("1.") && jdkTargetVersion.matches("\\d(\\.0|)")) {
444-
jdkTargetVersion = "1." + jdkTargetVersion.substring(0, 1);
445-
}
446462
name = name + "-" + jdkTargetVersion;
463+
name = fixTargetVersion(name);
447464
in = Checker.class.getResourceAsStream("signatures/" + name + ".txt");
448465
}
449466
if (in == null) {

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

+3
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@
1919
package de.thetaphi.forbiddenapis;
2020

2121
import java.util.Locale;
22+
import java.util.regex.Pattern;
2223

2324
public interface Constants {
2425

2526
final String BS_JDK_NONPORTABLE = "jdk-non-portable";
2627

28+
final Pattern JDK_SIG_PATTERN = Pattern.compile("(jdk\\-.*?\\-)(\\d)(\\.\\d)?(\\.\\d)*");
29+
2730
final String DEPRECATED_WARN_INTERNALRUNTIME = String.format(Locale.ENGLISH,
2831
"The setting 'internalRuntimeForbidden' was deprecated and will be removed in next version. For backwards compatibility task/mojo is using '%s' bundled signatures instead.", BS_JDK_NONPORTABLE);
2932

src/main/java/de/thetaphi/forbiddenapis/ant/AntTask.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public class AntTask extends Task implements Constants {
7070
private boolean failOnUnresolvableSignatures = true;
7171
private boolean failOnViolation = true;
7272
private boolean ignoreEmptyFileset = false;
73+
private String targetVersion = null;
7374

7475
@Override
7576
public void execute() throws BuildException {
@@ -132,7 +133,19 @@ public void info(String msg) {
132133
if (name == null) {
133134
throw new BuildException("<bundledSignatures/> must have the mandatory attribute 'name' referring to a bundled signatures file.");
134135
}
135-
checker.addBundledSignatures(name, null);
136+
String targetVersion = this.targetVersion;
137+
if (bs.getTargetVersion() != null) {
138+
if (!name.startsWith("jdk-")) {
139+
throw new ParseException("Cannot supply a targetVersion for non-JDK signatures.");
140+
}
141+
targetVersion = bs.getTargetVersion();
142+
}
143+
if (targetVersion == null && name.startsWith("jdk-")) {
144+
log.warn("The 'targetVersion' parameter is missing. " +
145+
"Trying to read bundled JDK signatures without compiler target. " +
146+
"You have to explicitely specify the version in the resource name.");
147+
}
148+
checker.addBundledSignatures(name, targetVersion);
136149
}
137150
if (internalRuntimeForbidden) {
138151
log.warn(DEPRECATED_WARN_INTERNALRUNTIME);
@@ -357,4 +370,14 @@ public void setIgnoreEmptyFileSet(boolean ignoreEmptyFileset) {
357370
public void setFailOnViolation(boolean failOnViolation) {
358371
this.failOnViolation = failOnViolation;
359372
}
373+
374+
/**
375+
* The default compiler target version used to expand references to bundled JDK signatures.
376+
* E.g., if you use "jdk-deprecated", it will expand to this version.
377+
* This setting should be identical to the target version used in the compiler task.
378+
* Defaults to {@code null}.
379+
*/
380+
public void setTargetVersion(String targetVersion) {
381+
this.targetVersion = targetVersion;
382+
}
360383
}

src/main/java/de/thetaphi/forbiddenapis/ant/BundledSignaturesType.java

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
public final class BundledSignaturesType extends ProjectComponent {
2222

2323
private String name = null;
24+
private String targetVersion = null;
2425

2526
public void setName(String name) {
2627
this.name = name;
@@ -30,4 +31,12 @@ public String getName() {
3031
return name;
3132
}
3233

34+
public void setTargetVersion(String targetVersion) {
35+
this.targetVersion = targetVersion;
36+
}
37+
38+
public String getTargetVersion() {
39+
return targetVersion;
40+
}
41+
3342
}

src/test/antunit/TestCommonsIOSignatures.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
<echo message="Testing signatures of version ${commons-io-version}..."/>
3333
<ivy:cachepath organisation="commons-io" module="commons-io" revision="${commons-io-version}"
3434
inline="true" conf="master" type="jar" pathid="commons-io.classpath" log="${ivy.logging}"/>
35-
<forbiddenapis bundledSignatures="${commons-io-signature}" ignoreEmptyFileset="true" classpathref="commons-io.classpath"/>
35+
<forbiddenapis bundledSignatures="${commons-io-signature}" ignoreEmptyFileset="true" classpathref="commons-io.classpath" targetVersion="${jdk.version}"/>
3636
</target>
3737

3838
</project>

src/test/antunit/TestDeprecatedTask.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
<taskdef name="forbiddenapis-deprecated" classname="de.thetaphi.forbiddenapis.AntTask" classpath="${jar-file}"/>
2020

2121
<target name="testMySelf">
22-
<forbiddenapis-deprecated classpathref="path.all">
22+
<forbiddenapis-deprecated classpathref="path.all" targetVersion="${jdk.version}">
2323
<fileset dir="${antunit.main.classes}"/>
24-
<bundledsignatures name="jdk-unsafe-${jdk.version}"/>
25-
<bundledsignatures name="jdk-deprecated-${jdk.version}"/>
24+
<bundledsignatures name="jdk-unsafe"/>
25+
<bundledsignatures name="jdk-deprecated"/>
2626
<bundledsignatures name="jdk-non-portable"/>
2727
</forbiddenapis-deprecated>
2828
<au:assertLogContains level="info" text=" 0 error(s)."/>

src/test/antunit/TestFileSignatures.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@
5959

6060
<target name="testGeneralResources">
6161
<au:expectfailure expectedMessage="Check for forbidden API calls failed, see log">
62-
<forbiddenapis classpathref="path.all">
62+
<forbiddenapis classpathref="path.all" targetVersion="${jdk.version}">
6363
<fileset refid="main.classes"/>
6464
<signatures>
6565
<file file="signatures1.txt"/>
6666
<string>java.util.Locale#ENGLISH @ We are speaking chinese here!</string>
67-
<bundled name="jdk-unsafe-${jdk.version}"/>
67+
<bundled name="jdk-unsafe"/>
6868
</signatures>
6969
</forbiddenapis>
7070
</au:expectfailure>

src/test/antunit/TestFinalJAR.xml

+10-9
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,28 @@
1919
<taskdef name="forbiddenapis-jar" classname="de.thetaphi.forbiddenapis.ant.AntTask" classpath="${jar-file}"/>
2020

2121
<target name="testMySelfWithFinalJAR1">
22-
<forbiddenapis-jar classpathref="path.all">
22+
<forbiddenapis-jar classpathref="path.all" targetVersion="${jdk.version}">
2323
<fileset dir="${antunit.main.classes}"/>
24-
<bundledsignatures name="jdk-unsafe-${jdk.version}"/>
25-
<bundledsignatures name="jdk-deprecated-${jdk.version}"/>
24+
<bundledsignatures name="jdk-unsafe"/>
25+
<bundledsignatures name="jdk-deprecated"/>
2626
<bundledsignatures name="jdk-non-portable"/>
2727
</forbiddenapis-jar>
2828
<au:assertLogContains level="info" text=" 0 error(s)."/>
2929
</target>
3030

3131
<target name="testMySelfWithFinalJAR2">
3232
<forbiddenapis-jar dir="${antunit.main.classes}" classpathref="path.all">
33-
<bundledsignatures name="jdk-unsafe-${jdk.version}"/>
34-
<bundledsignatures name="jdk-deprecated-${jdk.version}"/>
35-
<bundledsignatures name="jdk-non-portable"/>
33+
<bundledsignatures name="jdk-unsafe" targetVersion="${jdk.version}"/>
34+
<bundledsignatures name="jdk-deprecated" targetVersion="${jdk.version}"/>
35+
<bundledsignatures name="jdk-non-portable" targetVersion="${jdk.version}"/>
3636
</forbiddenapis-jar>
3737
<au:assertLogContains level="info" text=" 0 error(s)."/>
3838
</target>
3939

4040
<target name="testMySelfWithAntLib">
4141
<taskdef uri="antlib:de.thetaphi.forbiddenapis" classpath="${jar-file}"/>
4242
<fa:forbiddenapis xmlns:fa="antlib:de.thetaphi.forbiddenapis" dir="${antunit.main.classes}" classpathref="path.all">
43+
<!-- here with hardcoded versions -->
4344
<bundledsignatures name="jdk-unsafe-${jdk.version}"/>
4445
<bundledsignatures name="jdk-deprecated-${jdk.version}"/>
4546
<bundledsignatures name="jdk-non-portable"/>
@@ -55,10 +56,10 @@
5556
only plexus-utils v1.1, which is much slimmer and does not reference
5657
broken StringUtils. ASM is completely forbidden-api bug-free!
5758
-->
58-
<forbiddenapis-jar>
59+
<forbiddenapis-jar targetVersion="${jdk.version}">
5960
<zipfileset src="${jar-file}" excludes="de/thetaphi/forbiddenapis/commons/cli/**"/>
60-
<bundledsignatures name="jdk-unsafe-${jdk.version}"/>
61-
<bundledsignatures name="jdk-deprecated-${jdk.version}"/>
61+
<bundledsignatures name="jdk-unsafe"/>
62+
<bundledsignatures name="jdk-deprecated"/>
6263
<bundledsignatures name="jdk-non-portable"/>
6364
<classpath>
6465
<pathelement path="${jar-file}"/>

src/test/antunit/TestInternalRuntimeCalls.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
<target name="testNonPortableSignatures" if="has.sunmisc">
2424
<au:expectfailure expectedMessage="Check for forbidden API calls failed, see log">
25-
<forbiddenapis failOnMissingClasses="false">
25+
<forbiddenapis failOnMissingClasses="false" targetVersion="${jdk.version}">
2626
<file file="OracleInternalRuntime.class"/>
2727
<bundledsignatures name="jdk-non-portable"/>
2828
</forbiddenapis>
@@ -45,9 +45,9 @@
4545
<!-- this should work also with non-Oracle runtimes, as no heuristics: -->
4646
<target name="testInternalSignatures">
4747
<au:expectfailure expectedMessage="Check for forbidden API calls failed, see log">
48-
<forbiddenapis failOnMissingClasses="false">
48+
<forbiddenapis failOnMissingClasses="false" targetVersion="${jdk.version}">
4949
<file file="OracleInternalRuntime.class"/>
50-
<bundledsignatures name="jdk-internal-${jdk.version}"/>
50+
<bundledsignatures name="jdk-internal"/>
5151
</forbiddenapis>
5252
</au:expectfailure>
5353
<au:assertLogContains level="error" text="sun.misc.BASE64Encoder [non-public internal runtime class in Java ${jdk.version}]"/>

src/test/antunit/TestJava6Reflection.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
<target name="testReflection">
2020
<au:expectfailure expectedMessage="Check for forbidden API calls failed, see log">
21-
<forbiddenapis>
21+
<forbiddenapis targetVersion="${jdk.version}">
2222
<bundledsignatures name="jdk-reflection"/>
2323
<file file="Java6Reflection.class"/>
2424
</forbiddenapis>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* (C) Copyright Uwe Schindler (Generics Policeman) and others.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package de.thetaphi.forbiddenapis;
18+
19+
import static org.junit.Assert.assertEquals;
20+
import static org.junit.Assert.fail;
21+
22+
import org.junit.Test;
23+
24+
public final class CheckerStaticTest {
25+
26+
@Test
27+
public void testTragetVersionFix() throws Exception {
28+
assertEquals("jdk-dummy-1.7", Checker.fixTargetVersion("jdk-dummy-1.7"));
29+
assertEquals("jdk-dummy-1.7", Checker.fixTargetVersion("jdk-dummy-7"));
30+
assertEquals("jdk-dummy-1.7", Checker.fixTargetVersion("jdk-dummy-7.0"));
31+
32+
assertEquals("jdk-dummy-1.1", Checker.fixTargetVersion("jdk-dummy-1"));
33+
assertEquals("jdk-dummy-1.1", Checker.fixTargetVersion("jdk-dummy-1.1"));
34+
35+
assertFails("jdk-dummy-1.7.1");
36+
assertFails("jdk-dummy-1.7.1.1");
37+
assertFails("jdk-dummy-1.7.0.1");
38+
39+
assertFails("jdk-dummy-7.1");
40+
assertFails("jdk-dummy-7.1.1");
41+
assertFails("jdk-dummy-7.0.1");
42+
}
43+
44+
private void assertFails(String name) {
45+
try {
46+
Checker.fixTargetVersion(name);
47+
fail("Should fail for: " + name);
48+
} catch (ParseException pe) {
49+
// pass
50+
}
51+
}
52+
53+
}

0 commit comments

Comments
 (0)