读书人

制造一个基于OSGi的Web Application

发布时间: 2012-10-06 17:34:01 作者: rapoo

打造一个基于OSGi的Web Application——设置初始化bundle的StartLevel

在前几天的文章中描述了如何在Web Application中启动OSGi,参见

打造一个基于OSGi的Web Application——在WebApplication中启动OSGi

后来发现其中在初始化时加载bundle的方式,还有一些美中不足。这种方式加载的bundle都具有相同的启动顺序,即bundle的初始化默认start level,在之前均没有做过特别的设置,所以默认值都是1,这样会导致所有的bundle的启动顺序无法控制,在某些希望特殊bundle优先加载的场合(如日志功能,需要最先加载),我们希望能够在bundle初始化的时候就能指定特别的start level,这样所有的bundle就能按照我们预设的启动顺序来加载了。下面就是我优化过的初始化代码,能够解决启动顺序问题。

工作原理是这样的,首先,在原来存放初始化bundle的目录,也就是OSGi-Web工程的/WEB-INF/osgi/plugins目录下面再增加一个名为start的目录,在start目录下,再按照期望设置的start level来建立子目录,例如,期望设置start level为1的bundle,放到plugins/start/1目录下面;期望设置start level为2的bundle,放到plugins/start/2目录下面,以此类推。

代码方面,设置bundle的start level,需要使用StartLevel Service,可以通过下面代码获得:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->1?????????????????//?StartLevel?Service,用于设置bundle的startlevel
2?????????????????ServiceReference?slRef?=?bundleContext.getServiceReference(StartLevel.class.getName());
3?????????????????StartLevel?sl?=?slRef?==?null???null?:?(StartLevel)?bundleContext.getService(slRef);

然后设置initial bundle start level:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->1?????????????????//?设置新bundle的初始startlevel为系统配置项:org.osgi.framework.startlevel.beginning的值
2?????????????????String?bsl?=?bundleContext.getProperty("org.osgi.framework.startlevel.beginning");
3?????????????????if?(bsl?!=?null?&&?isInteger(bsl))?sl.setInitialBundleStartLevel(Integer.parseInt(bsl));

这样所有新安装的bundle的初始化start level都将被设置为和系统配置项:org.osgi.framework.startlevel.beginning相同的值,以确保所有默认安装的bundle都能启动。
修改osgi.properties中关于org.osgi.framework.startlevel.beginning的配置项,我改成了5:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->1?#Specifies?the?beginning?start?level?of?the?framework.?See?Start
2?#Level?Service?Specification?on?page?235?for?more?information.
3?#
4?org.osgi.framework.startlevel.beginning?=?5



增加一个方法,用于安装一个目录下所有的直属bundle,并且设置start level:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->?1?????private?static?void?installBundles(BundleContext?bundleContext,?File?bundleRoot,?StartLevel?sl,?int?bsl)?{
?2?????????File?bundleFiles[]?=?bundleRoot.listFiles(new?FilenameFilter()?{
?3?????????????public?boolean?accept(File?dir,?String?name)?{
?4?????????????????return?name.endsWith(".jar");
?5?????????????}
?6?????????});
?7?
?8?????????if?(bundleFiles?!=?null?&&?bundleFiles.length?>?0)?{
?9?????????????for?(File?bundleFile?:?bundleFiles)?{
10?????????????????try?{
11?????????????????????Bundle?bundle?=?bundleContext.installBundle(bundleFile.toURL().toExternalForm());
12?????????????????????if?(sl?!=?null?&&?bsl?>?0)?sl.setBundleStartLevel(bundle,?bsl);
13?????????????????????if?(logger.isInfoEnabled())?logger.info("Install?bundle?success:?"?+?bundleFile.getName());
14?????????????????}?catch?(Throwable?e)?{
15?????????????????????if?(logger.isWarnEnabled())?logger.warn("Install?bundle?error:?"?+?bundleFile,?e);
16?????????????????}
17?????????????}
18?????????}
19?????}


最后,遍历start目录下的子目录来安装所有的bundle:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->?1?????????????????//?安装bundle并设置相应的start?level
?2?????????????????File?slRoot?=?new?File(bundleRoot,?"start");
?3?????????????????if?(slRoot.isDirectory())?{
?4?????????????????????File?slDirs[]?=?slRoot.listFiles(new?FileFilter()?{
?5?????????????????????????public?boolean?accept(File?file)?{
?6?????????????????????????????return?file.isDirectory()?&&?isInteger(file.getName());
?7?????????????????????????}
?8?????????????????????});
?9?
10?????????????????????for?(File?slDir?:?slDirs)?{
11?????????????????????????installBundles(bundleContext,?slDir,?sl,?Integer.parseInt(slDir.getName()));
12?????????????????????}
13?????????????????}
14?
15?????????????????//?安装直属目录下面的bundle
16?????????????????installBundles(bundleContext,?bundleRoot,?sl,?0);

?

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->1?????private?static?boolean?isInteger(String?value)?{
2?????????try?{
3?????????????Integer.parseInt(value);
4?????????????return?true;
5?????????}?catch?(NumberFormatException?e)?{
6?????????????return?false;
7?????????}
8?????}


