Equinox OSGI平台中集成Tuscany SCA容器(转载)

Tuscany与OSGI集成
本文介绍如何在Equinox中集成Tuscany,通过创建OsgiSCADomain及实现热部署能力,解决不同Contribution使用不同ClassLoader的问题,并提供运行时刻调用示例。
本文介绍如何在Equinox中集成Tuscany,Tuscany容器作为OSGI环境中的一个Bundle存在。同时一个Contribution也对应为一个Bundle,此种方式使Tuscany的Contribution具有了热部署和动态修改替换的能力。这也是Tuscany邮件组中目前正在讨论的问题。
修改Tuscany:
1. 创建 OsgiSCADomain, 继承自 SCADomain. OsgiSCADoamin 参照 DefaultSCADomain, 做了少许改动。
a) DefaultSCADomain 是在构造方法中加载 Contribution 的资源。修改 OsgiSCADomain ,添加 initContribution(Bundle bundle) 方法。代码片断如下:
ContributionService contributionService = runtime .getContributionService();
URL contributionURL;
try {
contributionURL = getContributionLocation(bundle);
if (contributionURL != null ) {
// Make sure the URL is correctly encoded (for example, escape the space characters)
contributionURL = contributionURL.toURI().toURL();
}
} catch (Exception e) {
throw new ServiceRuntimeException(e);
}
以上代码,获取Bundle的META-INF目录下sca-contribution.xml的URL,并通过 ContributionService contribute 加载 sca-contribution.xml 及其他资源文件。在实验代码中仅考虑 .composite 文件。
b) 替换org.apache.tuscany.sca.host.embedded. SCADomain扩展点实现为 org.apache.tuscany.sca.host.embedded.impl.OsgiSCADomain
2. 另一个主要问题是要考虑 ClassLoader 的问题。在 OSGI 中,不同的 Contribution 使用不同的 ClassLoader 。因此在 org.eclipse.equinox.tuscany 插件中对构件进行装配时,无法加载构件描述文件的的类。
a) 新建 BundleProxyClassLoader Bundle 默认不对外提供 ClassLoader ,因此创建一个代理 ProxyClassLoader BundleProxyClassLoader 的代码参见: http://wiki.eclipse.org/index.php/BundleProxyClassLoader_recip
3. BundleContext Tuscany 中传递的问题。如果要将 BundleContext 直接在 Tuscany 中传递,需要修改大量已有代码,代价较大。采用折中方法。修改 Contribution 接口,添加 setBundle getBundle 方法。
Bundle getBundle();
void setBundle(Bundle bundle);
4. 修改 ContributionServiceImpl,
a) 添加 addContribution 方法,在此方法中将 Bundle 设置给 Contribution
b) 添加 readContributionMetadata 方法 。在此方法中将 BundleProxyClassLoader 传给 ContributionMetadataDocumentProcessor ,用户加载 sca-contribution.xml 文件。
private Contribution readContributionMetadata(Bundle bundle) throws ContributionException{
Contribution contributionMetadata = null ;
ClassLoader cl = new BundleProxyClassLoader(bundle);
ContributionMetadataDocumentProcessor metadataDocumentProcessor =
new ContributionMetadataDocumentProcessor(cl, staxProcessor, assemblyFactory, contributionFactory,
xmlFactory);
contributionMetadata = contributionFactory.createContribution();
try {
metadataDocumentProcessor.read(contributionMetadata);
} catch (XMLStreamException e) {
throw new InvalidContributionMetadataException( "Invalid contribution metadata for contribution." );
}
return contributionMetadata;
}
5. 修改 ClassReferenceModelResolver ,使用 Contribution Bundle ClassLoader 来加载 Java Class
public ClassReferenceModelResolver(Contribution contribution, ModelFactoryExtensionPoint modelFactories) {
this . contribution = contribution;
// FIXME The classloader should be passed in
// this.classLoader = new WeakReference (Thread.currentThread().getContextClassLoader());
this . classLoader = new WeakReference ( new BundleProxyClassLoader(contribution.getBundle()));
try {
Class osgiResolverClass =
Class.forName( "org.apache.tuscany.sca.contribution.osgi.impl.OSGiClassReferenceModelResolver" );
if (osgiResolverClass != null ) {
Constructor constructor =
osgiResolverClass.getConstructor(Contribution. class , ModelFactoryExtensionPoint. class );
this . osgiResolver = (ModelResolver)constructor.newInstance(contribution, modelFactories);
}
} catch (Exception e) {
}
}
创建 org.apache.tuscany org.eclipse.equinox.tuscany 两个插件
org.apache.tuscany 插件包含了 Tuscany 运行时刻类库文件。
org.eclipse.equinox.tuscany 则负责在 OSGI 容器中启动 SCA 容器,并遍历 ACTIVE Bundle ,加载 Bundle 中的 SCA 资源。
SCAActivator 代码如下:
public class SCAActivator implements BundleActivator, BundleTrackerCustomizer, SynchronousBundleListener {
private SCADomain scaDomain ;
private BundleTracker bundleTracker ;
private static SCAActivator activator ;
public SCAActivator() {
activator = this ;
}
public static SCAActivator getDefault() {
return activator ;
}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext bundleContext) throws Exception {
scaDomain = SCADomain.newInstance();
bundleContext.registerService(SCADomain. class .getName(), scaDomain , null );
bundleTracker = new BundleTracker(bundleContext, Bundle. ACTIVE , this );
bundleContext.addBundleListener( this ); //track UNRESOLVED events
bundleTracker .open();
}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
scaDomain .close();
}
public void bundleChanged(BundleEvent event) {
if (event.getType() == BundleEvent. UNRESOLVED ) {
// TODO
}
else if (event.getType() == BundleEvent. RESOLVED ) {
// TODO
}
}
public Object addingBundle(Bundle bundle) {
if ( scaDomain instanceof OsgiSCADomain) {
OsgiSCADomain domain = (OsgiSCADomain) scaDomain ;
domain.initContribution(bundle);
}
return null ;
}
public void modifiedBundle(Bundle bundle, Object object) {
// TODO
}
public void removedBundle(Bundle bundle, Object object) {
// TODO
}
public SCADomain getScaDomain() {
return scaDomain ;
}
}
运行时刻调用
Servlet 中可以使用如下方式调用:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException{
response.setContentType( "text/html" );
ServletOutputStream output=response.getOutputStream();
SCADomain scaDomain = SCAActivator.getDefault().getScaDomain();
CalculatorService calculatorService =
scaDomain.getService(CalculatorService. class , "CalculatorServiceComponent" );
// Calculate
output.println( "3 + 2=" + calculatorService.add(3, 2) + "
"
);
output.println( "3 - 2=" + calculatorService.subtract(3, 2) + "
"
);
output.println( "3 * 2=" + calculatorService.multiply(3, 2) + "
"
);
output.println( "3 / 2=" + calculatorService.divide(3, 2) + "
"
);
}

 

了解更多内容,请登录http://gocom.primeton.com/blog3086_14.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值