Og du vil naturligvis ikke bruge den simple løsning: at lade alle hente JAXP implementationen med en: Class-Path: jar-fil i manifestet på din jar-fil ?
Jeg vil mene at du "bare" skal have: - en classloader der virker - bruge den classloader til at loade den klasse der kalder XML klasserne med (så burde den blive brugt til at loade XML klasserne med)
public class Test { public static void main(String[] args) throws Exception { URL[] url = new URL[1]; url[0] = new URL("file:/C:/classloader/"); ClassLoader cl = new SpecialClassLoader(url); Object o = Class.forName("Wrapper", true, cl).newInstance(); Class[] noc = new Class[0]; Object[] noo = new Object[0]; Method m = o.getClass().getMethod("execute",noc); m.invoke(o, noo); } }
C:\classloader\Dummy.java
public class Dummy { public void hello() { System.out.println("Hello"); } }
C:\classloader\SpecialClassLoader.java
import java.net.*;
public class SpecialClassLoader extends URLClassLoader { public SpecialClassLoader(URL[] url) throws Exception { super(url); } }
C:\classloader\Wrapper.java
public class Wrapper { public Wrapper() { } public void execute() { Dummy d = new Dummy(); d.hello(); } }
javac *.java copy Test.class without copy SpecialClassLoader.class without copy Test.class with copy SpecialClassLoader.class with copy Dummy.class with cd with java Test cd .. cd without java Test cd ..
with og without er directories under.
Det er meget meget vigtigt at Wrapper.class ikke er i without (i normal classpath), fordi så virker det ikke !
Jeg får en: java.lang.InstantiationException: com.mypackage.MyApplet$MyRunnable at java.lang.Class.newInstance0(Unknown Source) at java.lang.Class.newInstance(Unknown Source) ...
og MyRunnable har en 'tom' constructor og er ikke abstract eller interface, så iflg. api docs betyder det "or if the instantiation fails for some other reason."
Hvad skulle der være i vejen med at bruge URLClassLoader direkte?
Jeg har oprettet en ny URLClassLoader med appletens classloader som parent, så tilføjer jeg crimson.jar til den nye classloader og derefter bruger jeg den nye classloader til at loade en klasse som ligger inlejret i min applet-klasse. Og så langt går det fint, klassen bliver loaded. Men når jeg så forsøger at oprette en ny instans, fejler den.
URL[] urls = new URL[] { getURL("crimson.jar") }; ClassLoader cl = getClass().getClassLoader(); URLClassLoader ucl = URLClassLoader.newInstance(urls, cl); Class c = ucl.loadClass("com.mypackage.MyApplet$MyRunnable"); Object o = c.newInstance();
Ps. Fejlene oven over er fra denne kode, ikke dit eksempel. Jeg skrev dem før jeg havde set dit indlæg.
Nej det burde være ligegyldigt hviklen klasse classloader det er bare det er en ny instans.
Hvis MyApplet$MyRunnable kan loades af den almindelige classloader (fordi den er i din applet jar fil) *og* den i constructor bruger nogle af de ting der skal loades via den specielle classloader, så virker det ikke.
Så pointen er måske at når den klasse som skal loade noget via den nye classloader, er loaded af en classloader højere oppe i hirakiet, så virker det ikke -- altså det er ikke nok at den nye classloader er med/kaldes :-/
-
Men MyApplet$MyRunnable laver ikke noget i dens constructor. Først i dens start() metode bliver xml-klasserne brugt.
Under alle omstændigheder bliver det for kedeligt (omstændigt) at skulle lave en klasse som ligger på serveren og kalder tilbage osv. kun hvis der ikke allerede er en parser på klienten. Så må brugeren bare leve med altid at downloade en parser ;-) Jeg kan jo bruge Piccolo.jar som fylder ~50kB mindre og skulle være hurtigere.
Du skal have en classloader med 2 URL's: wrapper og JAXP jar.
Så bruger du classloaderen til at loade wrapperen med og fordi wrapperen ikke kan loades af den normale classloader så bliver din classloader faktisk brugt. Og derfor kan den senere loade far JAXP jar'en.
Og ja det er bøvlet - og jeg mener også at jeg en 15 indlæg oppe startede lidt med at forske i alternativerne.
Men det var jo netop alternativet (at downloade alle klasserne) jeg ville undgå ;-)
Hvis bare class-path'en kunne være 'sløv' så den kun blev brugt hvis en klasse ikke fandtes blandt de allerede eksisterende -- når nu classloaderen alligvel starter oppefra.
Skal jeg prøve at lave et "applet-JAXP" eksempel i weekenden ?
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.