Print

Print


Commit in maven-service-plugin on MAIN
pom.xml+41added 1.1
src/main/java/org/lcsim/MavenServicePluginMojo.java+226added 1.1
+267
2 added files
JM: new maven plugin for automatically generating service files

maven-service-plugin
pom.xml added at 1.1
diff -N pom.xml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ pom.xml	28 Aug 2008 20:21:35 -0000	1.1
@@ -0,0 +1,41 @@
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.lcsim</groupId>
+    <artifactId>maven-service-plugin</artifactId>
+    <packaging>maven-plugin</packaging>
+    <version>1.0-SNAPSHOT</version>
+    <name>Generates a services file by scanning over a directory containing Java classes.</name>
+    <dependencies>
+        <dependency>
+           <groupId>org.apache.maven</groupId>
+           <artifactId>maven-plugin-api</artifactId>
+           <version>2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>1.3.2</version>
+        </dependency>
+        <dependency>
+	    <groupId>org.apache.maven</groupId>
+	    <artifactId>maven-artifact</artifactId>
+            <version>2.0</version>
+        </dependency>
+        <dependency>
+	    <groupId>org.apache.maven</groupId>
+    	    <artifactId>maven-project</artifactId>
+            <version>2.0</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.5</source>
+                    <target>1.5</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

maven-service-plugin/src/main/java/org/lcsim
MavenServicePluginMojo.java added at 1.1
diff -N MavenServicePluginMojo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ MavenServicePluginMojo.java	28 Aug 2008 20:21:36 -0000	1.1
@@ -0,0 +1,226 @@
+package org.lcsim;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.commons.io.DirectoryWalker;
+import org.apache.maven.project.MavenProject;
+import java.io.FileFilter;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.net.URLClassLoader;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.StringTokenizer;
+import java.io.Writer;
+import java.io.FileWriter;
+import java.io.BufferedWriter;
+
+/**
+ * A Maven plugin that generates a services file by walking a directory looking for 
+ * subclasses of a specified service class.
+ * 
+ * @goal generate-service-file
+ */
+public class MavenServicePluginMojo extends AbstractMojo
+{
+	/**
+	 * Directory to scan for classes implementing service, which defaults to project's build output directory.
+	 *
+	 * @parameter expression="scanDir=${project.build.outputDirectory}"
+	 */
+	private String scanDir;
+
+	/**
+	 * Fully qualified name of super class which corresponds to the service, with no default. 
+	 *
+	 * @parameter expression="className"
+	 */
+	private String className;
+
+	/**
+	 * Output directory where services file is placed, which defaults to standard resources area.
+	 *
+	 * @parameter expression="outputDirectory=${basedir}/src/main/resources/META-INF/services"
+	 */ 
+	private String outputDirectory;
+
+	/**
+	 * File containing full classpath that should be used by the services search.
+	 * Generate with <code>mvn dependency:build-classpath</code> saved to <code>target/classpath.txt</code>.
+	 * @parameter expression="classPathFile"
+	 */
+	private String classPathFile;
+
+	/**
+	 * The ClassLoader that will be used when instantiating classes to test against.
+	 */
+	private MyURLClassLoader loader;
+	
+	/**
+	 * The service class that will be compared against.
+	 */
+	private Class serviceClass;
+
+	/**
+	 * Setup the custom ClassLoader with the full class path.
+	 * @throws Exception
+	 */
+	private void setupClassLoader() throws Exception
+	{
+		BufferedReader input =  new BufferedReader(new FileReader(new File(classPathFile)));
+		String line = null;
+		List<URL> urls = new ArrayList<URL>();        
+		while (( line = input.readLine()) != null)
+		{
+			StringTokenizer tok = new StringTokenizer(line,":");
+			while(tok.hasMoreTokens()) 
+			{
+				String nextTok = tok.nextToken();
+				urls.add((new File(nextTok)).toURL());
+			}        	        	
+		}
+		URL urlsArr[] = new URL[urls.size()];
+		for (int i=0; i<urls.size(); i++)
+		{
+			urlsArr[i] = urls.get(i);
+		}        
+		loader = new MyURLClassLoader(urlsArr);
+	}
+
+	public void execute() throws MojoExecutionException
+	{
+		if (scanDir == null) throw new RuntimeException("scanDir not set");
+		if (className == null) throw new RuntimeException("className not set");
+		if (outputDirectory == null) throw new RuntimeException("outputDirectory not set");
+		if (classPathFile == null) throw new RuntimeException("classPathFile not set");
+
+		try {
+			setupClassLoader();
+		}
+		catch (Exception x)
+		{
+			throw new RuntimeException(x);
+		}
+		
+		try {
+			serviceClass = loader.loadClass(className);
+		}
+		catch (Exception x)
+		{
+			throw new RuntimeException(x);
+		}
+
+		// Walk the start directory for subclasses of the service class.
+		ServiceDirWalker dirWalk = new ServiceDirWalker(new ClassFileFilter(), -1);
+		Collection drivers = new ArrayList();
+		dirWalk.walkIt(new File(scanDir), drivers);
+
+		// Add results of search to services file.
+		try {
+			(new File(outputDirectory)).mkdirs();
+			File outfile = new File(outputDirectory + File.separator + className);
+
+			BufferedWriter output = new BufferedWriter(new FileWriter(outfile));
+
+			for (Object o : drivers)
+			{
+				Class klass = (Class)o;
+				output.write(klass.getName());
+				output.newLine();
+			}        
+			output.close();
+			
+			getLog().info("Wrote services file to " + outfile.toString());
+		}
+		catch (Exception x)
+		{
+			throw new RuntimeException(x);
+		}
+	}
+	
+	class ServiceDirWalker extends DirectoryWalker
+	{
+		File baseDir;
+		
+		public ServiceDirWalker(FileFilter filter, int depth)
+		{
+			super(filter, depth);
+		}
+
+		public void handleDirectoryStart(File directory, int depth, Collection results)
+		{
+			try 
+			{
+				loader.addURL(directory.toURL());
+			}
+			catch (Exception x)
+			{
+				throw new RuntimeException(x);
+			}
+		}		
+
+		public void handleFile(File file, int depth, Collection results) 
+		{
+			try {		
+				// Load the class.
+				Class klass = 
+					loader.loadClass(file.getCanonicalPath().replace(baseDir.getCanonicalPath(),"").replace(".class","").replace("/",".").substring(1));
+				// Check if service class is a superclass.
+				if (serviceClass.isAssignableFrom(klass))
+				{
+					// Add to results.
+					results.add(klass);
+				} 
+			}
+			catch (Exception x)
+			{
+				throw new RuntimeException(x);
+			}
+		}
+
+		public void walkIt(File f, Collection c)
+		{
+			baseDir = f;
+			try 
+			{
+				super.walk(f, c);
+			}
+			catch(IOException x)
+			{
+				throw new RuntimeException(x);
+			}
+		}
+	}
+
+	class MyURLClassLoader extends URLClassLoader
+	{
+		public MyURLClassLoader(URL urls[])
+		{
+			super(urls, Thread.currentThread().getContextClassLoader());
+		}
+
+		public void addURL(URL url)
+		{
+			super.addURL(url);
+		}
+	}
+
+	class ClassFileFilter implements FileFilter
+	{
+		public boolean accept(File pathname)
+		{
+			if (pathname.isDirectory()) return true;                        
+			try {
+				if (pathname.getCanonicalPath().endsWith(".class")) return true; else return false;
+			}
+			catch (Exception x)
+			{
+				throw new RuntimeException(x);
+			}
+		}
+	}
+}
CVSspam 0.2.8