Brett,
2009/3/21 Brett Randall <[email protected]>:
> I think this was asked on the list last week, or recently anyway. The
> poster was pointed at https://animal-sniffer.dev.java.net/ .
You are right! I requested this last week. However, the Maven plugin
of animal-sniffer didn't really have a mojo for only checking the
class file versions although most of the ground work was there. I sent
Koshuke a patch for including another goal to check the main and
attached artifacts for a specific Java version. It seems it can help
out some other people too, so here is the patch file again.
Ringo
diff --git
a/animal-sniffer/src/main/java/org/jvnet/animal_sniffer/ClassFileVisitor.java
b/animal-sniffer/src/main/java/org/jvnet/animal_sniffer/ClassFileVisitor.java
index b814c9a..2ae98b4 100644
---
a/animal-sniffer/src/main/java/org/jvnet/animal_sniffer/ClassFileVisitor.java
+++
b/animal-sniffer/src/main/java/org/jvnet/animal_sniffer/ClassFileVisitor.java
@@ -35,7 +35,7 @@ public abstract class ClassFileVisitor {
if(file.getName().endsWith(".class"))
processClassFile(file);
else
- if(file.getName().endsWith(".jar"))
+ if(file.getName().endsWith(".jar") || file.getName().endsWith(".war"))
processJarFile(file);
// ignore other files
diff --git
a/animal-sniffer/src/main/java/org/jvnet/animal_sniffer/maven/ClassVersionMojo.java
b/animal-sniffer/src/main/java/org/jvnet/animal_sniffer/maven/ClassVersionMojo.java
new file mode 100644
index 0000000..28c41b9
--- /dev/null
+++
b/animal-sniffer/src/main/java/org/jvnet/animal_sniffer/maven/ClassVersionMojo.java
@@ -0,0 +1,86 @@
+package org.jvnet.animal_sniffer.maven;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+
+/**
+ * Checks that all the built JAR/EAR/WAR files contain class files targeted to
a specific
+ * Java version.
+ *
+ * @author Ringo De Smet
+ * @phase verify
+ * @goal classVersions
+ */
+public class ClassVersionMojo extends AbstractMojo {
+
+ private final static Map JAVA_VERSIONS_MAP;
+
+ static {
+ JAVA_VERSIONS_MAP = new HashMap();
+ JAVA_VERSIONS_MAP.put("1.3", new Integer(47));
+ JAVA_VERSIONS_MAP.put("1.4", new Integer(48));
+ JAVA_VERSIONS_MAP.put("5.0", new Integer(49));
+ JAVA_VERSIONS_MAP.put("6.0", new Integer(50));
+ }
+
+ /**
+ * @parameter expression="${project}"
+ * @required
+ * @readonly
+ */
+ private MavenProject project;
+
+ /**
+ * Specify the Java version where all class files should comply to.
+ * Valid values for this argument are '1.3', '1.4', '5.0' and '6.0'.
+ *
+ * @parameter expression=${javaVersion} default="1.4"
+ */
+ private String javaVersion;
+
+ /**
+ * Specify whether the built artifacts should have generated class files
+ * exactly for the specified Java version. By default, this is not enforced.
+ * If it is enforced, even class file versions for a lower JDK version are
not
+ * allowed. For instance, when the javaVersion specified is '5.0' and this
+ * parameter is set to 'true', then class files for Java 1.4 are not
allowed either.
+ *
+ * @parameter expression="${strict}" default="false"
+ */
+ private boolean strict;
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ Integer requestedClassVersion =
(Integer)JAVA_VERSIONS_MAP.get(javaVersion);
+ if(requestedClassVersion==null) {
+ throw new MojoFailureException("Invalid Java version '" + javaVersion
+ "'! Valid values are 1.3, 1.4, 5.0 and 6.0.");
+ }
+ ReportingClassFileVersionVisitor visitor = new
ReportingClassFileVersionVisitor(getLog(),requestedClassVersion.intValue(),strict);
+ List builtArtifacts = new ArrayList();
+ // Add the main artifact
+ builtArtifacts.add(project.getArtifact());
+ // Add additional attached artifacts
+ builtArtifacts.addAll(project.getAttachedArtifacts());
+ if(getLog().isDebugEnabled())
+ getLog().debug("Validating class files to match version number " +
requestedClassVersion);
+ for(int artifactNumber = 0; artifactNumber < builtArtifacts.size();
artifactNumber++) {
+ org.apache.maven.artifact.Artifact artifact =
(org.apache.maven.artifact.Artifact) builtArtifacts.get(artifactNumber);
+ try {
+ File artifactFile = artifact.getFile();
+ getLog().info("Checking class file versions of " +
artifactFile.getName());
+ visitor.process(artifactFile);
+ } catch(IOException ioe) {
+ throw new MojoExecutionException("I/O Exception",ioe);
+ }
+ }
+ if(visitor.getNumberOfMismatches()>0) {
+ throw new MojoFailureException("Not all class files comply to the
Java version " + javaVersion);
+ }
+ }
+
+}
diff --git
a/animal-sniffer/src/main/java/org/jvnet/animal_sniffer/maven/ReportingClassFileVersionVisitor.java
b/animal-sniffer/src/main/java/org/jvnet/animal_sniffer/maven/ReportingClassFileVersionVisitor.java
new file mode 100644
index 0000000..ebb47d4
--- /dev/null
+++
b/animal-sniffer/src/main/java/org/jvnet/animal_sniffer/maven/ReportingClassFileVersionVisitor.java
@@ -0,0 +1,56 @@
+package org.jvnet.animal_sniffer.maven;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.maven.plugin.logging.Log;
+import org.jvnet.animal_sniffer.ClassFileVisitor;
+
+/**
+ * @author Ringo De Smet
+ */
+public class ReportingClassFileVersionVisitor extends ClassFileVisitor {
+
+ private final Log logger;
+ private final boolean strict;
+ private final int requestedClassFileVersion;
+ private int nrOfMismatches;
+
+ public ReportingClassFileVersionVisitor(Log logger,int
requestedClassFileVersion, boolean strict) {
+ this.logger = logger;
+ this.requestedClassFileVersion = requestedClassFileVersion;
+ this.strict = strict;
+ this.nrOfMismatches = 0;
+ }
+
+ protected void process(String name, InputStream image) throws IOException {
+ if(logger.isDebugEnabled())
+ logger.debug("Verifying class file version of " + name);
+ DataInputStream dis = new DataInputStream(image);
+ byte[] buf = new byte[8];
+ dis.readFully(buf);
+
+ int actualClassFileVersion = u2(buf[6],buf[7]);
+ if(strict) {
+ if(actualClassFileVersion != requestedClassFileVersion) {
+ nrOfMismatches++;
+ logger.error(name + " has version " +
actualClassFileVersion+"."+u2(buf[4],buf[5])+"!");
+ }
+ } else {
+ if(actualClassFileVersion > requestedClassFileVersion) {
+ nrOfMismatches++;
+ logger.error(name + " has version " +
actualClassFileVersion+"."+u2(buf[4],buf[5])+"!");
+ }
+ }
+ }
+
+ private static int u2(byte u, byte d) {
+ return ((int)u)*256+d;
+ }
+
+ public int getNumberOfMismatches() {
+ return nrOfMismatches;
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]