最后,由于Declarative Services的存在,稍微调整了一下启动策略,所有包含Service-Component的header定义的bundle,也调用start方法来启动:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->?1?????????????????for?(Bundle?bundle?:?bundleContext.getBundles())?{
?2?????????????????????if?(bundle.getState()?==?Bundle.INSTALLED?||?bundle.getState()?==?Bundle.RESOLVED)?{
?3?????????????????????????if?(bundle.getHeaders().get(Constants.BUNDLE_ACTIVATOR)?!=?null?||?bundle.getHeaders().get("Service-Component")?!=?null)?{
?4?????????????????????????????try?{
?5?????????????????????????????????bundle.start(Bundle.START_ACTIVATION_POLICY);
?6?????????????????????????????????if?(logger.isInfoEnabled())?logger.info("Start?bundle:?"?+?bundle);
?7?????????????????????????????}?catch?(Throwable?e)?{
?8?????????????????????????????????if?(logger.isWarnEnabled())?logger.warn("Start?bundle?error:?"?+?bundle,?e);
?9?????????????????????????????}
10?????????????????????????}
11?????????????????????}
12?????????????????}


clean Server然后启动Server,我们可以看到初始化后的bundle已经被赋予了指定Start Level。


附上initFramework方法的完整代码,更多的代码请参加以前的帖子:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->?1?????//?初始化Framework环境
?2?????private?static?void?initFramework(Framework?framework,?ServletContextEvent?event)?throws?IOException?{
?3?????????BundleContext?bundleContext?=?framework.getBundleContext();
?4?????????ServletContext?servletContext?=?event.getServletContext();
?5?
?6?????????//?将ServletContext注册为服务
?7?????????registerContext(bundleContext,?servletContext);
?8?
?9?????????File?file?=?bundleContext.getDataFile(".init");
10?????????if?(!file.isFile())?{?//?第一次初始化
11?????????????if?(logger.isInfoEnabled())?logger.info("Init?Framework制造一个基于OSGi的Web Application——设置初始化bundle的StartLevel");
12?
13?????????????String?pluginLocation?=?servletContext.getInitParameter(CONTEXT_PARAM_OSGI_PLUGINS_LOCATION);
14?????????????if?(pluginLocation?==?null)?pluginLocation?=?DEFAULT_OSGI_PLUGINS_LOCATION;
15?????????????else?if?(!pluginLocation.startsWith("/"))?pluginLocation?=?"/".concat(pluginLocation);
16?
17?????????????//?安装bundle
18?????????????File?bundleRoot?=?new?File(servletContext.getRealPath(pluginLocation));
19?????????????if?(bundleRoot.isDirectory())?{
20?????????????????if?(logger.isInfoEnabled())?logger.info("Load?Framework?bundles?from:?"?+?pluginLocation);
21?
22?????????????????//?StartLevel?Service,用于设置bundle的startlevel
23?????????????????ServiceReference?slRef?=?bundleContext.getServiceReference(StartLevel.class.getName());
24?????????????????StartLevel?sl?=?slRef?==?null???null?:?(StartLevel)?bundleContext.getService(slRef);
25?????????????????//?设置新bundle的初始startlevel为系统配置项:org.osgi.framework.startlevel.beginning的值
26?????????????????String?bsl?=?bundleContext.getProperty("org.osgi.framework.startlevel.beginning");
27?????????????????if?(bsl?!=?null?&&?isInteger(bsl))?sl.setInitialBundleStartLevel(Integer.parseInt(bsl));
28?
29?????????????????//?安装bundle并设置相应的start?level
30?????????????????File?slRoot?=?new?File(bundleRoot,?"start");
31?????????????????if?(slRoot.isDirectory())?{
32?????????????????????File?slDirs[]?=?slRoot.listFiles(new?FileFilter()?{
33?????????????????????????public?boolean?accept(File?file)?{
34?????????????????????????????return?file.isDirectory()?&&?isInteger(file.getName());
35?????????????????????????}
36?????????????????????});
37?
38?????????????????????for?(File?slDir?:?slDirs)?{
39?????????????????????????installBundles(bundleContext,?slDir,?sl,?Integer.parseInt(slDir.getName()));
40?????????????????????}
41?????????????????}
42?
43?????????????????//?安装直属目录下面的bundle
44?????????????????installBundles(bundleContext,?bundleRoot,?sl,?0);
45?
46?????????????????for?(Bundle?bundle?:?bundleContext.getBundles())?{
47?????????????????????if?(bundle.getState()?==?Bundle.INSTALLED?||?bundle.getState()?==?Bundle.RESOLVED)?{
48?????????????????????????if?(bundle.getHeaders().get(Constants.BUNDLE_ACTIVATOR)?!=?null?||?bundle.getHeaders().get("Service-Component")?!=?null)?{
49?????????????????????????????try?{
50?????????????????????????????????bundle.start(Bundle.START_ACTIVATION_POLICY);
51?????????????????????????????????if?(logger.isInfoEnabled())?logger.info("Start?bundle:?"?+?bundle);
52?????????????????????????????}?catch?(Throwable?e)?{
53?????????????????????????????????if?(logger.isWarnEnabled())?logger.warn("Start?bundle?error:?"?+?bundle,?e);
54?????????????????????????????}
55?????????????????????????}
56?????????????????????}
57?????????????????}
58?
59?????????????????if?(slRef?!=?null)?bundleContext.ungetService(slRef);
60?????????????}
61?
62?????????????new?FileWriter(file).close();
63?????????????if?(logger.isInfoEnabled())?logger.info("Framework?inited.");
64?????????}
65?????}

?

读书人网 >操作系统

热点推荐