破门点滴(Java技术版)

在日常学习和工作中记录

  BlogJava :: 首页 ::  :: 聚合  :: 管理
  15 Posts :: 7 Stories :: 36 Comments :: 0 Trackbacks
根据插件ID(Namespace)和路径找出视图源文件
2004-12-23 19:58:14

主要任务,根据插件 ID Namespace )和路径找出视图源文件。

基本上完成文件的读取:

              Bundle nsbundle = Platform.getBundle(pluginId);  // 获取 bundle( 插件 )

              URL url = nsbundle.getEntry( target );             //    获取资源路径

              url = Platform.asLocalURL( url );             // 返回物理文件路径 URL

 

以上参数说明:

pluginId 插件 ID                     例如: org.softme.triones.hello

              target   资源文件相对路径    例如: templates/index.vm

 

结果范例:

file:/D:/netshop/triones/plugins/org.softme.triones.hello_0.0.1/templates/index. vm

其中: file:/D:/netshop/triones/ Triones 系统安装路径。

第二步:创建 netshop web 应用

问题出现:

2004-12-23 19:46:38 StandardContext[/netshop]Exception sending context initialized event to listener instance of class org.softme.triones.TrionesContextListener

java.lang.Error: factory already defined

         at java.net.URL.setURLStreamHandlerFactory(Unknown Source)

         at org.eclipse.osgi.framework.internal.core.Framework.initialize(Framework.java:154)

         at org.eclipse.osgi.framework.internal.core.Framework.<init>(Framework.java:95)

         at org.eclipse.osgi.framework.internal.core.OSGi.createFramework(OSGi.java:90)

         at org.eclipse.osgi.framework.internal.core.OSGi.<init>(OSGi.java:31)

         at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:215)

         at org.softme.triones.launcher.TrionesStarter.basicRun(TrionesStarter.java:1063)

         at org.softme.triones.launcher.TrionesStarter.launch(TrionesStarter.java:672)

         at org.softme.triones.TrionesContextListener.contextInitialized(TrionesContextListener.java:51)

 

原因:在一个虚拟机中,该方法只能被调用一次。

参考:

java.net.URL 是各种协议,包括已知和未知的入口,通过 URL.setURLStreamHandlerFactory(URLStreamHandlerFactory handlerFactory) 方法可以设置新的协议处理器的工厂类的实例,在一个虚拟机中,该方法只能被调用一次。除了利用这种方式向系统注册外,还可以通过设置系统属性 java.handler.protol.pkg 或者 sun.net.www.protocol 来实现注册。系统会按照 setURLStreamHandlerFactory() java.handler.protol.pkg sun.net.www.protocol 三种方法,从高优先级到低优先级的进行搜索特定协议对应的处理器。 java.handler.protol.pkg 对应的值的构成是用 | 分隔的各个协议处理器的类,格式为 ..Handler | ..Handler | ... sun.net.www.protocol 的设置方式是 sun.net.www.protocol..Handler ,这个 sun.net.www.protocol..Handler 会被追加到第二种方式得到的值后面,然后逐个加载。注意,设置属性的时候,只需要写上 handler package protocol 之前的部分,例如对于 myProtocol 协议,则, myProtocol 的处理器的类命名格式为 myPackage.myProtocol.Handler ,或者是 sun.net.www.protocol.myProtocol.Handler, 设置属性的时候,只需要写上 myPackage 即可,剩下的部分, URL 类会自动处理的。

 

看样子必须改回用反射来初始化框架了。

改回成反射调用的模式依然出现以上错误,看来可能是与 tomcat 发生了冲突,先下 tomcat 的源码等明天查查看。

果然,发现 Tomcat 已经调用了此方法: org.apache.catalina.loader.WebappLoader

// Register a stream handler factory for the JNDI protocol

        URLStreamHandlerFactory streamHandlerFactory =

            new DirContextURLStreamHandlerFactory();

        if (first) {

            first = false;

            try {

                URL.setURLStreamHandlerFactory(streamHandlerFactory);

            } catch (Exception e) {

                // Log and continue anyway, this is not critical

                log.error("Error registering jndi stream handler", e);

            } catch (Throwable t) {

                // This is likely a dual registration

                log.info("Dual registration of jndi stream handler: "

                         + t.getMessage());

            }

        }

 

尝试将 Eclipse OSGi Framework 对象进行更改:

org.eclipse.osgi.framework.internal.core.Framework

initialize() 方法,跳过二次注册 setURLStreamHandlerFactory 的错误:

/* install URLStreamHandlerFactory */

                   try{

                            URL.setURLStreamHandlerFactory(new

 StreamHandlerFactory(systemBundle.context, adaptor));

                   } catch (Throwable t) {

                            // This is likely a dual registration

                            if (Debug.DEBUG && Debug.DEBUG_GENERAL)

                                     System.out.println("Dual registration of jndi stream handler: "

                     + t.getMessage());

                   }

 

运行出现错误, Eclipse 无法加载插件:

j ava.net.MalformedURLException: unknown protocol: reference

         at java.net.URL.<init>(Unknown Source)

         at org.eclipse.core.runtime.adaptor.EclipseStarter.searchForBundle(EclipseStarter.java:366)

         at org.eclipse.core.runtime.adaptor.EclipseStarter.getInitialBundles(EclipseStarter.java:466)

         at org.eclipse.core.runtime.adaptor.EclipseStarter.loadBasicBundles(EclipseStarter.java:418)

         at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:222)

         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

         at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

         at java.lang.reflect.Method.invoke(Unknown Source)

         at org.softme.triones.launcher.TrionesInvokeStarter.basicRun(TrionesInvokeStarter.java:342)

         at org.softme.triones.launcher.TrionesInvokeStarter.launch(TrionesInvokeStarter.java:899)

         at org.softme.triones.TrionesContextListener.

 

只能先研究以上参考中更新 protocol 注册的第二种或第三种方法了。

Eclipse 采用了 URLStreamHandlerProxy 的代理机制来处理,实际的服务定义在 OSGi service org.osgi.service.url. URLStreamHandlerService 实现中。解决了 Java JVM URLStreamHandler 进行缓存而不能支持动态加载的问题。

因此,看来不能够去掉 Eclipse 中对 URL. setURLStreamHandlerFactory 的调用。

 

解决办法呢? ………………………………………….????????????????????????

 

讨论:

方案一:在 JVM URL 协议注册机制中寻求其他入口点。

困难度 100 %: JVM 协议注册的第二种和第三种方法都无法支持 Eclipse 的入口。

因为 Eclipse 通过对 Factory 的扩展支持了协议处理器( Handler )的动态加载,以及嵌入了 OSGi 服务机制,所以无法采取其他入口实现 Eclipse 加载机制。

方案二:修改 Eclipse 框架,避开 setURLStreamHandlerFactory 的调用。

困难度 100% :原因同上。

方案三:修改 JRE java.net.URL 对象,允许多 factory 设置。

困难度 10%



不得窥道门,不得悟佛门,不得入窄门,实乃破门。
posted on 2006-03-27 10:29 破门 阅读(790) 评论(0)  编辑  收藏 所属分类: Triones

只有注册用户登录后才能发表评论。


网站导航: