To generate signatures of any API, you simple construct a project with the appropriate dependencies exposed by the API and then add an execution of the animal-sniffer:build goal to your project. In the case of the Java Runtime, this is a project with no dependencies, e.g.
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>____</groupId>
<artifactId>____</artifactId>
<version>____</version>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.16</version>
<executions>
<execution>
<id>___id of execution___</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Then you just build this project with the appropriate Java Runtime, and it will generate the signatures of that Java Runtime.
The observant reader may have spotted that it may not always be possible to run Maven with the Java Runtime that you want to generate the signatures of. In these cases you have a number of solutions:
An example of using the jdk parameter is:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.16</version>
...
<configuration>
...
<jdk>
<version>[1.6.0,1.6.1)</version>
<vendor>sun</vendor>
</jdk>
...
</configuration>
...
</plugin>
...
</plugins>
...
</build>
...
</project>
An example of using the javaHome parameter is:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.16</version>
...
<configuration>
...
<javaHome>C:\Program Files\Java\jdk_1.6.0_14</javaHome>
...
</configuration>
...
</plugin>
...
</plugins>
...
</build>
...
</project>
An example of this technique is:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.16</version>
...
<configuration>
...
<javaHomeClassPath>
<javaHomeClassPath>C:\Program Files\Java\jdk_1.6.0_14\jre\lib\rt.jar</javaHomeClassPath>
<javaHomeClassPath>C:\Program Files\Java\jdk_1.6.0_14\jre\lib\jsse.jar</javaHomeClassPath>
</javaHomeClassPath>
...
</configuration>
...
</plugin>
...
</plugins>
...
</build>
...
</project>
The above examples generate signatures of the entire classpath of the JRE. That will include all the implementation classes which are not part of the public contract of the JRE. For example sun.misc.BASE64Encoder is part of Sun's JRE runtime libraries, but is not part of the JRE specification and if you run on a JRE produced by a different vendor, it is highly likely that that class will not be available to your program.
In order to ensure that the Java signatures you generate only include those classes which are officially published by the JRE, you will need to tune your signatures.
One technique is to only include those classes which you know are part of the JRE public specification. For example:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.16</version>
...
<configuration>
...
<jdk>
<version>[1.4.0,1.5.0)</version>
</jdk>
<includeClasses>
<includeClass>java.*</includeClass>
<includeClass>javax.*</includeClass>
<includeClass>org.omg.*</includeClass>
<includeClass>org.w3c.dom.*</includeClass>
<!-- etc -->
...
</includeClasses>
...
</configuration>
...
</plugin>
...
</plugins>
...
</build>
...
</project>
This requires that you known exactly what classes are part of the JRE specification.
The other technique is to specify which classes are not to be included. Note that a combination of the two can also be used. For example:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.16</version>
...
<configuration>
...
<jdk>
<version>[1.4.0,1.5.0)</version>
</jdk>
<excludeClasses>
<excludeClass>com.sun.*</excludeClass>
<excludeClass>sun.*</excludeClass>
<!-- etc -->
...
</excludeClasses>
...
</configuration>
...
</plugin>
...
</plugins>
...
</build>
...
</project>
By default, if the version of Java that you require is not available, the animal-sniffer plugin will fail the build. If you are generating multiple signatures, this may not be exactly what you want. For example you may be generating signatures for JREs on Windows, Linux and MacOS from the same project. This would require building the same project at least three times and setting the skipIfNoJavaHome option to true for example
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.16</version>
...
<configuration>
...
<skipIfNoJavaHome>true</skipIfNoJavaHome>
...
</configuration>
...
<executions>
<execution>
<id>windows</id>
...
<configuration>
...
<classifier>windows</classifier>
<jdk>
<version>[1.4.0,1.5.0)</version>
<os>windows</os>
</jdk>
...
</configuration>
...
</execution>
<execution>
<id>linux
...
<configuration>
...
<classifier>linux</classifier>
<jdk>
<version>[1.4.0,1.5.0)</version>
<os>linux</os>
</jdk>
...
</configuration>
...
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>
Animal sniffer uses a helper module to try and determine the boot classpath of the Java Home that has been specified. This can be done in one of two ways:
The helper module should work for most common versions of Java providing they are at least Java 1.2.
If the default helper module does not work for the version of Java that you need to generate signatures of, you can replace the helper module with your own module. The replacement module must meet the following specification:
When invoking the helper module, animal-sniffer will:
A replacement module must be added to the dependencies section of the Animal Sniffer Plugin and the groupId and artifactId must be configured using the jbcpdGroupId and jbcpdArtifactId configuration options. For example, if your custom boot classpath detector is com.mycompany:detect-boot-classpath:1.2.0:jar then you could configure animal-sniffer to use this with the following:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.16</version>
...
<configuration>
...
<jbcpdGroupId>com.mycompany</jbcpdGroupId>
<jbcpdArtifactId>detect-boot-classpath</jbcpdArtifactId>
...
</configuration>
...
<dependencies>
...
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>detect-boot-classpath</artifactId>
<version>1.2.0</version>
</dependency>
...
</dependencies>
...
</plugin>
...
</plugins>
...
</build>
...
</project>