Estigmatizados

La informática profesional no es un juego de políticos

Jarfinder Tool – Utilidad cli para localizar clases Java en el Classpath

El título parece un chiste de Chiquito… Disculpad, tengo que cuidar también el mercado anglosajón🙂
Esta utilidad tiene básicamente la misma función que la JSP para localizar clases vista en un post anterior.
Ejecutada sobre un directorio busca los archivos .jar existentes y crea un ClassLoader para delegar en él la búsqueda de la clase indicada como parámetro.
Presenta un par de diferencias con la versión JSP, estas diferencias se traducen en pros y contras.

Pros
—-
Al poder ser invocada desde línea de comando es mucho más sencilla de usar; no tenemos por qué andar copiando la JSP en el contexto de una aplicación. Tan sólo tenemos que ejecutarla indicando el directorio padre donde se encuentran los archivos JAR que pueden contener la clase buscada (ej: c:\install\alfresco\tomcat)

Contras
—-
Al crear un ClassLoader propio, el JAR que esta utilidad encuentra puede no coincidir con el JAR que utiliza el ClassLoader de la aplicación web. Recordemos que los ClassLoader se organizan en una jerarquía y ésta puede ser parent-child o child-parent. Si dos JAR contienen una misma clase la versión de línea de comandos no tiene por qué devolver el mismo JAR que utiliza el ClassLoader de la aplicación web.

Un ejemplo de uso de la utilidad sería:
jarfinder /R -class org.apache.coyote.ActionCode -dir .

Siendo jarfinder un archivo de script (sh o bat) tal como:

@echo off
c:\desarrollo\java\install\jdk1.6.0_14\bin\java.exe -jar "C:\Archivos de programa\Desarrollo\jarfinder.jar" %1 %2 %3 %4 %5 %6 %7 %8 %9

El código fuente Java de la utilidad:

package es.fsaldepaz.cmdutils;
import java.io.File;
import java.io.FileFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Fernando Salazar de Paz
 *
 */
public class JarFinder {

	private static final String VERBOSE_PARAM_KEY = "/V";
	private static final String RECURSIVE_PARAM_KEY = "/R";
	private static final String CLASSNAME_PARAM_KEY = "-CLASS";
	private static final String BASEDIR_PARAM_KEY = "-DIR";
	private static final String JAR_EXTENSION = ".JAR";

	private static boolean recursive = false;
	private static boolean verbose = false;
	private static String className = null;
	private static String baseDir = null;

	/**
	 * @param args
	 */
	private static void processArgs(String[] args) {

		for (int i = 0; i < args.length; i++) {
			if (args&#91;i&#93;.equalsIgnoreCase(RECURSIVE_PARAM_KEY))
				recursive = true;

			if (args&#91;i&#93;.equalsIgnoreCase(VERBOSE_PARAM_KEY))
				verbose = true;	

			if (args&#91;i&#93;.equalsIgnoreCase(BASEDIR_PARAM_KEY))
				baseDir = (i < args.length-1 ? args&#91;i+1&#93; : "");

			if (args&#91;i&#93;.equalsIgnoreCase(CLASSNAME_PARAM_KEY))
				className = (i < args.length-1 ? args&#91;i+1&#93; : "");
		}
	}

	/**
	 * @param baseDir
	 * @param recursive
	 * @param fileList
	 */
	private static void addJarFiles(String baseDir, boolean recursive, List<File> fileList) {

		File baseFile = new File(baseDir);

		FileFilter jarFilter = new FileFilter() {

			@Override
			public boolean accept(File arg0) {
				return arg0.getPath().toUpperCase().endsWith(JAR_EXTENSION);
			}
		};

		File[] files = baseFile.listFiles(jarFilter);

		if (files!= null)
			for(File f : files)
				fileList.add(f);

		if (recursive) {
			files = baseFile.listFiles();
			if (files != null)
				for(File file : files)
					if (file.isDirectory())
						addJarFiles(file.getPath(), recursive, fileList);
		}
	}

	/**
	 * @param jarFiles
	 * @return
	 * @throws MalformedURLException
	 */
	private static URLClassLoader createURLClassLoader(List<File> jarFiles) throws MalformedURLException {

		URL[] urls = new URL[jarFiles.size()];

		for(int i = 0; i < urls.length; i++)
			urls&#91;i&#93; = jarFiles.get(i).toURI().toURL();

		return new URLClassLoader(urls);
	}

	/**
	 *
	 */
	private static void printUsageInfo() {

		System.out.println("jarfinder -class fqn_clase &#91;-dir directorio&#93; &#91;/V&#93; &#91;/R&#93;");
		System.out.println();
		System.out.println("fqn_clase\tNombre de clase totalmente cualificado -ej: java.lang.String-");
		System.out.println("basedir\t\tDirectorio raíz para la búsqueda &#91;.&#93;");
		System.out.println("/V\t\tModo 'verbose'");
		System.out.println("/R\t\tBúsqueda recursiva");
	}

	/**
	 * @param args
	 * @throws MalformedURLException
	 */
	public static void main(String&#91;&#93; args) throws MalformedURLException {

		processArgs(args);

		if (verbose) {
			System.out.println("Clase buscada: " + className);
			System.out.println("Directorio base: " + baseDir);
			System.out.println("Modo recursivo: " + recursive);
			System.out.println("Modo explicativo: " + verbose);
			System.out.println();
			System.out.println("Creando lista de archivos .JAR...");
		}

		if (className != null && !className.isEmpty()) {
			String normClassName = className.replace(".", "/").concat(".class");

			List<File> jarFiles = new ArrayList<File>();			

			addJarFiles(baseDir, recursive, jarFiles);

			if (verbose) {
				for(File f : jarFiles)
					System.out.println(f.getPath());
				System.out.println();
			}

			URLClassLoader uClsLoader = createURLClassLoader(jarFiles);
			URL foundUrl = uClsLoader.getResource(normClassName);

			if (foundUrl != null)
				System.out.println(foundUrl.getFile());
			else
				System.out.println("No encontrado");

		} else
			printUsageInfo();
	}

}

La utilidad podría ocuparse ella de misma de buscar las clases utilizando el soporte de archivos ZIP que incluye Java. Esto permitiría, por ejemplo, listar todos los JAR que contuvieran una misma clase.

septiembre 14, 2009 - Posted by | Programación

Aún no hay comentarios.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: