The Craftsman <library> Tag
Craftsman <library> tags perform a lot of heavy lifting for the developer. Using a properly configured <library> tag and properly configured library definition file, your library can be downloaded automatically, unpacked, included in the build path, and referenced in the resulting binaries.How <library> works
The simple <library> tag performs several tasks automatically, without intervention. It's these tasks that make it so valuable to the developer and make using Craftsman so much easier.Automatic discovery
The <library> tag works by searching for the libs automatically or in a more targeted fashion if the externaldir attribute is set. Depending on where it is declared, <library> looks for a directory with the same name under a lib directory. If the <library> tag is declared within a <module> definition, <library> looks under the module directory for a lib/libraryname directory. If it is declared outside any modules, it looks for lib/libraryname in the current directory.If <library> cannot find a directory named the same as its name attribute, it will stop the build with an error saying it is unable to find the library.
Once the library directory is found, <library> looks for a library definition file. These files are usually named library-libraryname.xml, but <library> isn't too picky. It starts looking for library.xml, then looks for library-*.xml. If no definition file is found, <library> will then use any .jar file found in the directory. If no jar files are found, it will stop the build with an error, saying it cannot find any of the resources for the library.
Library configuration processing
If <library> finds a library definition file, it opens it up an parses it. Library definition files define "sources" for the library jars, etc that make up the library. The sources tell <library> how to go about finding the library jars: whether it is in the local filesystem, at remote source, or whether it should search the Craftsman libcache.The <library> tag will use these sources and try them in order to retrieve the library. You can tell it to try the local filesystem and then a remote location if the local filesystem fails. You can have any number of sources in any order you want. You can also tell it to use checks to verify the libraries (like MD5). The <library> tag will then retrieve the resources and put them in the library directory where it found the library definition.
Automatic <fileset> and <path> creation
Once the all the library resources are found, <library> creates a <fileset> and <path> for the library resources. This allows the build to reuse the library resources in builds, packaging, execution, etc.Defining a library definition file
Well, first off, you shouldn't have to define a library definition file if the project or library you are using uses Craftsman. The Craftsman bundle feature creates one automatically. So you should be able to download a library definition file from your library provider and just be able to drop it into place.But if your library provider doesn't provide you with a library definition file (or if it doesn't suit your needs), you can create your own. Below is an example definition file:
Simple Example
<library>
<filesystem>
<directory name="${env.JAVA_3RD_PARTY_LIB}/j2ee">
<file name="j2ee.jar"/>
</directory>
</filesystem>
<libcache>
<location url="http://craftsman.redstarhackers.com/libcache" checksum="MD5">
<file name="j2ee.jar"/>
</location>
</libcache>
</library>
This simple definition will tell Craftsman to look in the directory $JAVA_3RD_PARTY_LIB/j2ee for the j2ee.jar, where $JAVA_3RD_PARTY_LIB is an environment setting. If the jar is not found, Craftsman will try the next source strategy, the libcache.
The libcache is basically a caching system: when you get a file throught the libcache, it checks to see if it already has the file. If it does, it runs a checksum (if you requested it), and then uses the local version. If it doesn't have a local version, it gets it via the source specified (in this case, a remote location of "http://craftsman.redstarhackers.com/libcache") and then that new copy becomes the local copy for any other request.
Using Archives
Sometimes using individual jars can be a pain or not efficient. For instance, if the library includes 30 jars, doing a download for each is a bit expensive in terms of overhead. The Craftsman <library> supports extracting your library resources from archives (zip, tar, etc). All you need to do is wrap the <file> tags in an <archive> tag:<library>
<libcache>
<location url="http://craftsman.redstarhackers.com/libcache">
<archive name="rsh-commons-1.0.0.zip">
<file name="rsh-utils.jar"/>
<file name="rsh-logging.jar"/>
<file name="commons-logging.jar"/>
<file name="rsh-ant.jar"/>
<file name="rsh-config.jar"/>
<file name="rsh-commons.jar"/>
</archive>
</location>
</libcache>
</library>
This definition tells libcache to look for the resource rsh-commons.zip. If it does not have it locally, it gets it from the remote location. Once it has the local version, it unpacks the designated files from the archive and into the library directory.
This feature allows you to take distributions from other projects that may not have anything to do with Craftsman and use them as is. You would need to only point at a release on the project's website and then list the file names as they appear in the archive. Craftsman will unpack them and flatten them into the library directory.
Using Variables
You've already seen the environment variable setting. Craftsman also supports hard-coding a variable into the definition itself:<library>
<properties>
<property name="rsh-commons.release" value="1.0.0"/>
</properties>
<libcache>
<location url="http://craftsman.redstarhackers.com/libcache">
<archive name="rsh-commons-${rsh-commons.release}.zip">
<file name="rsh-utils.jar"/>
<file name="rsh-logging.jar"/>
<file name="commons-logging.jar"/>
<file name="rsh-ant.jar"/>
<file name="rsh-config.jar"/>
<file name="rsh-commons.jar"/>
</archive>
</location>
</libcache>
</library>
Craftsman <library> will look for the file "rsh-commons-1.0.0.zip" when it performs the resource retrieval and check.
