Eclipse RCP中获取Plugin/Bundle中文件资源的绝对路径
2012-02-21 20:00
387 查看
摘要:在进行Eclipse RCP开发的过程中,需要使用一些其他的资源(如图片、声音、配置文件、数据库等),我们一般将这些资源放到Plugin/Bundle的相应目录下(如图片资源放到icons目录,声音放到sounds目录,数据库文件放到data目录)。本文先对Eclipse Plugin和Bundle进行分析,之后讲解了如何使用Eclipse API通过这些资源的相对路径(相对于Plugin/Bundle)获取这些资源的绝对路径的方法,最后总结了org.osgi.framework.Bundle接口和FileLocator工具类的使用方法。
Bundle和Plugin
Eclipse Platform架构于OSGi核心之上,每个Eclipse Plugin就是OSGi的一个Bundle,因此在Eclipse RCP中Plugin和Bundle是等价的概念。
OSGi框架中定义了org.osgi.framework.IBundle接口,表示运行于OSGi环境中的一个Bundle。Eclipse RCP中定义了org.eclipse.core.runtime.Plugin抽象类,代表一个Eclipse插件。但是Plugin抽象类并没有实现IBundle接口,而是在内部拥有一个IBundle对象实例。Plugin类实现了BundleActivator,控制其内部的IBundle对象的启动和停止,并负责将BundleContext注入到IBundle对象实例中。
我们可以发现,在IBundle接口中定义了如下几个方法,可以获取位于在Bundle文件目录中的资源:
如何获取当前的Bundle对象
开发Eclipse Plugin/Bundle应用首先需要创建Activator类,继承自org.eclipse.ui.plugin.AbstractUIPlugin,该类继承自上文提到的org.eclipse.core.runtime.Plugin类,OSGi框架在加载Plugin/Bundle的时候首先加载此Activator类,然后调用此类中定义的start(BundleContext context)和stop(BundleContext context)方法启动和停止这个Plugin/Bundle。在这个类的父类Plugin中声明了Bundle类型实例,可以通过getBundle()方法获取这个Bundle实例。
以下代码为Activator类中的start(BundleContext)方法,在其中调用了getResource(String)和getEntry(String)两个方法,同时调用FileLocator.toFileURL(String)将URL转化为文件系统的路径
上面代码输出结果为:
通过结果可以很明显看到,使用getResource(String)和getEntry(String)获取到的URL是OSGi环境中的路径,需要通过FileLocator.toFileURL(String)方法将OSGi环境中的URL转化为文件系统中的URL。
至于getResource()和getEntry()有什么区别,我到Eclipse Forum里面提了问题,回答是:
getResource uses the bundle’s class loader to load a resource. This resource could come from imported constraints (Import-Package, Require-Bundle) or from the local bundle classpath.
getEntry only searches the bundles jar files itself and does not consider any constraints or the bundle’s class path (Bundle-ClassPath header).”
详见http://www.eclipse.org/forums/index.php/m/710032/#msg_710032
FileLocator
在上文已经提到FileLocator的toFileUrl(String)方法,FileLocator是一个工具类,其目的就是在Bundle中查找相应的资源文件,其本身定义了如下几个方法:
看起来和Bundle中的方法那么的相似,归根结底,FileLocator中的方法也都是通过调用Bundle中的相对应方法来实现其功能的,除了resolve(URL)和toFileURL(URL),后者之前演示过其功能,前者的功能也同样是将OSGi环境中的URL解析成为文件系统中的URL。其实我不认为此FileLocator除去toFileURL()此方法外地其他方法有更好的地方,如果可能,还是直接用Bundle的方法更好。
总结
很明显,在Bundle中查找文件资源需要通过FileLocator和Bundle两个类的协作才能完成,由于一般情况下Eclipse RCP的属性以及配置值存放于Eclipse Workspace中,从Bundle中读取资源的需求比较少。最主要的应用场景是,一些图片资源可以通过此方式读取,然后在Eclipse RCP应用中处理和显示。
Eclipse RCP 中 Part 和 Site、菜单和工具栏
Eclipse RCP开发中关于Image(图片)的API使用
Eclipse RCP中的日志
Bundle和Plugin
Eclipse Platform架构于OSGi核心之上,每个Eclipse Plugin就是OSGi的一个Bundle,因此在Eclipse RCP中Plugin和Bundle是等价的概念。
OSGi框架中定义了org.osgi.framework.IBundle接口,表示运行于OSGi环境中的一个Bundle。Eclipse RCP中定义了org.eclipse.core.runtime.Plugin抽象类,代表一个Eclipse插件。但是Plugin抽象类并没有实现IBundle接口,而是在内部拥有一个IBundle对象实例。Plugin类实现了BundleActivator,控制其内部的IBundle对象的启动和停止,并负责将BundleContext注入到IBundle对象实例中。
我们可以发现,在IBundle接口中定义了如下几个方法,可以获取位于在Bundle文件目录中的资源:
方法 | 解释 |
---|---|
URL getResource(String name); | 通过Bundle的Class Loader加载资源,和Class.getResource(String)类似,注意如果当前的bundle是一个fregment,则返回null |
Enumeration getResources(String name) | 和上面的方法一样,不过由于Eclipse插件可以包括多个Fregment,每个Fregment中可以分别包含相对路径相同的文件,因此通过一个相对路径可能找到多个匹配的资源 |
URL getEntry(String path); | 在当前Bundle中根据Path找相应的Entry(此处的entry和resource到底有什么区别我还尚不清楚) |
Enumeration getEntryPaths(String path); | 和上面的方法一样,同getResources(String) |
Enumeration findEntries(String path, String filePattern, boolean recurse); | 根据path和pattern找相应的资源文件,可以使用通配符,如需要查找所有语言文件: bundle.findEntries(“OSGI-INF/l10n”, “*.properties”, true); |
开发Eclipse Plugin/Bundle应用首先需要创建Activator类,继承自org.eclipse.ui.plugin.AbstractUIPlugin,该类继承自上文提到的org.eclipse.core.runtime.Plugin类,OSGi框架在加载Plugin/Bundle的时候首先加载此Activator类,然后调用此类中定义的start(BundleContext context)和stop(BundleContext context)方法启动和停止这个Plugin/Bundle。在这个类的父类Plugin中声明了Bundle类型实例,可以通过getBundle()方法获取这个Bundle实例。
以下代码为Activator类中的start(BundleContext)方法,在其中调用了getResource(String)和getEntry(String)两个方法,同时调用FileLocator.toFileURL(String)将URL转化为文件系统的路径
public void start(BundleContext context) throws Exception { super.start(context); plugin = this; System.out.println(Activator.getDefault().getBundle().getLocation()); URL url = Activator.getDefault().getBundle().getResource("META-INF/MANIFEST.MF"); System.out.println(url); System.out.println(FileLocator.toFileURL(url)); URL url2 = Activator.getDefault().getBundle().getEntry("META-INF/MANIFEST.MF"); System.out.println(url2); System.out.println(FileLocator.toFileURL(url2)); }
上面代码输出结果为:
reference:file:/D:/demo/modeling-workspace/com.zhlwish.proppagedemo/ bundleresource://709.fwk15218962:1/META-INF/MANIFEST.MF file:/D:/demo/modeling-workspace/com.zhlwish.proppagedemo/META-INF/MANIFEST.MF bundleentry://709.fwk15218962/META-INF/MANIFEST.MF file:/D:/demo/modeling-workspace/com.zhlwish.proppagedemo/META-INF/MANIFEST.MF
通过结果可以很明显看到,使用getResource(String)和getEntry(String)获取到的URL是OSGi环境中的路径,需要通过FileLocator.toFileURL(String)方法将OSGi环境中的URL转化为文件系统中的URL。
至于getResource()和getEntry()有什么区别,我到Eclipse Forum里面提了问题,回答是:
getResource uses the bundle’s class loader to load a resource. This resource could come from imported constraints (Import-Package, Require-Bundle) or from the local bundle classpath.
getEntry only searches the bundles jar files itself and does not consider any constraints or the bundle’s class path (Bundle-ClassPath header).”
详见http://www.eclipse.org/forums/index.php/m/710032/#msg_710032
FileLocator
在上文已经提到FileLocator的toFileUrl(String)方法,FileLocator是一个工具类,其目的就是在Bundle中查找相应的资源文件,其本身定义了如下几个方法:
static URL find(Bundle bundle, IPath path, Map override); static URL find(URL url); static URL[] findEntries(Bundle bundle, IPath path); static URL[] findEntries(Bundle bundle, IPath path, Map override); static File getBundleFile(Bundle bundle); static InputStream openStream(Bundle bundle, IPath file, boolean substituteArgs); static URL resolve(URL url); static URL toFileURL(URL url);
看起来和Bundle中的方法那么的相似,归根结底,FileLocator中的方法也都是通过调用Bundle中的相对应方法来实现其功能的,除了resolve(URL)和toFileURL(URL),后者之前演示过其功能,前者的功能也同样是将OSGi环境中的URL解析成为文件系统中的URL。其实我不认为此FileLocator除去toFileURL()此方法外地其他方法有更好的地方,如果可能,还是直接用Bundle的方法更好。
总结
很明显,在Bundle中查找文件资源需要通过FileLocator和Bundle两个类的协作才能完成,由于一般情况下Eclipse RCP的属性以及配置值存放于Eclipse Workspace中,从Bundle中读取资源的需求比较少。最主要的应用场景是,一些图片资源可以通过此方式读取,然后在Eclipse RCP应用中处理和显示。
关于Eclipse RCP开发的其他文章:
Eclipse RCP 中 Part 和 Site、菜单和工具栏
Eclipse RCP开发中关于Image(图片)的API使用
Eclipse RCP中的日志
相关文章推荐
- Eclipse RCP中获取Plugin/Bundle中文件资源的绝对路径
- Eclipse RCP中获取Plugin/Bundle中文件资源的绝对路径(转载)
- Eclipse RCP中获取Plugin/Bundle中文件资源的绝对路径(转)
- Eclipse RCP中获取Plugin/Bundle中文件资源的绝对路径
- rcp(插件开发)获取Plugin/Bundle中文件资源的绝对路径
- rcp(插件开发)获取Plugin/Bundle中文件资源的绝对路径
- iOS获取工程目录下的资源文件的绝对路径
- Java中获取classpath路径下的资源文件【ClassLoader.getSystemResource("")获取当前ClassPath的绝对URI路径,还可以以流的形式获取文件】
- JavaSE 文件递归之删除&获取文件夹目录中所有的以.jpg的文件的绝对路径
- ie9下获取上传文件的绝对路径
- 获取可执行文件的绝对路径
- 一个获取文件绝对路径的sh
- Java或者JAR包获取读取资源文件的路径的问题总结
- 获取文件绝对路径和目录
- 使用GetModuleFileName()获取当前.exe所在绝对路径,并且读取.ini配置文件
- JAVA 用getName()来获取名字, 获取的是文件的绝对路径还是文件的名字??
- 根据Uri获取文件绝对路径
- 转:Maven项目中获取classpath和资源文件的路径
- PHP 获取 主机地址 和脚本文件的绝对路径
- Java代码获取classpath路径方法和资源文件路径方法