Skip to content

Commit ccfecc1

Browse files
committed
Merge pull request #69 from policeman-tools/features-pkg-refactor
Package refactoring of Cli, Ant, Maven
2 parents bc413f5 + ac2c1c0 commit ccfecc1

14 files changed

+428
-337
lines changed

build.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
<property name="documentation-dir" location="build/docs"/>
9898
<property name="test-results-dir" location="build/test-results"/>
9999

100-
<property name="cli-classname" value="de.thetaphi.forbiddenapis.CliMain"/>
100+
<property name="cli-classname" value="de.thetaphi.forbiddenapis.cli.CliMain"/>
101101

102102
<!-- define Maven coordinates -->
103103
<property name="groupId" value="de.thetaphi" />
@@ -333,7 +333,7 @@
333333
<zips><fileset refid="fileset.bundle"/></zips>
334334
</archives>
335335
</restrict>
336-
<keep pattern="de.thetaphi.forbiddenapis.*"/>
336+
<keep pattern="de.thetaphi.forbiddenapis.**"/>
337337
<rule pattern="org.objectweb.asm.**" result="de.thetaphi.forbiddenapis.asm.@1"/>
338338
<rule pattern="org.apache.commons.**" result="de.thetaphi.forbiddenapis.commons.@1"/>
339339
<rule pattern="org.codehaus.plexus.**" result="de.thetaphi.forbiddenapis.plexus.@1"/>
@@ -424,7 +424,7 @@
424424
description="Checks bundled signatures file corresponding to the current JVM. Run after every update!"/>
425425

426426
<target name="-install-forbiddenapi-task" depends="compile" unless="installed.forbiddenapi-task">
427-
<taskdef name="forbiddenapis" classname="de.thetaphi.forbiddenapis.AntTask" classpathref="path.main-run"/>
427+
<taskdef name="forbiddenapis" classname="de.thetaphi.forbiddenapis.ant.AntTask" classpathref="path.main-run"/>
428428
<property name="installed.forbiddenapi-task" value="true"/>
429429
</target>
430430

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

+8-310
Original file line numberDiff line numberDiff line change
@@ -18,325 +18,23 @@
1818
* limitations under the License.
1919
*/
2020

21-
import static de.thetaphi.forbiddenapis.Checker.Option.*;
21+
import java.util.Locale;
2222

23-
import org.apache.tools.ant.AntClassLoader;
2423
import org.apache.tools.ant.BuildException;
2524
import org.apache.tools.ant.Project;
26-
import org.apache.tools.ant.ProjectComponent;
27-
import org.apache.tools.ant.Task;
28-
import org.apache.tools.ant.types.Path;
29-
import org.apache.tools.ant.types.FileList;
30-
import org.apache.tools.ant.types.FileSet;
31-
import org.apache.tools.ant.types.Reference;
32-
import org.apache.tools.ant.types.Resource;
33-
import org.apache.tools.ant.types.ResourceCollection;
34-
import org.apache.tools.ant.types.resources.FileResource;
35-
import org.apache.tools.ant.types.resources.Resources;
36-
import org.apache.tools.ant.types.resources.StringResource;
37-
38-
import java.io.IOException;
39-
import java.io.File;
40-
import java.util.ArrayList;
41-
import java.util.EnumSet;
42-
import java.util.Iterator;
43-
import java.util.List;
44-
import java.util.Locale;
4525

