How can I use properties taken from a file in the code of an eclipse PDE fragment/plugin project?
I have created an eclipse plugin project and a corresponding fragment project which I use for junit tests.
In the fragment I specify the plugin project as the "Host plugin". Further 开发者_如何转开发I specify the following on the build.properties pane:
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
my.properties
where my.properties is a file located at the root of the fragment project. I have then written a test where I try to load the my.properties file like this:
Properties properties = new Properties();
InputStream istream = this.getClass().getClassLoader()
.getResourceAsStream("my.properties");
try {
properties.load(istream);
} catch (IOException e) {
e.printStackTrace();
}
but istream
is null and the test fails with a NullPointerException when calling load in the try block.
I have tried to do the same thing in the host plugin and there it works fine. Any ideas about why I can't read resouces in my PDE fragment when using Junit?
Try using Bundle#getEntry. If your plug-in has an Activator, you get a BundleContext object when your plugin is started (use Bundle-ActivationPolicy: lazy
in your manifest). You can get the Bundle object from the BundleContext:
public class Activator implements BundleActivator {
private static Bundle bundle;
public static Bundle getBundle() {
return myBundle;
}
public void start(BundleContext context) throws Exception {
bundle = context.getBundle();
}
}
...
URL url = Activator.getBundle().getEntry("my.properties");
InputStream stream = url.openStream();
properties.load(stream);
One problem you MIGHT be having is that
InputStream istream = this.getClass().getClassLoader().
getResourceAsStream("my.properties");
behaves differently in two situations where "this" is located in a different package. Since you did not append "/" to the beginning, java will automatically start looking at the package root instead of the classpath root for the resource. If the code in your plug-in project and your fragment project exist in different packages, you have a problem.
Andrew Niefer has pointed the direction, but the solution is wrong. That is one that works:
1) Add super();
to the your Activator constructor.
2) Put this into the constructor of your plugin:
Properties properties = new Properties();
try {
Bundle bundle=Activator.getDefault().getBundle();
URL url = bundle.getEntry("plugin.properties");
InputStream stream;
stream = url.openStream();
properties.load(stream);
} catch (Exception e) {
e.printStackTrace();
}
And you have functioning "properties".
Explanations:
Doing (1) you will reach all that functionality:
public class Activator implements BundleActivator {
private static Bundle bundle;
public static Bundle getBundle() {
return myBundle;
}
public void start(BundleContext context) throws Exception {
bundle = context.getBundle();
}
}
It is present already in the pre-parent class Plugin. And you simply can't put it into Activator, because getBundle() is final in Plugin.
Notice Activator.getDefault() in (2). Without it bundle is unreachable, it is not static. And if you simply create a new instance of activator, bundle of it will be null.
There is one more way to take a bundle:
Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID);
Only check that Activator.PLUGIN_ID
is set to the correct string - as is in the ID field of the Overview page of the plugin. BTW, you should check this Activator.PLUGIN_ID
after every change of the plugin ID anyway.
精彩评论