2009年2月24日

Java WebStart + Linux + URLStreamHandler = MalformedURLException

又發現了一個Java的陷阱,讓我手頭上的一個Java專案,在porting到Linux環境的過程一直很不順利。

今天仗著不找到solution不罷休的的決心,把jEdit的原始碼拿出來一隻隻慢慢啃,最後連JDK的原始碼都找出來翻山倒海一番,才發現只需要加幾行程式碼就能解決。

我開發的軟體是這麼樣運作:
  • 使用JNLP配置Java WebStart
  • 搭配jEdit的jar檔啟動編輯器
  • 自製兩項jedit的plug-ins
在jEdit啟動後,會找尋jars目錄下的jar檔案,檢查是否為plug-in,如果是則會自動載入。

好死不死,在討人厭的 Windows + JDK6 一切都正常;而在迷人的 Linux + JDK6 卻發生 MalformedURLException 的意外。

經過逐步的檢查發現,原來是 jEdit 自己定義了一個新的URL格式「jeditresource:/檔案路徑」。

一般來說,Java註冊新的URL格式,會使用如下的Property「java.protocol.handler.pkgs」定義,這幾行是jEdit.java包含的程式碼。

System.getProperties().put("java.protocol.handler.pkgs",
"org.gjt.sp.jedit.proto|" +
System.getProperty("java.protocol.handler.pkgs",""));

但不知道、不知道、不知道為什麼,在Linux下的Java VM,似乎根本不理會這些定義,根據挖掘JDK原始碼URL.java的了解後,我認為跟Security機制有關,但是嘗試一些Security Policy的設定後,還是~~無效。

只好把希望放在另一種方法,也就是 URL.setURLStreamHandlerFactory 這個method,它可以讓我們自己定義Factory Implementation,將protocol對應到處理它的Handler Implementation。

以jEdit來說,需要的程式碼摘要如下:

class JEditURLStreamHandlerFactory implements URLStreamHandlerFactory {
public URLStreamHandler createURLStreamHandler(String protocol) {
if (protocol.equals("jeditresource")) {
return new org.gjt.sp.jedit.proto.jeditresource.Handler();
}
return null;
}
}

URLStreamHandlerFactory factory = new JEditURLStreamHandlerFactory();
URL.setURLStreamHandlerFactory(factory);

雖然暫時解決啟動的問題,但遇上Java惱人的Security機制,不知道何時還會在其他地方踩到地雷!

再次體驗Java的「Write Once, Debug Everywhere」不是喊假的。

沒有留言:

張貼留言

lyhcode by lyhcode
歡迎轉載,請務必註明出處!