From: Eric B. <el...@gm...> - 2006-08-15 22:14:27
|
Hi all, I'm trying to retrieve an XML file as a Stream from the inside of a JAR file. Here's what works: [code] PluginJAR myPluginJAR = jEdit.getPluginJAR("myPluginClass"); ClassLoader myPluginClassLoader = myPluginJAR.getClassLoader(); InputStream inputStream = myPluginClassLoader.getResourceAsStream("conf/myImportant.xml"); [/code] Here's what doesn't work: [code] ClassLoader myPluginClassLoader = new JARClassLoader(); InputStream inputStream = myPluginClassLoader.getResourceAsStream("conf/myImportant.xml"); [/code] I didn't expect this to work because there's no way to find out which jar it's in. So I tried: [code] ClassLoader myPluginClassLoader = new JARClassLoader(); InputStream inputStream = myPluginClassLoader.getResourceAsStream("jeditresource:/myPlugin.jar!/conf/myImportant.xml"); [/code] This didn't work either. The JavaDoc for JARClassLoader says: "A class loader implementation that loads classes from JAR files. All instances share the same set of classes." So I thought that any instance of the classLoader should be able get at the resources of the other Jars as well, perhaps with a different notation? Anyway, there isn't that much documentation on how to use the jeditresource and the plugins that use it like XML don't seem to be using it this way. I've tried using the java.net.JarURLConnection syntax as well, "jar:<url>!/{entry}" and that doesn't seem to work either. Any help on this would be greatly appreciated. Thanks, Eric -- Learn from the past. Live in the present. Plan for the future. |
From: Marcelo V. <va...@us...> - 2006-08-16 06:21:43
|
Hi there, Very easy to fix. Comments inline. Eric Berry wrote: > The JavaDoc for JARClassLoader says: > "A class loader implementation that loads classes from JAR files. All > instances share the same set of classes." So I thought that any > instance of the classLoader should be able get at the resources of the > other Jars as well, perhaps with a different notation? The documentation says all instances share the same set of classes, not resources. That might be counter intuitive, but if you look at the implementation, that's exactly what happens: JARClassLoader keeps a map with the loaded classes and the respective class loaders, but totally disregards anything that is not a class. So to get a resource from a jar file, you need to find the class loader that loaded that jar file. Doing what you tried: > Here's what doesn't work: > [code] > ClassLoader myPluginClassLoader = new JARClassLoader(); Won't work because the jar file wasn't loaded by your new instance of JARClassLoader. So you have two options: (i) if the resource belongs to the jar from where the class is loaded (i.e., you're trying to load a resource from the same plugin that's executing that Java code), you can just use "getClass().getResource()" and it works. ProjectViewer (and I'm sure others) does that, just look at projectviewer.vpt.IconComposer. (ii) if you're trying to load a resource from another plugin, you need to find it's class loader. The easiest way to do it is to call jEdit.getPlugin(name).getPluginJAR().getClassLoader(). The just do classloader.getResource(). I haven't tried the URLs you tried to figure out why they're not working, but I know the two options above should work (at least the first one works for sure). -- Marcelo Vanzin va...@us... "Life is too short to drink cheap beer" |
From: Eric B. <el...@gm...> - 2006-08-16 15:35:28
|
Thanks Vampire and Marcelo, I was playing around with these suggestions this morning and they work for my situation where I'm doing manual loading of files from various Jar files. Unfortunately, they won't work when there is any automatic loading from a 3rd party. The plugin I'm building integrates the Spring Framework with jEdit allowing other plugins to provide one Main context file which I can load via your suggestions. However, I found that those didn't work right when using an "import" from within the context files. I found that the JarURLConnection syntax worked if I pointed the url to a file on the local system. Which isn't bad because it's not too hard to just figure out where all the plugins are installed. So, for now I think I'll use this, unless I can find a way to easily override how Spring loads resources and then replace it with one of the above suggestions. I'll keep working on it though, because I'd like to be able to use the jeditresource and allow other plugins to use it - if they are using my plugin. Thanks again for the help, and if there's any suggestions I'd love to hear them. Thanks, Eric On 8/16/06, Vampire <Vam...@gm...> wrote: > If you want to use a URL like > "jeditresource:/myPlugin.jar!/conf/myImportant.xml" (which is valid and > works, but you should use > "jeditresource:///myPlugin.jar!/conf/myImportant.xml" which is the > correct syntax for the URL) you have to use it where it is valid, means > you can use it (it = new > URL("jeditresource:///myPlugin.jar!/conf/myImportant.xml");) anywhere, > where an URL is taken as argument. The > ClassLoader.getResourceAsStream(String) method is not such a place where > you can use an URL. A working example is e. g. > > new org.gjt.sp.jedit.proto.jeditresource.PluginResURLConnection(new > URL("jeditresource:///myPlugin.jar!/conf/myImportant.xml")).getInputStream(); > > to get the InputStream you wanted. > > -- Learn from the past. Live in the present. Plan for the future. |
From: Vampire <Vam...@gm...> - 2006-08-16 16:02:42
|
> Unfortunately, they won't work when there is any automatic loading >from a 3rd party. > > What do you mean with "automatic loading from a 3rd party"? >The plugin I'm building integrates the Spring Framework with jEdit >allowing other plugins to provide one Main context file which I can >load via your suggestions. However, I found that those didn't work >right when using an "import" from within the context files. > > What is a context file in your terms and what does "import" mean in that context? >I found that the JarURLConnection syntax worked if I pointed the url >to a file on the local system. Which isn't bad because it's not too >hard to just figure out where all the plugins are installed. > I doesn't have to be the case that all plugins are installed in the same directory, e. g. some could be in the jedit-directory/jars, and some could be in the settings-directory/jars. But you can get the full path of a loaded plugin through the PluginJAR classes getPath()-method e. g.. But you should _maybe_ consider to don't use it. Maybe in future there will be changes that makes that way impossible (nothing planned, just a thought what could happen) >So, for now I think I'll use this, unless I can find a way to easily override >how Spring loads resources and then replace it with one of the above >suggestions. > >I'll keep working on it though, because I'd like to be able to use the >jeditresource and allow other plugins to use it - if they are using my >plugin. > >Thanks again for the help, and if there's any suggestions I'd love to hear them. > > |
From: Vampire <Vam...@gm...> - 2006-08-16 15:41:53
|
If you want to use a URL like "jeditresource:/myPlugin.jar!/conf/myImportant.xml" (which is valid and works, but you should use "jeditresource:///myPlugin.jar!/conf/myImportant.xml" which is the correct syntax for the URL) you have to use it where it is valid, means you can use it (it = new URL("jeditresource:///myPlugin.jar!/conf/myImportant.xml");) anywhere, where an URL is taken as argument. The ClassLoader.getResourceAsStream(String) method is not such a place where you can use an URL. A working example is e. g. new org.gjt.sp.jedit.proto.jeditresource.PluginResURLConnection(new URL("jeditresource:///myPlugin.jar!/conf/myImportant.xml")).getInputStream(); to get the InputStream you wanted. |
From: Vampire <Vam...@gm...> - 2006-08-17 15:21:25
|
Eric Berry wrote: > Hey Vampire, > > On 8/16/06, Vampire <Vam...@gm...> wrote: > >> >> > Unfortunately, they won't work when there is any automatic loading >> >from a 3rd party. >> > >> > >> What do you mean with "automatic loading from a 3rd party"? > > > Spring provides (among other things) a great way to initialize beans > through XML. It uses the ClassLoader to load classes in the classpath, > but you define the beans in XML files. There's more comments below on > this matter. Just to note it, the bean persistence mechanism from the java.beans package stores beans in XML files too, or rather in XML format, no matter if you pipe it into a file or somewhere else. >> >The plugin I'm building integrates the Spring Framework with jEdit >> >allowing other plugins to provide one Main context file which I can >> >load via your suggestions. However, I found that those didn't work >> >right when using an "import" from within the context files. >> > >> > >> What is a context file in your terms and what does "import" mean in that >> context? > > In accordance with the above, a context file would be a file > containing bean definitions you want Spring to load and initialize. > Importing, allows you to include/import other bean context files in > your main context file. > > As an example. I could have a database plugin for jEdit. This plugin > would have the "main" plugin class (DatabasePlugin), which could be in > a "main" context file (databasePlugin.xml). The databasePlugin.xml > might want to import other context files to help separate components. > For instance: The DatabasePlugin might have a set of pre-defined > datasources. These might be in a dataSource.xml. > > My issue was that I didn't want to have to copy all these context > files to the local file system, so a better bet would be to use the > classpath, and reference the files via some sort of classpath URL. To > do that I needed to figure out what the URL structure would be to > access these XML files from the jar files, and be able to do this from > one instance of a ClassLoader. Why from a ClassLoader and not through an URLConnection? How does such an import look like and how does Spring process it? >> directory, e. g. some could be in the jedit-directory/jars, and some >> could be in the settings-directory/jars. But you can get the full path >> of a loaded plugin through the PluginJAR classes getPath()-method e. g.. >> But you should _maybe_ consider to don't use it. Maybe in future there >> will be changes that makes that way impossible (nothing planned, just a >> thought what could happen) > > I doesn't have to be the case that all plugins are installed in the same > > Bummer! I'll keep this in mind as I progress along with this plugin. I > was kind of banking on the fact that on the plugin download options > pane, you only have 2 options for where you want the plugins to be > installed, and you can only select one of them. Which I thought would > mean all downloaded plugins would go into one directory. You are partly right. The thing is that you can still have plugins in both directories. Plugins in the jEdit directory get always loaded (unless the -noplugins switch is used), plugins in the settings directory get loaded if that settings directory is used (i. e. if no switch is used every user has its own settings directory and additional you can influence which settings directory is used on startup with the -settings switch, or suppress any settings-directory with the -nosettings switch). Additionally you can set the property to "settings directory", download some plugins, then they are put there (while the standard plugins QuickNotepad, LatestVersion and MacOS still are at the "jEdit home") and then you switch the setting to "jEdit home" and download again some plugins, then the new plugins are put in the jEdit home, but the "old" plugins still are at the settings directory. And I didn't think much about it, but I think it is possible to load plugins manually/programmatically from any location you want, so the plugin-jars can reside everywhere. But as I said you can get the full paths of all loaded plugins programmatically how I described in the last mail. |
From: Eric B. <el...@gm...> - 2006-08-18 23:09:36
|
> Just to note it, the bean persistence mechanism from the java.beans > package stores beans in XML files too, or rather in XML format, no > matter if you pipe it into a file or somewhere else. Yes, the XMLEncoder rocks! Spring has it's own format however. I've used XSLT before to translate the serialized (XML) java objects into the Spring format, but really their XML is more about dependency injection or inversion of control (IOC). It's a way to initialize and create beans through XML, but also to inject beans with their perspective dependencies. If you're interested, I urge you to check out the website, they'll be able to explain everything much easier than I will. http://www.springframework.org > Why from a ClassLoader and not through an URLConnection? > How does such an import look like and how does Spring process it? Classes are loaded from the ClassLoader - resources are loaded through their own ResourceLoaders, but after looking through their code and fiddling around a bit, it looks like they end up using basically 3 different methods, URLConnection, a file or the classloader. An import literally looks like this: [code] <import resource="axis.xml"/> [/code] This is in my web context file and loads up all the stuff for Apache Axis since I have a small webservice. > You are partly right. The thing is that you can still have plugins in > both directories. Plugins in the jEdit directory get always loaded > (unless the -noplugins switch is used), plugins in the settings > directory get loaded if that settings directory is used (i. e. if no > switch is used every user has its own settings directory and additional > you can influence which settings directory is used on startup with the > -settings switch, or suppress any settings-directory with the > -nosettings switch). Additionally you can set the property to "settings > directory", download some plugins, then they are put there (while the > standard plugins QuickNotepad, LatestVersion and MacOS still are at the > "jEdit home") and then you switch the setting to "jEdit home" and > download again some plugins, then the new plugins are put in the jEdit > home, but the "old" plugins still are at the settings directory. And I > didn't think much about it, but I think it is possible to load plugins > manually/programmatically from any location you want, so the plugin-jars > can reside everywhere. But as I said you can get the full paths of all > loaded plugins programmatically how I described in the last mail. Yeah, I figured out a way to work around this. Since Spring allows for the dynamic replacement of variables in their XML files (like ant style variables), I can easily set the directory of each plugin as a System property and then the plugins can reference that in their context files. So a plugin using my plugin might have this in their main context file. [code] <import resource="${myOtherPlugin.resource.root}/axis.xml"/> [/code] ${myOtherPlugin.resource.root} will get replaced with a "jar:file://path/to/myOtherPlugin.jar!". This is great, this way, any plugin using my plugin (and thus Spring) can be anywhere, as long as jEdit's JARLClassloader knows about it, and I can find it via the getPlugins() method. I'm not sure if it's possible to have a plugin where the jar doesn't exist on the filesystem, but this would be the only problem. Thanks again for all the help. Eric -- Learn from the past. Live in the present. Plan for the future. |