Um problema que sempre atormentou minha vida foi tentar descobrir em qual JAR está uma determinada classe. Até o momento eu recorria ao http://www.findjar.com, http://www.jarfinder.com/ ou Google. O problema é que nem sempre o JAR é encontrado ou está em versão errada. Para resolver esse tormento resolvi criar um programinha que consiste em buscar à partir de um caminho todos os arquivos JAR e procurar dentro dele à classe que eu quero.
Primeiro eu busco por arquivos JAR recursivamente:
protected void searchForJars(File path, List<String> resultado) { for (File f : path.listFiles(filter)) { if (breakIfFound && found) return; if (f.isDirectory()) { searchForJars(f, resultado); } else { List<String> res = searchInsideJar(f); if (res != null) { resultado.addAll(res); found = true; } } } }
Se eu encontrar um arquivo JAR, eu busco dentro dele a informação que eu quero:
protected List<String> searchInsideJar(File f) { List<String> resultado = null; try { JarFile jar = new JarFile(f); Enumeration<JarEntry> entries = jar.entries(); while (entries.hasMoreElements()) { String entry = entries.nextElement().getName(); if (entry.contains(classToFind)) { if (resultado == null) { resultado = new ArrayList<String>(); } resultado.add(f.getPath() + ":" + entry); if (breakIfFound) { return resultado; } } } } catch (IOException e) { e.printStackTrace(); } return resultado; }
Se eu encontrar algum arquivo que tenha a String que eu quero, adiciono o resultado numa lista. Para quem só precisa do utilitário, vou disponibizá-lo aqui. Para usar é necessário Java 7 e depois é só digitar:
java -jar thiago-vespa-utils-classfinder.jar <CAMINHO> <CLASSE COMPLETA OU TRECHO> <BREAK>
Por exemplo:
java -jar thiago-vespa-utils-classfinder.jar /opt/Oracle111150/Middleware/Oracle_SOA1/soa/modules Record
Ou
java -jar thiago-vespa-utils-classfinder.jar /opt/Oracle111150/Middleware/Oracle_SOA1/soa/modules oracle.tip.adapter.api.record.RecordElement break
O break serve para informar que é para parar ao encontrar o primeiro. Se não digitar break ele vai encontrar todas as referências da classe especificada.
Boa :).
Um problema parecido (mas não idêntico) que volta e meia aparece é o seguinte: Descobrir o jar de uma classe a qual você tem acesso em runtime.
Pode parecer estranho mas em um Application Server com trocentas shared libraries, não é incomum você usar uma classe sem ter a menor idéia da sua proveniência.
Eis uma solução:
public static URL getLocation(Class clazz) {
return clazz.getProtectionDomain().getCodeSource().getLocation();
}
public static URL getLocation(String className) throws ClassNotFoundException {
return getLocation(Class.forName(className));
}
Exemplo de uso:
System.out.println(getLocation(EntityManager.class));
System.out.println(getLocation("org.apache.commons.lang.builder.ReflectionToStringBuilder"));
Saída do exemplo para um projeto Maven na minha máquina:
file:/home/anthony/.m2/repository/javax/persistence/javax.persistence/2.0-SNAPSHOT/javax.persistence-2.0-SNAPSHOT.jar
file:/home/anthony/.m2/repository/commons-lang/commons-lang/2.6/commons-lang-2.6.jar
[...] utilizando uma classe com versão diferente do quartz-2.x. Se você utilizar o utilitário descrito nesse post na pasta de instalação do WebLogic com SOA Suite, irá verificar que o WebLogic utiliza outra [...]