The Apache Ant frontend: ProjectHelper
What is a ProjectHelper?
The
ProjectHelper
in Apache Ant is responsible for parsing the build file and creating java instances representing the build workflow. It also signals which kind of file it can parse, and which file name it expects as default input file.Ant' default
ProjectHelper
(org.apache.tools.ant.helper.ProjectHelper2
) parses the usual build.xml files. And if no build file is specified on the command line, it will expect to find a file namedbuild.xml
.The immediate benefit of a such abstraction it that it is possible to make Ant understand other kind of descriptive languages than XML. Some experiments have been done around a pure java frontend, and a groovy one too (ask the dev mailing list for further info about these).
Since Ant 1.8.2, the import task will also try to use the proper helper to parse the imported file. So it is possible to write different build files in different languages and have them import each other.
How is Ant is selecting the proper ProjectHelper
Ant knows about several implementations of
ProjectHelper
and has to decide which to use for each build file.At startup Ant lists the all implementations found and keeps them in the same order they've been found in an internal 'repository':
In case of an error while trying to instantiate a
- the first to be searched for is the one declared by the system property
org.apache.tools.ant.ProjectHelper
(see Java System Properties);- then it searches with its class loader for a
ProjectHelper
service declarations in the META-INF: it searches in the classpath for a fileMETA-INF/services/org.apache.tools.ant.ProjectHelper
. This file will just contain the fully qualified name of the implementation ofProjectHelper
to instantiate;- it will also search with the system class loader for
ProjectHelper
service declarations in the META-INF;- last but not least it will add its default
ProjectHelper
that can parse classical build.xml files.ProjectHelper
, Ant will log an error but won't stop. If you want further debugging info about theProjectHelper
internal 'repository', use the system propertyant.project-helper-repo.debug
and set it totrue
; the full stack trace will then also be printed.When Ant is expected to parse a file, it will ask the
ProjectHelper
repository to find an implementation that will be able to parse the input file. Actually it will just iterate over the ordered list and the first implementation that returnstrue
tosupportsBuildFile(File buildFile)
will be selected.When Ant is started and no input file has been specified, it will search for a default input file. It will iterate over list of
ProjectHelper
s and will select the first one that expects a default file that actually exist.Writing your own ProjectHelper
The class
org.apache.tools.ant.ProjectHelper
is the API expected to be implemented. So write your ownProjectHelper
by extending that abstract class. You are then expected to implement at least the functionparse(Project project, Object source)
. Note also that your implementation will be instantiated by Ant, and it is expecting a default constructor with no arguments.There are some functions that will help you define what your helper is capable of and what is is expecting:
getDefaultBuildFile()
: defines which file name is expected if none providedsupportsBuildFile(File buildFile)
: defines if your parser can parse the input filecanParseAntlibDescriptor(URL url)
: whether your implementation is capable of parsing a given Antlib descriptor. The base class returnsfalse
parseAntlibDescriptor(Project containingProject, URL source)
: invoked to actually parse the Antlib descriptor if your implementation returnedtrue
for the previous method.Now that you have your implementation ready, you have to declare it to Ant. Three solutions here:
- use the system property
org.apache.tools.ant.ProjectHelper
(see also the Java System Properties);- use the service file in META-INF: in the jar you will build with your implementation, add a file
META-INF/services/org.apache.tools.ant.ProjectHelper
. And then in this file just put the fully qualified name of your implementation- use the projecthelper task (since Ant 1.8.2) which will install dynamically an helper in the internal helper 'repository'. Then your helper can be used on the next call to the import task.