4626
/**
47-
* Task to check if a set of class files contains calls to forbidden APIs
48-
* from a given classpath and list of API signatures (either inline or as pointer to files).
49-
* In contrast to other ANT tasks, this tool does only visit the given classpath
50-
* and the system classloader, not ANT's class loader.
27+
* {@inheritDoc}
28+
* @deprecated Use {@link de.thetaphi.forbiddenapis.ant.AntTask} instead.
5129
*/
52-
public final class AntTask extends Task {
53-
54-
private final Resources classFiles = new Resources();
55-
private final Resources apiSignatures = new Resources();
56-
private final List<BundledSignaturesType> bundledSignatures = new ArrayList<BundledSignaturesType>();
57-
private final List<SuppressAnnotationType> suppressAnnotations = new ArrayList<SuppressAnnotationType>();
58-
private Path classpath = null;
30+
@Deprecated
31+
public final class AntTask extends de.thetaphi.forbiddenapis.ant.AntTask {
5932

60-
private boolean failOnUnsupportedJava = false;
61-
private boolean internalRuntimeForbidden = false;
62-
private boolean restrictClassFilename = true;
63-
private boolean failOnMissingClasses = true;
64-
private boolean failOnUnresolvableSignatures = true;
65-
private boolean failOnViolation = true;
66-
private boolean ignoreEmptyFileset = false;
67-
6833
@Override
6934
public void execute() throws BuildException {
70-
AntClassLoader antLoader = null;
71-
try {
72-
final ClassLoader loader;
73-
if (classpath != null) {
74-
classpath.setProject(getProject());
75-
loader = antLoader = getProject().createClassLoader(ClassLoader.getSystemClassLoader(), classpath);
76-
antLoader.setParentFirst(true); // use default classloader delegation
77-
} else {
78-
loader = ClassLoader.getSystemClassLoader();
79-
}
80-
classFiles.setProject(getProject());
81-
apiSignatures.setProject(getProject());
82-
83-
final EnumSet<Checker.Option> options = EnumSet.noneOf(Checker.Option.class);
84-
if (internalRuntimeForbidden) options.add(INTERNAL_RUNTIME_FORBIDDEN);
85-
if (failOnMissingClasses) options.add(FAIL_ON_MISSING_CLASSES);
86-
if (failOnViolation) options.add(FAIL_ON_VIOLATION);
87-
if (failOnUnresolvableSignatures) options.add(FAIL_ON_UNRESOLVABLE_SIGNATURES);
88-
final Checker checker = new Checker(new Logger() {
89-
public void error(String msg) {
90-
log(msg, Project.MSG_ERR);
91-
}
92-
93-
public void warn(String msg) {
94-
// ANT has no real log levels printed, so prefix with "WARNING":
95-
log("WARNING: " + msg, Project.MSG_WARN);
96-
}
97-
98-
public void info(String msg) {
99-
log(msg, Project.MSG_INFO);
100-
}
101-
}, loader, options);
102-
103-
if (!checker.isSupportedJDK) {
104-
final String msg = String.format(Locale.ENGLISH,
105-
"Your Java runtime (%s %s) is not supported by <%s/>. Please run the checks with a supported JDK!",
106-
System.getProperty("java.runtime.name"), System.getProperty("java.runtime.version"), getTaskName());
107-
if (failOnUnsupportedJava) {
108-
throw new BuildException(msg);
109-
} else {
110-
log("WARNING: " + msg, Project.MSG_WARN);
111-
return;
112-
}
113-
}
114-
115-
for (final SuppressAnnotationType a : suppressAnnotations) {
116-
checker.addSuppressAnnotation(a.getClassname());
117-
}
118-
119-
try {
120-
for (BundledSignaturesType bs : bundledSignatures) {
121-
final String name = bs.getName();
122-
if (name == null) {
123-
throw new BuildException("<bundledSignatures/> must have the mandatory attribute 'name' referring to a bundled signatures file.");
124-
}
125-
log("Reading bundled API signatures: " + name, Project.MSG_INFO);
126-
checker.parseBundledSignatures(name, null);
127-
}
128-
129-
@SuppressWarnings("unchecked")
130-
final Iterator<Resource> iter = apiSignatures.iterator();
131-
while (iter.hasNext()) {
132-
final Resource r = iter.next();
133-
if (r instanceof StringResource) {
134-
final String s = ((StringResource) r).getValue();
135-
if (s != null && s.trim().length() > 0) {
136-
log("Reading inline API signatures...", Project.MSG_INFO);
137-
checker.parseSignaturesString(s);
138-
}
139-
} else {
140-
log("Reading API signatures: " + r, Project.MSG_INFO);
141-
checker.parseSignaturesFile(r.getInputStream());
142-
}
143-
}
144-
} catch (IOException ioe) {
145-
throw new BuildException("IO problem while reading files with API signatures: " + ioe);
146-
} catch (ParseException pe) {
147-
throw new BuildException("Parsing signatures failed: " + pe.getMessage());
148-
}
149-
150-
if (checker.hasNoSignatures()) {
151-
throw new BuildException("No API signatures found; use signaturesFile=, <signaturesFileSet/>, <bundledSignatures/> or inner text to define those!");
152-
}
153-
154-
log("Loading classes to check...", Project.MSG_INFO);
155-
try {
156-
@SuppressWarnings("unchecked")
157-
final Iterator<Resource> iter = classFiles.iterator();
158-
boolean foundClass = false;
159-
while (iter.hasNext()) {
160-
final Resource r = iter.next();
161-
final String name = r.getName();
162-
if (restrictClassFilename && name != null && !name.endsWith(".class")) {
163-
continue;
164-
}
165-
checker.addClassToCheck(r.getInputStream());
166-
foundClass = true;
167-
}
168-
if (!foundClass) {
169-
if (ignoreEmptyFileset) {
170-
log("There is no <fileset/> or other resource collection given, or the collection does not contain any class files to check.", Project.MSG_WARN);
171-
log("Scanned 0 class files.", Project.MSG_INFO);
172-
return;
173-
} else {
174-
throw new BuildException("There is no <fileset/> or other resource collection given, or the collection does not contain any class files to check.");
175-
}
176-
}
177-
} catch (IOException ioe) {
178-
throw new BuildException("Failed to load one of the given class files: " + ioe);
179-
}
180-
181-
log("Scanning for API signatures and dependencies...", Project.MSG_INFO);
182-
try {
183-
checker.run();
184-
} catch (ForbiddenApiException fae) {
185-
throw new BuildException(fae.getMessage());
186-
}
187-
} finally {
188-
if (antLoader != null) antLoader.cleanup();
189-
}
35+
log(String.format(Locale.ENGLISH, "DEPRECATED-WARNING: Please change your build.xml to use new task class '%s'",
36+
getClass().getSuperclass().getName()), Project.MSG_WARN);
37+
super.execute();
19038
}
19139

192-
/** Set of class files to check */
193-
public void add(ResourceCollection rc) {
194-
classFiles.add(rc);
195-
}
196-
197-
/** Sets a directory as base for class files. The implicit pattern '**&#47;*.class' is used to only scan class files. */
198-
public void setDir(File dir) {
199-
final FileSet fs = new FileSet();
200-
fs.setProject(getProject());
201-
fs.setDir(dir);
202-
// needed if somebody sets restrictClassFilename=false:
203-
fs.setIncludes("**/*.class");
204-
classFiles.add(fs);
205-
}
206-
207-
private <T extends ResourceCollection> T addSignaturesResource(T res) {
208-
((ProjectComponent) res).setProject(getProject());
209-
apiSignatures.add(res);
210-
return res;
211-
}
212-
213-
/** Set of files with API signatures as <signaturesFileSet/> nested element */
214-
public FileSet createSignaturesFileSet() {
215-
return addSignaturesResource(new FileSet());
216-
}
217-
218-
/** List of files with API signatures as <signaturesFileList/> nested element */
219-
public FileList createSignaturesFileList() {
220-
return addSignaturesResource(new FileList());
221-
}
222-
223-
/** Single file with API signatures as <signaturesFile/> nested element */
224-
public FileResource createSignaturesFile() {
225-
return addSignaturesResource(new FileResource());
226-
}
227-
228-
/** A file with API signatures signaturesFile= attribute */
229-
public void setSignaturesFile(File file) {
230-
createSignaturesFile().setFile(file);
231-
}
232-
233-
/** Support for API signatures list as nested text */
234-
public void addText(String text) {
235-
addSignaturesResource(new StringResource(text));
236-
}
237-
238-
/** Creates a bundled signatures instance */
239-
public BundledSignaturesType createBundledSignatures() {
240-
final BundledSignaturesType s = new BundledSignaturesType();
241-
s.setProject(getProject());
242-
bundledSignatures.add(s);
243-
return s;
244-
}
245-
246-
/** A bundled signatures name */
247-
public void setBundledSignatures(String name) {
248-
createBundledSignatures().setName(name);
249-
}
250-
251-
/** Creates a instance of an annotation class name that suppresses error reporting in classes/methods/fields. */
252-
public SuppressAnnotationType createSuppressAnnotation() {
253-
final SuppressAnnotationType s = new SuppressAnnotationType();
254-
s.setProject(getProject());
255-
suppressAnnotations.add(s);
256-
return s;
257-
}
258-
259-
/** Class name of annotation that suppresses error reporting in classes/methods/fields. */
260-
public void setSuppressAnnotation(String classname) {
261-
createSuppressAnnotation().setClassname(classname);
262-
}
263-
264-
/** Classpath as classpath= attribute */
265-
public void setClasspath(Path classpath) {
266-
createClasspath().append(classpath);
267-
}
268-
269-
/** Classpath as classpathRef= attribute */
270-
public void setClasspathRef(Reference r) {
271-
createClasspath().setRefid(r);
272-
}
273-
274-
/** Classpath as <classpath/> nested element */
275-
public Path createClasspath() {
276-
if (this.classpath == null) {
277-
this.classpath = new Path(getProject());
278-
}
279-
return this.classpath.createPath();
280-
}
281-
282-
/**
283-
* Fail the build, if the bundled ASM library cannot read the class file format
284-
* of the runtime library or the runtime library cannot be discovered.
285-
* Defaults to {@code false}.
286-
*/
287-
public void setFailOnUnsupportedJava(boolean failOnUnsupportedJava) {
288-
this.failOnUnsupportedJava = failOnUnsupportedJava;
289-
}
290-
291-
/**
292-
* Fail the build, if a referenced class is missing. This requires
293-
* that you pass the whole classpath including all dependencies.
294-
* If you don't have all classes in the filesets, the application classes
295-
* must be reachable through this classpath, too.
296-
* Defaults to {@code true}.
297-
*/
298-
public void setFailOnMissingClasses(boolean failOnMissingClasses) {
299-
this.failOnMissingClasses = failOnMissingClasses;
300-
}
301-
302-
/**
303-
* Fail the build if a signature is not resolving. If this parameter is set to
304-
* to false, then such signatures are silently ignored.
305-
* Defaults to {@code true}.
306-
*/
307-
public void setFailOnUnresolvableSignatures(boolean failOnUnresolvableSignatures) {
308-
this.failOnUnresolvableSignatures = failOnUnresolvableSignatures;
309-
}
310-
311-
/**
312-
* Forbids calls to classes from the internal java runtime (like sun.misc.Unsafe)
313-
* Defaults to {@code false}.
314-
*/
315-
public void setInternalRuntimeForbidden(boolean internalRuntimeForbidden) {
316-
this.internalRuntimeForbidden = internalRuntimeForbidden;
317-
}
318-
319-
/** Automatically restrict resource names included to files with a name ending in '.class'.
320-
* This makes filesets easier, as the includes="**&#47;*.class" is not needed.
321-
* Defaults to {@code true}.
322-
*/
323-
public void setRestrictClassFilename(boolean restrictClassFilename) {
324-
this.restrictClassFilename = restrictClassFilename;
325-
}
326-
327-
/** Ignore empty fileset/resource collection and print a warning instead.
328-
* Defaults to {@code false}.
329-
*/
330-
public void setIgnoreEmptyFileSet(boolean ignoreEmptyFileset) {
331-
this.ignoreEmptyFileset = ignoreEmptyFileset;
332-
}
333-
334-
/**
335-
* Fail the build if violations have been found. If this parameter is set to {@code false},
336-
* then the build will continue even if violations have been found.
337-
* Defaults to {@code true}.
338-
*/
339-
public void setFailOnViolation(boolean failOnViolation) {
340-
this.failOnViolation = failOnViolation;
341-
}
34240
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818

1919
@SuppressWarnings("serial")
20-
public final class WrapperRuntimeException extends RuntimeException {
20+
final class WrapperRuntimeException extends RuntimeException {
2121

2222
public WrapperRuntimeException(Exception e) {
2323
super(e);

0 commit comments

Comments
 (0)