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]

Reply via email to