根據插件ID(Namespace)和路徑找出視圖源文件
|
主要任務,根據插件
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%
。
不得窺道門,不得悟佛門,不得入窄門,實乃破門。