#7703 closed defect (fixed)
How to get resources from inside plugin?
Reported by: | kendzi | Owned by: | bastiK |
---|---|---|---|
Priority: | critical | Milestone: | |
Component: | Core | Version: | |
Keywords: | Cc: |
Description (last modified by )
In plugin loading class I try to get resource file from my plugin jar (kendzi3d.jar) using call:
getClass().getResource(“/resources/pluginProperties.properties”);
but in response I get:
jar:file:/C:/Documents%20and%20Settings/kendzi/Dane%20aplikacji/JOSM/plugins/ImportImagePlugin.jar!/resources/pluginProperties.properties
So url is pointing to file inside different plugin! ImportImagePlugin plugin have file with same name.
call to getClass()
result:
class kendzi.josm.kendzi3d.Kendzi3DPlugin (inside kendzi3d.jar)
It seems that it is bug with plugin class loader.
Or there is any other way to get files from my plugin jar?
Attachments (0)
Change History (7)
comment:1 by , 13 years ago
Description: | modified (diff) |
---|
comment:2 by , 13 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:3 by , 13 years ago
comment:4 by , 13 years ago
Replying to kendzi:
Or there is any other way to get files from my plugin jar?
As a workaround, we could provide a plugin class loader, that is only used to get resources, but not classes.
follow-up: 6 comment:5 by , 13 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
In 5241/josm:
follow-up: 7 comment:6 by , 13 years ago
Replying to bastiK:
In 5241/josm:
I well test solution but as I understand it solve this one problem but the rest remains.
And problems are:
- what if two plugins use the same class in the same package?
- what if two plugins try loads externals jar file with different and not compatible version?
- how to load external jar from plugin? (eg jog4j) I’m using reflection on class loader [1], but it should be some “official” way to do it.
- as I saw some plugins extract class from externals jar into plugins jar, this may cause problems if two plugins are using the same jars
- it should be possible to share some code between plugins, but really should plugins see each other? Maybe plugins should declared some public api to internals?
- it should be possible to share resources between plugins eg icons. But it would be nice if in first place they were take from orginal jar.
- provided solution won’t work with external libraries which usually using call to getResource()
Did I say that I hate class loaders?
Maybe some solution to problems can be solve by using OSGi for plugins?
[1] https://github.com/kendzi/kendzi3d/blob/master/kendzi.josm.plugin3d/src/kendzi/josm/kendzi3d/NativeLibPlugin.java#L206
comment:7 by , 13 years ago
Replying to kendzi:
Replying to bastiK:
In 5241/josm:
I well test solution but as I understand it solve this one problem but the rest remains.
And problems are:
- what if two plugins use the same class in the same package?
Java conventions dictate, that you use a unique package name for each project.
- what if two plugins try loads externals jar file with different and not compatible version?
Right, that wouldn't work, but let's wait until this actually happens. There are still workarounds given the current setup.
- how to load external jar from plugin? (eg jog4j) I’m using reflection on class loader [1], but it should be some “official” way to do it.
I think a good solution would be to list the required libs in the Manifest, e.g.
Class-Path: resource://lib/mylib.jar resource://lib/otherlib.jar
The "resource:" prefix would indicate that the file needs to be copied from the plugin jar to the plugin folder before loading the plugin. (Or write a custom class loader, that gets the class files from the inner jars on the fly. this site has interesting info on class loaders, especially in the comments.)
It gets more complicated, when there is some code that gets to decide which libraries to load (e.g. depending on operating system and architecture).
In case you haven't seen it already: the ImportImagePlugin also loads external libs, but uses a different hack, if I remember correctly.
- as I saw some plugins extract class from externals jar into plugins jar, this may cause problems if two plugins are using the same jars
- it should be possible to share some code between plugins, but really should plugins see each other? Maybe plugins should declared some public api to internals?
Ideally, each plugin would see the classes of the dependent plugins and JOSM core. However, the obvious solution doesn't work as written above. What do you suggest?
- it should be possible to share resources between plugins eg icons. But it would be nice if in first place they were take from orginal jar.
I can provide a similar fix for icon loading. It would look something like this: new ImageProvider(name).setClassLoader(plugin.getResourceClassLoader()).get();
- provided solution won’t work with external libraries which usually using call to getResource()
True, unless you use a designated class loader.
Did I say that I hate class loaders?
I'm not too enthusiastic about it either. Also, the plugin code is serious foobar, so it feels like opening a can of worms. Anyway, I wouldn't mind if you provided some patches for core. :)
Maybe some solution to problems can be solve by using OSGi for plugins?
[1] https://github.com/kendzi/kendzi3d/blob/master/kendzi.josm.plugin3d/src/kendzi/josm/kendzi3d/NativeLibPlugin.java#L206
Here is a temporary "solution" that avoids hacking the JVM: Your plugin consists of a single bootstrap class and the real plugin is a jar file wrapped inside the plugin jar. Your single class would copy the real plugin jar and some libraries to the plugin folder and execute everything using a URLClassLoader. This would work similar to the plugin loading code in JOSM core.
Currently we have a single class loader for all plugins. I can change it such that each plugin has its own class loader that only sees the plugin jar, the main josm jar and the jar files of the required plugins.
However, there seem to be some side effects of having multiple class loaders:
These problems only apply to plugin dependencies, e.g. opendata requires jts.
Given these issues, I suggest, we keep the current broken behaviour.