Antlion uses what's called a <library-policy>
to describe how we describe a library, where we find it, and how we reference
it from our Ant script. These policies can get
tricky, so we need to be clear and descriptive
when we set it up.
The way we've structured our project shows us
that each jar file can be found by its name, its version, and the external
group that owns the jar file:
- log4j:
the library lives under
log4j/1.2.8/log4j-1.2.8.jar
. Here,
the group name is log4j
, the version is 1.2.8
,
and the name of the jar is log4j
. In this case, the group
name and the name of the jar are identical.
- xmlParserAPIs:
the library lives under
xerces/2.6.2/xmlParserAPIs.jar
.
The group name is xerces
, the version is 2.6.2
,
and the jar name is xmlParserAPIs
.
- xercesImpl:
the library lives under
xerces/2.6.2/xercesImpl.jar
.
The group name is xerces
, the version is 2.6.2
,
and the jar name is xercesImpl
.
- junit:
the library lives under
junit/3.8.1/junit.jar
.
The group name is junit
, the version is 3.8.1
,
and the jar name is junit
. The group name and the name of
the jar are identical.
From this, we can declare that each library entry must define a
group
, name
, and version
value. Since
we know that, in some circumstances, the group and name values are identical,
we can alias the name to be the same as the group in those cases.
Now, we can begin to define our policy. Policies requires a repository
(here, we'll use a local file-based repository using "lib" as our root dir),
and a set of rules on how to process libraries, called processors.
For our build, we will need to reference the libraries for class paths and
for copying, which, in Ant terms, means <path>
and <fileset>
references.
|
|
|
|
<library-policy id="policy">
<!--
The policy requires that all libraries be defined with
the following components:
group: the group that developed or owns the library.
name: name of the library file. This can be aliased
with the group.
version: the version of the library file to use.
type: the file type of the library. If not specified,
Antlion will default this attribute to "jar".
-->
<!--
the local file-based repository definition. We allow
for group to be an alias for name. Also, library files
may or may not have a version number in the file name.
Note that order matters here.
-->
<repository basedir="${lib.dir}">
<format text="[group]/[version]/[name]-[version].[type]" />
<format text="[group]/[version]/[name].[type]" />
<format text="[group]/[version]/[group]-[version].[type]" />
<format text="[group]/[version]/[group].[type]" />
</repository>
<!--
These processors will possibly alter the definition of
each library entry before they are used by the
processors and/or the repositories.
-->
<!-- pushes the attributes defined in the <library>
down into each entry, if the entry does not already have
that attribute defined. -->
<attribute attributes="group, version" />
<!--
These are the Ant elements we will generate for each
library. We will generate:
path: Antlion will create a reference ID
"path.[library id]" for each library with an
"id" attribute.
fileset: Antlion will create a reference ID
"fileset.[library id]" for each library with an
"id" attribute.
manifest-classpath: Antlion will create a property,
whose value is Class-Path like, and the name is
the value of the "manifest-classpath" attribute.
-->
<path />
<fileset />
<manifest-classpath />
</library-policy>
|
|
|
|
|
The ordering of the format strings inside the
<resource>
element is very important. They dictate the search order
for the file names for each library entry. If the ordering is wrong, or too
vague, then unexpected behavior might result, like picking up the same Jar file
twice.
Since the artifacts.xml
file requires the definition of a policy
before it can work, we must add this <library-policy>
before the
<import>
. If we were to expect this project to span multiple builds,
then we would probably want to put this policy definition into a common,
shared location, so that all the builds could reference the same policy and
library repository.
Now, let's look back at our dependency declaration for the main jar file,
and see what Antlion does:
|
|
|
|
<depends name="build">
<library id="lib.xerces" group="xerces"
version="2.6.2">
<entry name="xmlParserAPIs" />
<entry name="xercesImpl" />
</library>
<entry group="log4j" version="1.2.8" />
</depends>
|
|
|
|
|
The first library definition, "lib.xerces", joins all the Xerces libraries
under one umbrella. This is a short-hand to specify the group and
version in the library definition, so that the <entry>
tags will inherit these values. Both of these entries use the second
format string from the resource declaration.
The entry by itself with the group "log4j" references the
log4j-1.2.8.jar
file by using the third formatted text
reference in the repository definition.
Since the <artifact>
references our policy, Antlion
will act upon <depends>
:
-
A
<path>
object will be created, which contains the
three jar files described in the depends group. The ID of this
path will be path.simpleproject.jar.build
,
constructed using the ID of the artifact and the name of the
depends.
-
A
<fileset>
object will be created, which uses the
${lib.dir}
as the basedir (discovered as the lowest
common path), and includes relatives paths to the three entries.
The ID of this fileset will be
fileset.simpleproject.jar.build
,
constructed using the ID of the artifact and the name of the
depends.