Developing your own maven plugin to verify the bytecode of your artifact

In this article the goal is to develop your own maven plugin that accesses at build time the artifact of your project and verifies the class files. I used this concept for my library jb5n to verify that for each MessageResource interface an appropriate key/value pair is available in the underlying resource bundle.
The first step is of course to create a new maven module or project using the mojo archetype:

mvn archetype:generate \
  -DgroupId=sample.plugin \
  -DartifactId=hello-maven-plugin \
  -DarchetypeGroupId=org.apache.maven.archetypes \
  -DarchetypeArtifactId=maven-archetype-plugin

This will create a ready-to-run maven project of type maven-plugin for you:

  <groupId>sample.plugin</groupId>
  <artifactId>hello-maven-plugin</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>maven-plugin</packaging>

All necessary dependencies to develop your own maven plugin are already available. The archetype also creates a simple Mojo class:

/**
 * @goal verify
 * @phase verify
 */
public class MyMojo extends AbstractMojo {

    /**
     * @parameter default-value="${project}"
     */
    private MavenProject mavenProject;

The maven goal as well as the default phase of the lifecycle the plugin runs in is given by the javadoc elements @goal and @phase. Newer versions of maven let you define these values with annotations. To access the outcome of the current build process we let our plugin run in the verify phase. We can access the file of our artifact by accessing the member variable mavenProject, which is injected by maven into our plugin with the above definition:

File artifactFile = mavenProject.getArtifact().getFile();

The File object from the above snippet will point to the jar file (in case we have chosen jar packaging for our artifact). Therefore we can open the jar file using Java’s SDK classes JarFile and JarEntry:

JarFile jarFile = new JarFile(artifactFile);
Enumeration<JarEntry> entries = jarFile.entries();
while(entries.hasMoreElements()) {
	JarEntry jarEntry = entries.nextElement();
	String jarEntryName = jarEntry.getName();
	if(jarEntryName != null && jarEntryName.endsWith(".class")) {
		getLog().debug(String.format("Processing jar file entry '%s'.", jarEntryName));
		...
	}
}

Now we can use a library like javassist or Java’s reflection API to analyze each class file within the artifact.

Advertisements

Tags: , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: