Exporting Maven properties from Ant code - maven-2

I've embedded the following code within my POM:
<plugin name="test">
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>validate</phase>
<configuration>
<tasks>
<pathconvert targetos="unix" property="project.build.directory.portable">
<path location="${project.build.directory}"/>
</pathconvert>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
I then reference ${project.build.directory.portable} from the run project action but it comes back as null. Executing <echo> within the Ant block shows the correct value. What am I doing wrong?

For completeness, the mentioned feature was implemented in the maven-antrun-plugin in October 2010.
The configuration parameter you are looking for is exportAntProperties.
Example of use:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7-SNAPSHOT</version>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<exec outputproperty="svnversion"
executable="svnversion">
<arg value=".." />
</exec>
</target>
<exportAntProperties>true</exportAntProperties>
</configuration>
</execution>
</executions>
</plugin>
As a side note, at the time of this post (2011-10-20), the official plugin documentation didn't have this option documented. To get the help for 'versionXYZ' of the plugin:
mvn help:describe -Dplugin=org.apache.maven.plugins:maven-antrun-plugin:versionXYZ -Ddetail

The version 1.7 of the maven-antrun-plugin worked for me to pass a property from ant to maven (and from mvn to ant). Some sample code that calculates an md5 checksum of a file and later stores it into a property that is accessed by mvn at a later time:
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>ant-md5</id>
<phase>initialize</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<property name="compile_classpath" refid="maven.compile.classpath"/>
<property name="outputDir" value="${project.build.outputDirectory}"/>
<property name="sourceDir" value="${project.build.sourceDirectory}"/>
<checksum file="${sourceDir}/com/blah/db/blah.java" property="blah.md5db"/>
</target>
<exportAntProperties>true</exportAntProperties>
</configuration>
</execution>
</executions>
The property is accessible in later with ${blah.md5db} in a java file.

From the plugin documentation here:
Try to add the maven prefix, so you have
<path location="${maven.project.build.directory}"/> instead
If that doesn't work, you may need to explictly redefine the property yourself:
<property name="maven.project.build.dir" value="${project.build.directory}"/>
<path location="${maven.project.build.directory}"/>

I don't think you can set a property from Ant that will be visible from Maven. You should write a Mojo.

Related

How can I test for spaces in the path and give an appropriate error?

I am trying to write an integration test POM for our project. We've got the project downloading and installing/unzipping appropriately (using the maven-dependency-plugin), but one caveat of our project is that it can't yet run in paths that have spaces in them. I'm looking for a very simple way to evaluate ${project.build.directory} and throw a human readable error if it contains spaces. I'd like this to happen BEFORE downloading dependencies, since this takes quite a bit of time.
This will do it with the help of antrun plugin and <contains> condition.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<fail message="project.build.directory(${project.build.directory}) contains spaces">
<condition>
<contains string="${project.build.directory}" substring=" "/>
</condition>
</fail>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

create directory when needed in maven

I am using maven-exec-plugin to generate java sources of Thrift. It invokes the external Thrift compiler and using -o to specify the output directory, "target/generated-sources/thrift".
The problem is neither maven-exec-plugin nor Thrift compiler automatically create the output directory, I have to manually create it.
Is there a decent/portable way use create missing directories when needed? I don't want to define a mkdir command in the pom.xml, since my project need to be system independent.
Instead of the exec plugin, use the antrun plugin to first create the directory and then invoke the thrift compiler.
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<mkdir dir="target/generated-sources/thrift"/>
<exec executable="${thrift.executable}">
<arg value="--gen"/>
<arg value="java:beans"/>
<arg value="-o"/>
<arg value="target/generated-sources/thrift"/>
<arg value="src/main/resources/MyThriftMessages.thrift"/>
</exec>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
You may also want to take a look at the maven-thrift-plugin.
You can define an ant task to do the job. Put the plugin declaration into your project's pom.xml. This will keep your project system-independent:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>createThriftDir</id>
<phase>process-resources</phase>
<configuration>
<tasks>
<delete dir="${thrift.dir}"/>
<mkdir dir="${thrift.dir}"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
If you would like to prepare such folder structure somewhere in your project and then copy to place you want, use maven-resource plugin to do that:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-folder</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<resources>
<resource>
<filtering>false</filtering>
<directory>${project.basedir}/src/main/resources/folders</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

