Olá pessoal, tudo bem?
Bom antes de apresentar minha dúvida, apresento meu problema.
Eu estou fazendo um projeto onde eu quero mapear classes feitas em outros projetos de acordo com o padrão DAO, nesse caso esse mapeamento será feito usando JDBC (com PreparedStatement’s e tudo mais que tiver direito). Acontece que nas pesquisas que andei fazendo, vi que para poder manipular classes externas ao projeto em tempo de execução eu precisaria criar um classloader próprio (já li o tuto aqui do guj) e carregar essas classes de um jar para o meu projeto. Até aí tudo bem, pesquisando mais ainda consegui criar uma forma de adicionar arquivos .class dentro de um jar, sendo que esse jar eu salvo na pasta do projeto e em seguida passo ao objeto do tipo URLClassLoader que criei. O primeiro problema é que esses arquivos .class estão dentro de um pacote (pasta) e o código que tenho para gerar o jar aceita apenas 1 diretório contendo todos os .class dentro, nesse caso se tiver outra pasta (pacote) dentro ele não aceita, dá uma Exception dizendo que o arquivo tal é um diretório, só que as classes que eu estou adicionando tem no seu cabeçalho o nome do pacote a que pertence, logo o código que cria o Jar coloca as classes todas compactadas dentro do jar sem respeitar a pasta (pacote) em que estavam.
E o problema final. Depois que tudo foi criado e adicionado quando uso Reflection para “depenar” a classe o classloader não encontra ela, mas isso foi testado com 6 classes dentro de um jar e o mais estranho é que apenas 1 classe foi encontrada! Resumindo usando o comando classloader.loadClass("<nome_do_pacote.nome_da_classe>"), de 6 classes apenas uma encontra as demais não encontra e dá ClassNotFoundException, sendo que nesse caso se eu não coloco o pacote onde a classe foi criada o programa lança outra exceção dizendo que o nome da classe está errado apontando o nome dela mais o pacote a que ela pertence.
Então minha dúvida (finalmente) é: como posso adicionar classes externas de modo dinâmico ao meu projeto, para depois com o uso de reflection descobrir seus métodos?
Antes para dar uma clareada segue o método que gera o jar e adiciona o mesmo ao classloader.
public void createJarArchive(File archiveFile, File[] tobeJared) {
try {
byte buffer[] = new byte[10240];
// Abre o arquivo
FileOutputStream stream = new FileOutputStream(archiveFile);
JarOutputStream out = new JarOutputStream(stream, new Manifest());
for (int i = 0; i < tobeJared.length; i++) {
if (tobeJared[i] == null || !tobeJared[i].exists() || tobeJared[i].isDirectory())
continue; // Just in case...
System.out.println("Adicionando ao jar:" + tobeJared[i].getName());
// Adiciona o arquivo ao jar
JarEntry jarAdd = new JarEntry(tobeJared[i].getName());
jarAdd.setTime(tobeJared[i].lastModified());
out.putNextEntry(jarAdd);
// Salva o arquivo
FileInputStream in = new FileInputStream(tobeJared[i]);
while (true) {
int nRead = in.read(buffer, 0, buffer.length);
if (nRead <= 0)
break;
out.write(buffer, 0, nRead);
}
in.close();
}
out.close();
stream.close();
System.out.println("Criação do jar completa");
} catch (Exception ex) {
ex.printStackTrace();
System.out.println("Error: " + ex.getMessage());
}
}
A seguir a classe que representa o classloader
package util;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
/**
* Arquivo criado em: 09/07/2010
* @author Laudelino Martins Cardoso Neto
*/
public class CarregadorDeClassesUtil extends URLClassLoader{
private String urlPath;
public CarregadorDeClassesUtil() {
super(new URL[]{});
}
//Adiciona o jar
public void addJarFile (String path){
try{
urlPath = "jar:file://" + path + "!/";
addURL(new URL(urlPath));
}catch (Exception e) {
e.printStackTrace();
ArquivosUtil.gravarLog(DiversosUtil.getMensagemExcecao(e), ArquivosUtil.LOG_TIPO_ERRO);
}
}
//Com base no nome da classe tenta descobrir seus métodos
public void listarMetodosDaClasse(String nomeDaClasse){
try {
Class c = this.loadClass(nomeDaClasse);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++) {
System.out.println(m[i].toString());
}
}catch (Throwable e) {
System.err.println(e);
}
}
//Método que lista os .class dentro do jar criado
public List getClasseNamesInPackage(String jarName){
ArrayList listaDeClasses = new ArrayList ();
try{
JarInputStream jarFile = new JarInputStream(new FileInputStream(jarName));
JarEntry jarEntry;
while(true) {
jarEntry = jarFile.getNextJarEntry ();
if(jarEntry == null){
break;
}
listaDeClasses.add(jarEntry.getName().replaceAll("/", "\\."));
}
}catch( Exception e){
e.printStackTrace ();
}
return listaDeClasses;
}
}//Fim da classe CarregadorDeClassesUtil
Desde já agradeço a atenção de todos e aguardo retorno 