<dependency>
<groupId>axis</groupId>
<artifactId>axis</artifactId>
<version>1.1</version>
<type>jar</type>
<url>http://ws.apache.org/axis/index.html</url>
</dependency>
Maven goes looking for the following file in the remote repositories :
${repo}/axis/jars/axis-1.1.jar
If you have more than one repository in the list, then the way that Maven resolves which repository to use may not be what you expect.
# # The remote repositories Maven uses to download artifacts (jars etc) that it can't find in the local repository. maven.repo.remote=http://capc49.ast.cam.ac.uk/maven, http://astrogrid.ast.cam.ac.uk/maven, http://www.ibiblio.org/mavenYou might expect it to check the remote repositories in sequence, and use the first jar file it finds. In fact, it does check the repositories in sequence, and it does download the first one it finds. However, it then continues with the other repositories in the sequence, checking the last modified date of the files. If it finds another file with a more recent date, it will download that one as well. Result is that altering the sequence of remote repositories in your project.properties does not change the results you get.
# # This list checks the cambridge repositories first. maven.repo.remote=http://capc49.ast.cam.ac.uk/maven, http://astrogrid.ast.cam.ac.uk/maven, http://www.ibiblio.org/maven # # This list checks the ibiblio repositories first, but produces the same results. maven.repo.remote=http://www.ibiblio.org/maven, http://astrogrid.ast.cam.ac.uk/maven, http://capc49.ast.cam.ac.uk/mavenThe only way to prioritise one repository over another is to tweak the last modified dates of the files in the repository. It also means that if one of the remote repositories change the file dates when they create their repository, then their copy will override the other repositories.
<!--+
| Iterate our list of artifacts.
+-->
<core:forEach var="lib" items="${pom.artifacts}">
<ant:echo message=""/>
<ant:echo message="Name : ${lib.dependency.artifactId}"/>
<ant:echo message="Group : ${lib.dependency.groupId}"/>
<ant:echo message="Type : ${lib.dependency.type}"/>
<ant:echo message="Base : ${lib.file.parent}"/>
<ant:echo message="File : ${lib.file.name}"/>
<ant:echo message="Path : ${lib.path}"/>
</core:forEach>
If you want to do something with a specific set of jars, you can nest an if statement inside the loop.
This example copies the jars from the castor group into a separate diretory.
<!--+
| Create our target directory.
+-->
<ant:mkdir dir="castor-jars"/>
<!--+
| Iterate our list of artifacts.
+-->
<core:forEach var="lib" items="${pom.artifacts}">
<!--+
| Check if it is a member of the castor group.
+-->
<core:if test="${lib.dependency.groupId=='castor'}">
<ant:echo message=""/>
<ant:echo message="Found a Castor jar"/>
<ant:echo message="Name : ${lib.dependency.artifactId}"/>
<ant:echo message="Group : ${lib.dependency.groupId}"/>
<ant:echo message="Type : ${lib.dependency.type}"/>
<ant:echo message="Base : ${lib.file.parent}"/>
<ant:echo message="File : ${lib.file.name}"/>
<ant:echo message="Path : ${lib.path}"/>
<!--+
| Copy the jar to our target directory.
+-->
<ant:copy todir="castor-jars" file="${lib.path}"/>
</core:if>
</core:forEach>
Same thing simplified without the debug messages.
<!--+ Create our target directory +-->
<ant:mkdir dir="castor-jars"/>
<!--+ Iterate our list of artifacts +-->
<core:forEach var="lib" items="${pom.artifacts}">
<!--+ Check if it is a member of the castor group +-->
<core:if test="${lib.dependency.groupId=='castor'}">
<!--+ Copy the jar to our target directory +-->
<ant:copy todir="castor-jars" file="${lib.path}"/>
</core:if>
</core:forEach>
<!--+
| The Castor jars
+-->
<dependency>
<groupId>castor</groupId>
<artifactId>castor</artifactId>
<version>0.9.5</version>
<type>jar</type>
<url>http://www.castor.org/</url>
<properties>
<my-property>my-value</my-property>
</properties>
</dependency>
<dependency>
<groupId>castor</groupId>
<artifactId>castor-xml</artifactId>
<version>0.9.5</version>
<jar>castor-0.9.5-xml.jar</jar>
<type>jar</type>
<url>http://www.castor.org/</url>
<properties>
<my-property>my-value</my-property>
</properties>
</dependency>
<!--+
| The libraries that Castor relies on.
+-->
<dependency>
<groupId>jta</groupId>
<artifactId>jta</artifactId>
<version>1.0.1</version>
<type>jar</type>
<properties>
<my-property>my-value</my-property>
</properties>
</dependency>
We can then test the value of this property in our Jelly code.
This example only copies jars with a property called 'my-property' set to 'my-value'.
<ant:mkdir dir="webapp-jars"/>
<!--+
| Iterate our list of artifacts.
+-->
<core:forEach var="lib" items="${pom.artifacts}">
<!--+
| Check if we want to include this jar.
+-->
<core:if test="${lib.dependency.getProperty('my-property')=='my-value'}">
<!--+
| Copy the jar to our target directory.
+-->
<ant:copy todir="webapp-jars" file="${lib.path}"/>
</core:if>
</core:forEach>
Source :
plugin.jelly for the maven-war-plugin, checks a property called 'war.bundle' to see if an artifact should be included in the war file.
<!--+
| Set the name of the directory we want to scan.
+-->
<core:set var="mydir" value="/var/projects/maven/maven-1.0-rc1/plugins"/>
<!--+
| Use an Ant fileScanner to create a list of matching files.
+-->
<ant:fileScanner var="myfiles">
<ant:fileset dir="${mydir}" includes="*.jar"/>
</ant:fileScanner>
<!--+
| Iterate our list of matching files.
+-->
<core:forEach var="myfile" items="${myfiles.iterator()}">
<ant:echo message=""/>
<ant:echo message="Base : ${myfile.parent}"/>
<ant:echo message="File : ${myfile.name}"/>
<ant:echo message="Path : ${myfile.path}"/>
</core:forEach>
Note that you have to use myfiles.iterator() on your AntFileScanner to get an Iterator for the list of files.
Each item in the list resolves to a java.io.File object, which you can then treat as a Bean in Jelly.
Source
http://jira.codehaus.org/secure/ViewIssue.jspa?key=MAVEN-528
<!--+
| Task to unpack all the plugin jars.
+-->
<target name="plugin-list">
<!--+
| Set the name of the directory we want to unpack the jars to.
+-->
<core:set var="unpackdir" value="/var/projects/mumble/plugins"/>
<!--+
| Set the name of the directory we want to copy the jelly files to.
+-->
<core:set var="jellydir" value="/var/projects/mumble/jelly"/>
<!--+
| Create our directories.
+-->
<ant:mkdir dir="${unpackdir}"/>
<ant:mkdir dir="${jellydir}"/>
<!--+
| Use an Ant fileScanner to create a list of plugins jars.
+-->
<ant:fileScanner var="pluginjars">
<ant:fileset dir="${maven.home}/plugins" includes="*.jar"/>
</ant:fileScanner>
<!--+
| Iterate our list of files.
+-->
<core:forEach var="pluginjar" items="${pluginjars.iterator()}">
<ant:echo message=""/>
<ant:echo message="Base : ${pluginjar.parent}"/>
<ant:echo message="File : ${pluginjar.name}"/>
<ant:echo message="Path : ${pluginjar.path}"/>
<!--+
| Get the plugin name from the jar name.
| Plugin jars all follow the same format maven-{name}-plugin-{version}.jar
+-->
<core:set var="pluginname" value="${pluginjar.name.substring(6, pluginjar.name.lastIndexOf('-plugin'))}"/>
<ant:echo message="Name : ${pluginname}"/>
<!--+
| Create a directory for the jar contents.
+-->
<ant:mkdir dir="${unpackdir}/${pluginname}"/>
<!--+
| Unpack the jar file into our target directory.
+-->
<ant:unzip src="${pluginjar.path}" dest="${unpackdir}/${pluginname}"/>
<!--+
| Copy the plugin.jelly file to our jelly directory.
+-->
<ant:copy vebose="true" file="${unpackdir}/${pluginname}/plugin.jelly" tofile="${jellydir}/${pluginname}.jelly"/>
</core:forEach>
</target>
Note the embedded Java code inside the ${} sections.
<core:set var="pluginname" value="${pluginjar.name.substring(6, pluginjar.name.lastIndexOf('-plugin'))}"/>
java.io.File pluginjar ;
java.lang.Object pluginname = pluginjar.getName().substring(6, pluginjar.getName().lastIndexOf("-plugin"))
Or, not .... Actually Jelly does not know that 'pluginjar' is a java.io.File, so it treats it as an java.lang.Object and has to use the reflection mechanism to call the getName() method.
Well ... I hope that is clear
<goal name="java:compile" ....>
....
<ant:javac
....
<ant:classpath>
<ant:path refid="maven.dependency.classpath"/>
<ant:pathelement path="${maven.build.dest}"/>
</ant:classpath>
....
</ant:javac>
....
</goal>
This means that the ant:javac task uses a classpath with two elements.
<!--+
| Try to echo the Dependency Classpath
+-->
<ant:echo message="Classpath : ${maven.dependency.classpath}"/>
This does not work, because the ant:echo tag only works on properties, not on references.
However, we can convert the reference into an Ant property, and then print that out.
<!--+
| Convert the Dependency Classpath reference into an Ant property.
+-->
<ant:property name="frog" refid="maven.dependency.classpath"/>
<!--+
| Echo the property.
+-->
<ant:echo message="Classpath : ${frog}"/>
This works, but gives us the whole classpath as a single string.
[echo] Classpath : /var/projects/maven/local/repository/ant/jars/ant-1.5.4.jar:/var/projects/maven/local/repository/ant/jars/ant-optional-1.5.4.jar:/var/projects/maven/local/repository/castor/jars/castor-0.9.5.jar:/var/projects/maven/local/repository/castor/jars/castor-0.9.5-xml.jar:/var/projects/maven/local/repository/jta/jars/jta-1.0.1.jar:/var/projects/maven/local/repository/xerces/jars/xerces-2.4.0.jar:/var/projects/maven/local/repository/xml-apis/jars/xml-apis-1.0.b2.jar:/var/projects/maven/local/repository/jconfig/jars/jconfig-2.2.jar:/var/projects/maven/local/repository/hsqldb/jars/hsqldb-1.7.1.jar:/var/projects/maven/local/repository/junit/jars/junit-3.8.1.jar
It does indeed contain the list of jar files, but the format is a little difficult to use.
Ideally, we want this as a list that we can manipulate ourselves.
Everything in Maven appears to hang off of the top level ProjectObjectModel , or POM.
Looking the plugin.jelly examples from the various Maven plugins, a lot of them use properties or methods on the 'pom' to access the project data.
So, first step is to find out what the POM actually is.
<!--+
| Display the class for the 'pom'.
+-->
<ant:echo message="POM : ${pom.getClass()}"/>
[echo] POM : class org.apache.maven.project.Project
This tells us that, surprise surprise the 'pom' is a org.apache.maven.project.Project.
The JavaDoc for the Maven components is available here :
http://maven.apache.org/apidocs/index.html
and the JavaDoc for a Maven Project is here :
http://maven.apache.org/apidocs/org/apache/maven/project/Project.html
Looking at the JavaDoc there are a whole load of interesting things to play with.
However, the two main ones of interest at this point are getDependencies() and getAntProject().
At first glance, getDependencies() looks like it will do what we want.
public org.apache.commons.grant.GrantProject getAntProject()
And, in fact this does give us a list of all of the project dependencies.
We can see what is in the list using echo to display the properties and class for each item in the list.
<!--+
| Display the class and properties for the project dependencies.
+-->
<core:forEach var="item" items="${pom.getDependencies()}">
<ant:echo message="Class : ${item.getClass()}"/>
<ant:echo message="Item : ${item}"/>
</core:forEach>
[echo] Class : class org.apache.maven.project.Dependency
[echo] Item : Dep[ id:ant:ant pid:ant:ant ver:1.5.4 ar:ant-1.5.4.jar jar:null ]
[echo] Class : class org.apache.maven.project.Dependency
[echo] Item : Dep[ id:ant:ant-optional pid:ant:ant-optional ver:1.5.4 ar:ant-optional-1.5.4.jar jar:null ]
[echo] Class : class org.apache.maven.project.Dependency
[echo] Item : Dep[ id:castor:castor pid:castor:castor ver:0.9.5 ar:castor-0.9.5.jar jar:null ]
[echo] Class : class org.apache.maven.project.Dependency
[echo] Item : Dep[ id:castor:castor-xml pid:castor:castor-xml ver:0.9.5 ar:castor-0.9.5-xml.jar jar:castor-0.9.5-xml.jar ]
....
However, this is a list of the dependencies declared in the project.xml, not the actual list of jars in the java:compile classpath.
These may not be the same thing, as will become clear later on ...
What I'm interesetd in finding is the contents of the classpath used by the java:compile goal, 'maven.dependency.classpath'.
So, back to the JavaDoc for org.apache.maven.project.Project.
The other interesting method is getAntProject(), which returns an org.apache.commons.grant.GrantProject object.
public org.apache.commons.grant.GrantProject getAntProject()
This looks useful, because the way that java:compile goal referes to the 'maven.dependency.classpath' implies that it is a reference to Ant path object.
<goal name="java:compile" ....>
....
<ant:javac
....
<ant:classpath>
<ant:path refid="maven.dependency.classpath"/>
<ant:pathelement path="${maven.build.dest}"/>
</ant:classpath>
....
</ant:javac>
....
</goal>
Note that getAntProject() does not return an Ant Project, it returns an org.apache.commons.grant.GrantProject.
We can check this by using echo to display the class name of the object we get back from getAntProject().
<ant:echo message="AntProject : ${pom.getAntProject().getClass()}"/>
[echo] AntProject : class org.apache.commons.grant.GrantProject
I couldn't find out which of the commons projects this belongs to, but putting the class name into Google, I found the JavaDoc .
http://jakarta.apache.org/commons/sandbox/grant/apidocs/org/apache/commons/grant/GrantProject.html
The JavaDoc describes a GrantProject as :
A subclass of an ant Project which allows installation of delegators for particular functions.So, we do have an Ant Project, with extensions. The way that java:compile goal uses 'maven.dependency.classpath' implies that it is a reference to Ant path object. The JavaDoc for the Ant components isn't available on-line, but it does come packaged with the binary distributiion. Looking at the JavaDoc for org.apache.tools.ant.Project, there isn't an obvious way to get at the paths. However, there is a method called getReference()
public java.lang.Object getReference(java.lang.String key)
We can try seeing what we get if we ask for an object with the reference ID 'maven.dependency.classpath'.
<ant:echo message="Reference : ${pom.getAntProject().getReference('maven.dependency.classpath').getClass()}"/>
[echo] Reference : class org.apache.tools.ant.types.Path
Getting closer ... we have now resolved the reference ID 'maven.dependency.classpath' into an Ant Path object.
Looking up the JavaDoc for org.apache.tools.ant.types.Path there is a list() method that returns the path elements.
public java.lang.String[] list()
So, what happens if we pass this array into a Jelly ForNext loop ?
<core:forEach var="path" items="${pom.getAntProject().getReference('maven.dependency.classpath').list()}">
<ant:echo message="Path : ${path}"/>
</core:forEach>
[echo] Path : /var/projects/maven/local/repository/ant/jars/ant-1.5.4.jar
[echo] Path : /var/projects/maven/local/repository/ant/jars/ant-optional-1.5.4.jar
[echo] Path : /var/projects/maven/local/repository/castor/jars/castor-0.9.5.jar
[echo] Path : /var/projects/maven/local/repository/castor/jars/castor-0.9.5-xml.jar
[echo] Path : /var/projects/maven/local/repository/jta/jars/jta-1.0.1.jar
[echo] Path : /var/projects/maven/local/repository/xerces/jars/xerces-2.4.0.jar
[echo] Path : /var/projects/maven/local/repository/xml-apis/jars/xml-apis-1.0.b2.jar
[echo] Path : /var/projects/maven/local/repository/jconfig/jars/jconfig-2.2.jar
[echo] Path : /var/projects/maven/local/repository/hsqldb/jars/hsqldb-1.7.1.jar
[echo] Path : /var/projects/maven/local/repository/junit/jars/junit-3.8.1.jar
We now have a list of the paths in the 'maven.dependency.classpath', as used by the java:compile goal.
And, at the moment, it contains each of the jars listed in the project.xml dependencies.
So, why go through all this just to print out a list of the project dependencies (again) ?
Well, it turns out that the actual contents of the 'maven.dependency.classpath' may not be quite the same as the original project dependencies.
When poking around inside the plugin.jelly files for some of the plugins, I came accross the following code in the Clover plugin.
<ant:path id="clover.classpath">
<ant:pathelement path="${plugin.getDependencyPath('clover')}"/>
</ant:path>
<goal name="clover:on" ....>
....
<maven:addPath id="maven.dependency.classpath" refid="clover.classpath"/>
....
</goal>
The first section sets up an Ant Path, using getDependencyPath() to get the location of the Clover jar file.
The second section looks like it uses maven:addPath to add 'clover.classpath' to the 'maven.dependency.classpath'.
The JavaDoc for the maven:addPath tag is available here :
http://maven.apache.org/apidocs/org/apache/maven/jelly/tags/maven/AddPathTag.html
This describes the AddPathTag as :
This class takes a given path using an id and appends another path (using refid) to it.So, it turns out that any of the plugins can add things to your classpath, even if they are not listed in your project.xml dependencies.
# Maven home directory.
# Defaults to a hidden directory ${user.home}/.maven
maven.home.local=/var/projects/maven/local/home
Maven unpacks its plugin jars into a sub-directory under maven.home.local called plugins.
{maven.home.local}
|
\- plugins
|
+- maven-antlr-plugin-1.1
|
+- maven-ant-plugin-1.4
|
+- maven-appserver-plugin-2.0-dev
|
+ ....
To create a new plugin, just create a new directory.
{maven.home.local}
|
\- plugins
|
+- ....
|
\- maven-astrogrid-plugin-1.4.1
Inside that, you need to create three files, project.xml, plugin.jelly and plugin.properties.
{maven.home.local}
|
\- plugins
|
+- ....
|
\- maven-astrogrid-plugin-1.4.1
|
+- project.xml
|
+- plugin.jelly
|
\- plugin.properties
The project.xml is a cut-down version of the normal project.xml you would create for a top level project.
<?xml version="1.0"?>
<!--+
| Maven plugin for the AstroGrid project.
| ....
+-->
<project>
<extend>../project.xml</extend>
<pomVersion>3</pomVersion>
<id>maven-astrogrid-plugin</id>
<name>Maven Plug-in for AstroGrid</name>
<currentVersion>1.4.1</currentVersion>
<description>A Maven plugin to implement some commonly used tasks for the AstroGrid project</description>
<shortDescription>AstroGrid project tasks</shortDescription>
<url>http://www.astrogrid.org/</url>
<dependencies>
<!--+
| The Axis webapp war file.
+-->
<dependency>
<groupId>axis</groupId>
<artifactId>axis</artifactId>
<version>1.1</version>
<type>war</type>
<url>http://ws.apache.org/axis/index.html</url>
</dependency>
<!--+
| The 3rd party jars that Axis depends on.
+-->
<dependency>
<groupId>jaf</groupId>
<artifactId>jaf</artifactId>
<version>1.0.2</version>
<type>jar</type>
</dependency>
</dependencies>
</project>
The plugin.jelly is where you add your plugin goals.
I'm not sure about the xml namespaces as yet, some plugins declare them, some don't.
<?xml version="1.0" encoding="UTF-8"?>
<!--+
| Maven plugin for the AstroGrid project.
| ....
+-->
<project
xmlns:core="jelly:core"
xmlns:maven="jelly:maven"
xmlns:ant="jelly:ant"
xmlns:util="jelly:util"
xmlns:log="jelly:log"
xmlns:define="jelly:define"
xmlns:deploy="deploy"
xmlns:astro="astro"
>
<!--+
| Goal to check our plugin is active.
+-->
<goal name="astro:init">
<ant:echo message=""/>
<ant:echo message="Plugin : ${plugin}"/>
<ant:echo message="Version : ${plugin.currentVersion}"/>
</goal>
That is it.
With this in place, you should be able to call your plugin goal from your main project maven.xml.
<target name="my.test">
<attainGoal name="astro:init"/>
</target>
my.test:
astro:init:
[echo]
[echo] Plugin : Maven Plug-in for AstroGrid
[echo] Version : 1.4.1
BUILD SUCCESSFUL
Source : http://www.devx.com/java/Article/17204/0/page/4
And now for the caveat ...
Maven appears to cache some of the information about the goals available in the current set of plugins.
This information is stored in the following files, inside the plugins directory.
{maven.home.local}
|
\- plugins
|
+ ....
|
+- callbacks.cache
|
+- dynatag.cache
|
+- goals.cache
|
+- plugin-dynatag-deps.cache
|
\- plugins.cache
If you are working on your plugin code, and you change the name of one of your goals, e.g rename 'astro:init' to 'astro:start'.
Then you will need to delete these cache files before you run Maven again.
If you don't delete these cache files, then you will spend many happy hours trying to figure out why Maven is ignoring your new goal.
<?xml version="1.0"?>
<!--+
| Maven plugin for the AstroGrid project.
| ....
+-->
<project>
....
<dependencies>
<!--+
| The Axis webapp war file.
+-->
<dependency>
<groupId>axis</groupId>
<artifactId>axis</artifactId>
<version>1.1</version>
<type>war</type>
<url>http://ws.apache.org/axis/index.html</url>
</dependency>
<!--+
| The 3rd party jars that Axis depends on.
+-->
<dependency>
<groupId>jaf</groupId>
<artifactId>jaf</artifactId>
<version>1.0.2</version>
<type>jar</type>
</dependency>
</dependencies>
</project>
We can get at most of the details for these using getDependency() and getDependencyPath().
<goal name="astro:test">
<ant:echo message=""/>
<ant:echo message="Jaf library ...."/>
<ant:echo message="Object : ${plugin.getDependency('jaf')}"/>
<ant:echo message="Class : ${plugin.getDependency('jaf').getClass()}"/>
<ant:echo message="Version : ${plugin.getDependency('jaf').getVersion()}"/>
<ant:echo message="Artifact : ${plugin.getDependency('jaf').getArtifact()}"/>
<ant:echo message="Type : ${plugin.getDependency('jaf').getType()}"/>
<ant:echo message="Path : ${plugin.getDependencyPath('jaf')}"/>
<ant:echo message=""/>
<ant:echo message="Axis webapp ...."/>
<ant:echo message="Object : ${plugin.getDependency('axis')}"/>
<ant:echo message="Class : ${plugin.getDependency('axis').getClass()}"/>
<ant:echo message="Version : ${plugin.getDependency('axis').getVersion()}"/>
<ant:echo message="Artifact : ${plugin.getDependency('axis').getArtifact()}"/>
<ant:echo message="Type : ${plugin.getDependency('axis').getType()}"/>
<ant:echo message="Path : ${plugin.getDependencyPath('axis')}"/>
</goal>
[echo]
[echo] Jaf library ....
[echo] Object : Dep[ id:jaf:jaf pid:jaf:jaf ver:1.0.2 ar:jaf-1.0.2.jar jar:null ]
[echo] Class : class org.apache.maven.project.Dependency
[echo] Version : 1.0.2
[echo] Artifact : jaf-1.0.2.jar
[echo] Type : jar
[echo] Path : /var/projects/maven/local/repository/jaf/jars/jaf-1.0.2.jar
[echo]
[echo] Axis webapp ....
[echo] Object : Dep[ id:axis:axis pid:axis:axis ver:1.1 ar:axis-1.1.war jar:null ]
[echo] Class : class org.apache.maven.project.Dependency
[echo] Version : 1.1
[echo] Artifact : axis-1.1.war
[echo] Type : war
[echo] Path :
All apart from the last one .... it does not find the path for the Axis webapp war file.
So, starting at the top, what is ${plugin}.
<ant:echo message=""/>
<ant:echo message="Plugin ...."/>
<ant:echo message="Class : ${plugin.getClass()}"/>
Turns out that this is a Project not a Plugin.
[echo]
[echo] Plugin ....
[echo] Class : class org.apache.maven.project.Project
The JavaDoc for org.apache.maven.project.Project is available here :
http://maven.apache.org/apidocs/org/apache/maven/project/Project.html
There is a small clue in the JavaDoc description for getDependencyPath().
Get an individual dependencies classpath entry.
But we are looking for a war file, which does not get put into the classpath.
The source for getDependencyPath() is available here :
http://maven.apache.org/xref/org/apache/maven/project/Project.html#701
public String getDependencyPath( String depId )
{
return (String) dependencyPaths.get( legacyToStandardId( depId ) );
}
And dependencyPaths is setup about here :
http://maven.apache.org/xref/org/apache/maven/project/Project.html#1429
public void buildDependencyClasspath()
throws Exception
{
setDependencyClasspath( DependencyClasspathBuilder.build( this ) );
Path p = new Path( getContext().getAntProject() );
p.setPath( getDependencyClasspath() );
getContext().getAntProject().addReference( MavenConstants.DEPENDENCY_CLASSPATH, p );
}
The source for DependencyClasspathBuilder is available here :
http://maven.apache.org/xref/org/apache/maven/DependencyClasspathBuilder.html
And the build method is about here :
http://maven.apache.org/xref/org/apache/maven/DependencyClasspathBuilder.html#85
public static String build( Project project )
throws Exception
{
StringBuffer classpath = new StringBuffer();
for ( Iterator i = project.getArtifacts().iterator(); i.hasNext(); )
{
Artifact artifact = (Artifact) i.next();
Dependency d = artifact.getDependency();
// Only add jar or ejb (MAVEN-512) dependencies to the classpath
if ( d.isAddedToClasspath() )
{
classpath.append( artifact.getPath() ).append( cps );
project.setDependencyPath( d.getId(), artifact.getPath() );
}
}
return classpath.toString();
}
It checks if the Dependency.isAddedToClasspath() before it adds the artifact to the classpath.
The source for Dependency is available here :
http://maven.apache.org/xref/org/apache/maven/project/Dependency.html
And the isAddedToClasspath() method is about here :
http://maven.apache.org/xref/org/apache/maven/project/Dependency.html#357
public boolean isAddedToClasspath()
{
if (type != null)
{
String artifactType = type.getType();
return artifactType.equals("jar") || artifactType.equalsIgnoreCase("ejb");
}
return false;
}
This means that only 'jar' and 'ear' files get processed by the DependencyClasspathBuilder .
Which means that although we can use ${plugin.getDependency('axis')} to get the Dependency object for the Axis war file,
we can't use getDependencyPath() to get at the path because the it has not been added to the list.
If we had the Artifact object, we could use artifact.getPath().
However, although the project has a getDependency('ident') method, there isn't the equivalent getArtifact('ident') method.
If we did have an Artifact, then we could get the corresponding Dependency using artifact.getDependency().
However, there isn't the equivalent dependency.getArtifact() method to get from a Dependency to the corresponding Artifact.
Actually, there is a method called getArtifact(), but it returns a String rather than an Artifact object.
The only way I could figure out of doing this was to iterate through the list of Artifacts and grab the one we want.
<!--+
| Iterate through our list of plugin artifacts.
+-->
<core:forEach var="artifact" items="${plugin.getArtifacts()}">
<!--+
| Inspect each Artifact, and grab the one we want.
+-->
<ant:echo message="Artifact : ${artifact}"/>
<ant:echo message="Class : ${artifact.getClass()}"/>
<ant:echo message="Path : ${artifact.getPath()}"/>
<ant:echo message="Depend : ${artifact.getDependency()}"/>
<ant:echo message="Type : ${artifact.getDependency().getType()}"/>
<ant:echo message="Ident : ${artifact.getDependency().getId()}"/>
</core:forEach>
For the two artifacts in our project.xml, this generates the following outpur.
[echo]
[echo] Artifact : org.apache.maven.repository.GenericArtifact@bb494b
[echo] Class : class org.apache.maven.repository.GenericArtifact
[echo] Path : /var/projects/maven/local/repository/jaf/jars/jaf-1.0.2.jar
[echo] Depend : Dep[ id:jaf:jaf pid:jaf:jaf ver:1.0.2 ar:jaf-1.0.2.jar jar:null ]
[echo] Type : jar
[echo] Ident : jaf:jaf
[echo]
[echo] Artifact : org.apache.maven.repository.GenericArtifact@1077fc9
[echo] Class : class org.apache.maven.repository.GenericArtifact
[echo] Path : /var/projects/maven/local/repository/axis/wars/axis-1.1.war
[echo] Depend : Dep[ id:axis:axis pid:axis:axis ver:1.1 ar:axis-1.1.war jar:null ]
[echo] Type : war
[echo] Ident : axis:axis
So, In theory, to catch the Axis webapp war file, we could look for an Artifact with a Dependency type of 'war' and a Dependency id of 'axis:axis'.
This seemed a good place to start :
<!--+
| Iterate through our list of plugin artifacts.
+-->
<core:forEach var="artifact" items="${plugin.getArtifacts()}">
<!--+
| Inspect each Artifact, and grab the one we want.
+-->
<core:if test="${artifact.getDependency().getType()}=='war' and ${artifact.getDependency().getId()}=='axis:axis'}">
<ant:echo message=""/>
<ant:echo message="Found Axis war file"/>
<ant:echo message="Ident : ${artifact.getDependency().getId()}"/>
<ant:echo message="Type : ${artifact.getDependency().getType()}"/>
<ant:echo message="Name : ${artifact.getName()}"/>
<ant:echo message="Path : ${artifact.getPath()}"/>
</core:if>
</core:forEach>
This didn't work, for several reasons.
Simplifying the test to check only the type, I found that Jelly does not use the equals() method to compare strings.
So, the test needs to be be changed from this :
<core:if test="${artifact.getDependency().getType()}=='war'">
to this
<core:if test="${artifact.getDependency().getType().equals('war')}">
This works of you test for one value or the other,
<core:if test="${artifact.getDependency().getType().equals('war')}">
or
<core:if test="${artifact.getDependency().getId().equals('axis.axis')}">
but not both
<core:if test="${artifact.getDependency().getType().equals('war')} and ${artifact.getDependency().getId().equals('axis.axis')}">
Next guess was that the 'and' wasn't working, so try putting both conditions together inside one set of {}.
At this point I was guessing that whatever is inside the {} is Java code, so I also changed the 'and' to '&&'.
<core:if test="${artifact.getDependency().getType().equals('war') && artifact.getDependency().getId().equals('axis:axis')}">
This goes bang because you can't have an un-escaped '&' in an XML document.
org.xml.sax.SAXParseException: The entity name must immediately follow the '&' in the entity reference.
Try escaping the '&' with the XML entity, '&'
<core:if test="${artifact.getDependency().getType().equals('war') && artifact.getDependency().getId().equals('axis:axis')}">
This works, but is a little messy.
Turns out that you can use 'and' in the expression, which implies that the expression in the {} is not quite Java.
<core:if test="${artifact.getDependency().getType().equals('war') and artifact.getDependency().getId().equals('axis:axis')}">
So, putting this together, we can now get the path to our Axis webapp war file.
<!--+
| Iterate through our list of plugin artifacts.
+-->
<core:forEach var="artifact" items="${plugin.getArtifacts()}">
<!--+
| If the artifact matches our criteria.
+-->
<core:if test="${artifact.getDependency().getType().equals('war') && artifact.getDependency().getId().equals('axis:axis')}">
<ant:echo message=""/>
<ant:echo message="Found Axis war file"/>
<ant:echo message="Ident : ${artifact.getDependency().getId()}"/>
<ant:echo message="Type : ${artifact.getDependency().getType()}"/>
<ant:echo message="Name : ${artifact.getName()}"/>
<ant:echo message="Path : ${artifact.getPath()}"/>
</core:if>
</core:forEach>
<!--+
| Unpack the Axis war file.
+-->
<ant:echo message=""/>
<ant:echo message="Unpacking Axis war file"/>
<ant:echo message="Path : ${astro.axis.webapp.dir}"/>
<ant:unjar src="${artifact.getPath()}" dest="${astro.axis.webapp.dir}"/>
This uses a property called 'astro.axis.webapp.dir', which is configured in the plugin.properties file.
#
# Location where the Axis webapp will be unpacked.
astro.axis.webapp.dir = ${maven.build.dir}/axis/webapp
Making this a property means that it can be overriden in one of the main project property files.
Once we have unpacked the Axis webapp, we can create a classpath which includes all the jar files in the WEB-INF/lib directory.
<!--+
| Create an Ant classpath from the jars inside our Axis webapp.
+-->
<ant:path id="astro.axis.classpath">
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/axis.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/axis-ant.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/saaj.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/wsdl4j.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/jaxrpc.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/commons-logging.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/commons-discovery.jar"/>
</ant:path>
We can then use Project.addPath() to add this classpath to our global build classpath.
<!--+
| Add this to the global maven.dependency.classpath.
+-->
<maven:addPath id="maven.dependency.classpath" refid="astro.axis.classpath"/>
Putting all of this together, we have a plugin goal which finds the Axis war file, unpacks it, and adds the jar files into the build classpath.
<!--+
| Goal to prepare our Axis WebApp
+-->
<goal name="astro:init-axis">
<ant:echo message=""/>
<ant:echo message="Preparing Axis webapp ...."/>
<!--+
| Iterate through our list of plugin artifacts.
+-->
<core:forEach var="artifact" items="${plugin.getArtifacts()}">
<!--+
| If the artifact matches our criteria.
+-->
<core:if test="${artifact.getDependency().getType().equals('war') && artifact.getDependency().getId().equals('axis:axis')}">
<ant:echo message=""/>
<ant:echo message="Found Axis war file"/>
<ant:echo message="Ident : ${artifact.getDependency().getId()}"/>
<ant:echo message="Type : ${artifact.getDependency().getType()}"/>
<ant:echo message="Name : ${artifact.getName()}"/>
<ant:echo message="Path : ${artifact.getPath()}"/>
<!--+
| Unpack the Axis war file.
+-->
<ant:echo message=""/>
<ant:echo message="Unpacking Axis war file"/>
<ant:echo message="Path : ${astro.axis.webapp.dir}"/>
<ant:unjar src="${artifact.getPath()}" dest="${astro.axis.webapp.dir}"/>
<!--+
| Create an Ant classpath from the jars inside our Axis webapp.
+-->
<ant:path id="astro.axis.classpath">
<!--+
<ant:pathelement path="${astro.axis.webapp.dir}/WEB-INF/lib"/>
+-->
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/axis.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/axis-ant.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/saaj.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/wsdl4j.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/jaxrpc.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/commons-logging.jar"/>
<pathelement location="${astro.axis.webapp.dir}/WEB-INF/lib/commons-discovery.jar"/>
</ant:path>
<!--+
| Add this to the global maven.dependency.classpath.
+-->
<maven:addPath id="maven.dependency.classpath" refid="astro.axis.classpath"/>
</core:if>
</core:forEach>
</goal>
Now we can use the code we created earlier to print out the contents of the build path, just to check that it is doing what we want it to.
<!--+
| Goal to list the 'maven.dependency.classpath' classpath.
+-->
<goal name="astro:classpath">
<ant:echo message=""/>
<ant:echo message="Build classpath"/>
<core:forEach var="path" items="${pom.getAntProject().getReference('maven.dependency.classpath').list()}">
<ant:echo message="Path : ${path}"/>
</core:forEach>
</goal>
<!--+
| Quick check to see if it worked ...
+-->
<goal name="astro:check">
<attainGoal name="astro:classpath"/>
<attainGoal name="astro:init-axis"/>
<attainGoal name="astro:classpath"/>
</goal>
astro:check:
astro:classpath:
[echo]
[echo] Build classpath
[echo] Path : /var/projects/maven/local/repository/ant/jars/ant-1.5.4.jar
[echo] Path : /var/projects/maven/local/repository/ant/jars/ant-optional-1.5.4.jar
[echo] Path : /var/projects/maven/local/repository/castor/jars/castor-0.9.5.jar
[echo] Path : /var/projects/maven/local/repository/castor/jars/castor-0.9.5-xml.jar
[echo] Path : /var/projects/maven/local/repository/jta/jars/jta-1.0.1.jar
[echo] Path : /var/projects/maven/local/repository/xerces/jars/xerces-2.4.0.jar
[echo] Path : /var/projects/maven/local/repository/xml-apis/jars/xml-apis-1.0.b2.jar
[echo] Path : /var/projects/maven/local/repository/jconfig/jars/jconfig-2.2.jar
[echo] Path : /var/projects/maven/local/repository/hsqldb/jars/hsqldb-1.7.1.jar
[echo] Path : /var/projects/maven/local/repository/junit/jars/junit-3.8.1.jar
astro:init-axis:
[echo]
[echo] Preparing Axis webapp ....
[echo]
[echo] Found Axis war file
[echo] Ident : axis:axis
[echo] Type : war
[echo] Name : axis-1.1.war
[echo] Path : /var/projects/maven/local/repository/axis/wars/axis-1.1.war
[echo]
[echo] Unpacking Axis war file
[echo] Path : /var/projects/astrogrid/dave-dev-20031117/community/target/axis/webapp
[unjar] Expanding: /var/projects/maven/local/repository/axis/wars/axis-1.1.war into /var/projects/astrogrid/dave-dev-20031117/community/target/axis/webapp
astro:classpath:
[echo]
[echo] Build classpath
[echo] Path : /var/projects/maven/local/repository/ant/jars/ant-1.5.4.jar
[echo] Path : /var/projects/maven/local/repository/ant/jars/ant-optional-1.5.4.jar
[echo] Path : /var/projects/maven/local/repository/castor/jars/castor-0.9.5.jar
[echo] Path : /var/projects/maven/local/repository/castor/jars/castor-0.9.5-xml.jar
[echo] Path : /var/projects/maven/local/repository/jta/jars/jta-1.0.1.jar
[echo] Path : /var/projects/maven/local/repository/xerces/jars/xerces-2.4.0.jar
[echo] Path : /var/projects/maven/local/repository/xml-apis/jars/xml-apis-1.0.b2.jar
[echo] Path : /var/projects/maven/local/repository/jconfig/jars/jconfig-2.2.jar
[echo] Path : /var/projects/maven/local/repository/hsqldb/jars/hsqldb-1.7.1.jar
[echo] Path : /var/projects/maven/local/repository/junit/jars/junit-3.8.1.jar
[echo] Path : /var/projects/astrogrid/dave-dev-20031117/community/target/axis/webapp/WEB-INF/lib/axis.jar
[echo] Path : /var/projects/astrogrid/dave-dev-20031117/community/target/axis/webapp/WEB-INF/lib/axis-ant.jar
[echo] Path : /var/projects/astrogrid/dave-dev-20031117/community/target/axis/webapp/WEB-INF/lib/saaj.jar
[echo] Path : /var/projects/astrogrid/dave-dev-20031117/community/target/axis/webapp/WEB-INF/lib/wsdl4j.jar
[echo] Path : /var/projects/astrogrid/dave-dev-20031117/community/target/axis/webapp/WEB-INF/lib/jaxrpc.jar
[echo] Path : /var/projects/astrogrid/dave-dev-20031117/community/target/axis/webapp/WEB-INF/lib/commons-logging.jar
[echo] Path : /var/projects/astrogrid/dave-dev-20031117/community/target/axis/webapp/WEB-INF/lib/commons-discovery.jar
![]() |
Click here for the AstroGrid Service Web |
This is the AstroGrid Development Wiki |
|