Custom CharsetProvider doesn't get loaded in signed applet
Hi all,
I've been through all the documentation here, I've been searching this problem for a while now but could not find any solution.
I created a custom CharsetProvider the following way :
- created a class extending Charset doing my custom encoding
- created a class extending CharsetProvider returning the previous class
- added my provider to META-INF/services/java.nio.charset.spi.CharsetProvider
- created a test class doing only the following : java.nio.charset.Charset.isSupported("MyCustomCharsetFromAbove")
- created a simple applet calling the test class above
I then created a jar file, signed it and tried the Test class from
1. The command line (java -jar myJar.jar, having a Main entry in the manifest)
2. From a browser through the applet
In the first case my custom charset is supported, in the second case (from the browser) it is not supported. I'm using the same jar file in both cases, I can access files through the applet from the browser (so I have file read and write permission)
I don't get why my CharsetProvider doesn't get loaded ? Do I miss something here ?
Tip : if I put a bad CharsetProvider name in META-INF/services/java.nio.charset.spi.CharsetProvider I get an exception when I test from the command line, but do not get that exception in the browser environment. It's as if the java plugin doesn't even try to read that file ...
Why I'm trying to do this ? I desperately need Cp850 encoding support in my Applet, and the problem is Cp850 isn't provided by all JVMs. So I figured I'd add Cp850 code to my sources and so provide it all the time with my applet. There is maybe a simpler way to do this than creating a custom CharsetProvider, but I couldn't find one...
Thanks,
Sebastien
Hi malcolmmc,
Thanks for your quick response !
I see where you're going. I didn't think of that because I thought that anything inside a JAR file would automaticaly be on the classpath when called from an applet
In my case I have an ant script who does the following :
- compile all my classes to a "target" dir
- create a META-INF/services directory in "target"
- copy the java.nio.charset.spi.CharsetProvider file to that new directory
- jar the target directory with a manifest file parameter
- jarsign the jar newly created
- copy the newly signed jar to a web folder, where a test html file resides
I then reload my browser, point it to the http://localhost/Test/test.html and check if it's working. I added some code to show the classpath and get only the following line : "C:\PROGRA~1\Java\JRE15~1.0_0\classes" from the browser
When I'm in command line mode it show only the name of my Jar
In applet mode isn't the Jar file automaticaly on the classpath ? I'll look for a way to add it otherwise ...
Thanks,
Sebastien
Hmm.. I would have expected that to work. I presume the applet container would create a URLClassLoader to load the applet, and that that would be the contextClassLoader. I wonder if the problem is that the Charset class is loading the providers too early, before the applet is actually loaded. Trouble is, I don't see any obvious way to get it to rescan the providers list.
Can you access your Charset more directly? The InputStreamReader class, for example, accepts a CharSet in place of an encoding name, String doesn't but then you can do that kind of conversion more readilly.
Hi malcolmcc,
I've been wandering in the java sources and here are my conclusions for the moment :
- the providers list is reloaded each time you do a "isEncodingSupported" (Charset.LookupViaProviders)
- the class loader is the singleton Sun.misc.Launcher$AppClassLoader which is looking for objects using the classpath
- the classpath is only read once : at instanciation of the previous singleton, which is before I have any chance to change it
- the classpath doesn't contain the Jar file when in Applet mode
So a solution would be to :
- change the classpath so that it includes the jar file (don't know how to do that yet)
- get the AppClassLoader to reload the classpath (same)
Another solution would be to create a new ClassLoader (may be pretty difficult, don't know if you can change the ClassLoader at runtime in an applet, seems potentially dangerous to me)
Anyway, now that my headache has reached full potential I'll get some rest and see tomorrow if I can fall back on the stream options you talked about earlier.
Thanks,
Sebastien