Reflection und JAR files
-
Hallo Leute
Ich beschäftige mich zur Zeit mit einem Problem:
Ich möchte ein Projekt von mir (Fuzzy Engine) per reflection Plug-In Fähig machen.Nun ist das problem das ich hier jetzt nicht einfach hergehen kann und class files in einem folder hineinlegen kann und diese per reflection auslesen
das ganze ist schon etwas komplizierter:
Ich will .Jar files in ein directory legen:
Eine XML datei die enthalten ist soll notwendige konfigurationsparameter beinhalten und die klasse selbst ebenfallsdie klasse muss natuerlich ein spezielles interface definieren .. damit ich weiss das das ganze hand und fuss hat
ich hab mir da jetzt mal kurz was ausgedacht was ca. so aussieht
try { JarInputStream JarInput = new JarInputStream(new FileInputStream(args[0]), true); JarEntry entry; while ((entry = JarInput.getNextJarEntry()) != null) { String classMain = entry.toString(); //check den klassennamen ... funktioniert das so??? if((classMain.indexOf("class")) != -1 && classMain.indexOf("$") == -1) { Class cl = Class.forName(classMain); //jetzt kann ich mir dann die methoden holen bzw interface checken } } }
ich hab das problem das mein ding nicht funktioniert
ich hab schon verschiedene sachen probiert bekomme aber entweder eine
ClassNotFoundException oder eine violation exception (protected access)kann mir irgendjemand helfen und aufzeigen ob ich hier am komplett falschen weg bin um jar files dynamisch zu laden
danke
gomberl
-
Hier ist eine Klasse zum Laden von Jar-Archiven. Ich weis die Quelle (URL) leider nicht mehr, aber ich poste den code:
import java.io.*; import java.util.*; import java.util.zip.*; /** * JarResources: JarResources maps all resources included in a * Zip or Jar file. Additionaly, it provides a method to extract one * as a blob. */ public final class JarResources { // external debug flag public boolean debugOn=false; // jar resource mapping tables private Hashtable htSizes=new Hashtable(); private Hashtable htJarContents=new Hashtable(); // a jar file private String jarFileName; /** * creates a JarResources. It extracts all resources from a Jar * into an internal hashtable, keyed by resource names. * @param jarFileName a jar or zip file */ public JarResources(String jarFileName) { this.jarFileName=jarFileName; init(); } /** * Extracts a jar resource as a blob. * @param name a resource name. */ public byte[] getResource(String name) { return (byte[])htJarContents.get(name); } /** * initializes internal hash tables with Jar file resources. */ private void init() { try { // extracts just sizes only. ZipFile zf=new ZipFile(jarFileName); Enumeration e=zf.entries(); while (e.hasMoreElements()) { ZipEntry ze=(ZipEntry)e.nextElement(); if (debugOn) { System.out.println(dumpZipEntry(ze)); } htSizes.put(ze.getName(),new Integer((int)ze.getSize())); } zf.close(); // extract resources and put them into the hashtable. FileInputStream fis=new FileInputStream(jarFileName); BufferedInputStream bis=new BufferedInputStream(fis); ZipInputStream zis=new ZipInputStream(bis); ZipEntry ze=null; while ((ze=zis.getNextEntry())!=null) { if (ze.isDirectory()) { continue; } if (debugOn) { System.out.println( "ze.getName()="+ze.getName()+","+"getSize()="+ze.getSize() ); } int size=(int)ze.getSize(); // -1 means unknown size. if (size==-1) { size=((Integer)htSizes.get(ze.getName())).intValue(); } byte[] b=new byte[(int)size]; int rb=0; int chunk=0; while (((int)size - rb) > 0) { chunk=zis.read(b,rb,(int)size - rb); if (chunk==-1) { break; } rb+=chunk; } // add to internal resource hashtable htJarContents.put(ze.getName(),b); if (debugOn) { System.out.println( ze.getName()+" rb="+rb+ ",size="+size+ ",csize="+ze.getCompressedSize() ); } } } catch (NullPointerException e) { System.out.println("done."); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * Dumps a zip entry into a string. * @param ze a ZipEntry */ private String dumpZipEntry(ZipEntry ze) { StringBuffer sb=new StringBuffer(); if (ze.isDirectory()) { sb.append("d "); } else { sb.append("f "); } if (ze.getMethod()==ZipEntry.STORED) { sb.append("stored "); } else { sb.append("defalted "); } sb.append(ze.getName()); sb.append("\t"); sb.append(""+ze.getSize()); if (ze.getMethod()==ZipEntry.DEFLATED) { sb.append("/"+ze.getCompressedSize()); } return (sb.toString()); } /** * Is a test driver. Given a jar file and a resource name, it trys to * extract the resource and then tells us whether it could or not. * * <strong>Example</strong> * Let's say you have a JAR file which jarred up a bunch of gif image * files. Now, by using JarResources, you could extract, create, and display * those images on-the-fly. * <pre> * ... * JarResources JR=new JarResources("GifBundle.jar"); * Image image=Toolkit.createImage(JR.getResource("logo.gif"); * Image logo=Toolkit.getDefaultToolkit().createImage( * JR.getResources("logo.gif") * ); * ... * </pre> */ public static void main(String[] args) throws IOException { if (args.length!=2) { System.err.println( "usage: java JarResources <jar file name> <resource name>" ); System.exit(1); } JarResources jr=new JarResources(args[0]); byte[] buff=jr.getResource(args[1]); if (buff==null) { System.out.println("Could not find "+args[1]+"."); } else { System.out.println("Found "+args[1]+ " (length="+buff.length+")."); } } } // End of JarResources class.
Vielleicht hilft dir das weiter?
-
Danke das ist mal ne nette klasse als wrapper um ein .JAR file
nur hat sich bei mir noch nicht das problem gelöst das ich nicht weiss wie ich jetzt aus diesem BLOB den ich bekomme ein file classe instanzieren kann
ich schätze dazu werde ich wohl einen eigenen Class Loader brauchen
danke jedenfallls
-
Also durch diese Klasse kriegt man doch ein Byte-Array einer beliebigen Resource innerhalb des Archivs. Vielleicht kannst du folgender Maßen ein Objekt draus kriegen:
byte[] b = jr.getResource("Verzeichnis/Klasse.class"); Object o = (new Object()).getClass().getClassLoader().defineClass("Klasse", b, 0, b.length).newInstance(); // Also defineClass(String, int, int, int) hat Class als Rückgabewert
Es nur ein Vorschlag, vielleicht klappt es ja. Zumindest hast du so nun ein Objekt aus dem byte-array bekommen. Das glaube ich jedenfalls!
-
Ich habs jetzt zusammengebracht (Eigentlich schon freitags)
hier der code ausschnitt um aus einem jar file zu laden
es lädt eine klasse aus dem file, schaut nach ob sie ein bestimmtest interface implementiert und checkt dann ob es einen spezifischen konstruktor gibt
wenn ja lädt sie ein objekt der neuen klasseJARClassLoader ist hier nur ein etwas vereinfachter URL Class Loader
JARClassLoader ClassLoaderObject = new JARClassLoader(CurFile.toURL()); //load class Class ModuleClass = ClassLoaderObject.loadClass(ClassName); //check if ObjectClass Implements Interface Class[] Interfaces = this.getAllInterfaces(ModuleClass);//ModuleClass.getInterfaces(); boolean isModule = false; for(int j=0; (j < Interfaces.length) && (isModule == false); i++){ //System.out.println("\n\nCurrentInterface: " + Interfaces[i].getName() + " comparing to " + InterfaceClass.getName()); if(InterfaceClass.isAssignableFrom(Interfaces[i])){ //this is a correct class object isModule = true; } } if(isModule){ //load class object new instance System.out.println("Loading Module: " + ModuleClass.getName()); try{ //instantiate object with constructor Constructor ModuleConstructor = ModuleClass.getConstructor(ConstructorParams); Object[] ConsParameter = new Object[2]; ConsParameter[0] = id; ConsParameter[1] = config; ret = (AbstractModule) ModuleConstructor.newInstance(ConsParameter); System.out.println("Created Object"); //save object into hash cacheObject(ret,type,id); //ret = (AbstractModule) ModuleClass.newInstance(); } catch(Exception ex){ ex.printStackTrace(); throw new ClassNotFoundException("Constructor could not be instantiated. Class might not have correct PortalNode Constructor"); }
im endeffekt macht der URLClassLoader alles das man braucht