Maven - extract /test/resources/my.zip in /target during the Test Phase

I've some test resources (that are specific for a particular task) zipped in /test/resources/my.zip.
I want to extract the zip content to /target during the maven Test Phase.
Do you know what should I specify in the pom.xml to achieve this?
One solution is to use the maven-antrun-plugin to run the unzip Ant task. The following configuration in the build section of your POM should be pretty much what you need (but I haven't tested it):
<build>
<plugins>
<!-- ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-test-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<unzip src="test/resources/my.zip" dest="target/" overwrite="true"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<!-- ... -->
</plugins>
</build>

Can maven sign not only produced jar, but also dependencies

I managed to create main jar, copy dependencies to a single directory, the only step left is to sign all jars.
I can sign my own produced jar as a part of jar:sign, but how do i sign dependencies?
Thanks
Here are a couple of options:
Use the Maven ant task to run jarsigner from the JDK against all the dependencies.
Use the webstart plugin which can sign all your JARs, even if you aren't using it for the purpose of JNLP-izing your app. I'm using it to actually JNLPize one app.
Look at what the webstart plugin source is doing to iterate over all dependencies and sign them and start a new Maven Plugin/Mojo that does the same thing, sans JNLP.
Onejar your app and its dependencies and just sign that.
add to plug-in config <archiveDirectory>target</archiveDirectory>
If you are using maven-jar-plugin, you can specify which single jar to sign using the "jarPath" setting. The following configuration causes the jar-with-dependencies file to be signed instead of the dependency-less jar file:
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>sign</goal>
</goals>
</execution>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- NOTE: The secret key is in shared version control. The
password is in shared version control. This IS NOT
SECURE. It's intended to help avoid accidentally
loading the wrong class, nothing more. -->
<jarPath>${project.build.directory}/${project.build.FinalName}-${project.packaging}-with-dependencies.${project.packaging}</jarPath>
<keystore>${basedir}/keystore</keystore>
<alias>SharedSecret</alias>
<storepass>FOO</storepass>
</configuration>
</plugin>
If you want to sign both, I don't know how to do that with maven-jar-plugin, so you may need to look into the other options mentioned above.
One can also create a single JAR using the maven-assembly-plugin.
Together with the other suggestion by Eric Anderson (of signing another JAR) one can then sign this assembled JAR (instead of the original JAR). Note that the order of the plugin definitions matters here.
It is assumed that sign.keystore.file etc are set elsewhere (e.g. in a profile).
<build>
<plugins>
<!-- It seems that maven-assembly-plugin must be declared before the maven-jar-plugin,
so that it is executed first in the package phase,
and then the signing of the packaged jar can succeed. -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifestEntries>
<!-- ... -->
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<jarPath>${project.build.directory}/${project.build.FinalName}-${project.packaging}-with-dependencies.${project.packaging}</jarPath>
<keystore>${sign.keystore.file}</keystore>
<type>${sign.keystore.type}</type>
<storepass>${sign.keystore.storepass}</storepass>
<alias>${sign.keystore.alias}</alias>
<verify>true</verify>
<verbose>false</verbose>
<removeExistingSignatures>true</removeExistingSignatures>
</configuration>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<!-- <addClasspath>true</addClasspath> -->
</manifest>
<manifestEntries>
<!-- ... -->
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>

Can maven run command line instructions?

Can we bind some native OS commands to the maven goals and/or phases?
Actually there is the Exec Maven Plugin for these cases.
See exec-maven-plugin for details
Not natively.
However, by using the AntRun plugin, you can specify an Ant task (using Exec) that execute a OS command during the build.
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase> <!-- a lifecycle phase --> </phase>
<configuration>
<tasks>
<!--
Place any Ant task here. You can add anything
you can add between <target> and </target> in a
build.xml.
-->
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>