Add C:\Program Files (x86)\LibreOffice 4\program\classes to classpath.
Java で LibreOffice を操作しようとして最初で躓きました。。。が、どうにか解決しました。
前提知識的なところとして、大雑把には次のような手続きで処理します。
- LibreOffice をサーバとして起動
- LibreOffice に接続してリモート(サーバ側の)コンテキスト(オブジェクト)を取得
- リモートコンテキストを使って目的の操作を行う
LibreOffice を起動して接続して…という処理を自前で書いてもいいのですが、Bootstrap.bootstrap を使うと LibreOffice の起動からリモートコンテキストの取得までをよしなにやってくれます。
やってくれるはずなのですが上記のエラーが出ます。
"no office executable found!" の発生箇所。
soffice.exe(Windows の場合)のフルパスを取得しようとして失敗しています。
File fOffice = NativeLibraryLoader.getResource(com/sun/star/comp/helper/Bootstrap.getClassLoader(), sOffice); if(fOffice == null) throw new BootstrapException("no office executable found!");
さらに NativeLibraryLoader.getResource を見てみると次のようなことをやっていて、要するに、使っているライブラリのパスをクラスローダから取得し、そのライブラリのあるディレクトリ、またはその親ディレクトリに soffice.exe があるかを調べています。
java.net.URL urls[] = ((URLClassLoader)loader).getURLs(); for(int i = 0; i < urls.length; i++) { // file:///C:/path/to/file.ext のようなURLをパスに変換 File path = UrlToFileMapper.mapUrlToFile(urls[i]); if(path == null) continue; // path の親ディレクトリ File dir = path.isDirectory() ? path : path.getParentFile(); if(dir == null) continue; path = new File(dir, name); if(path.exists()) // soffice.exe が存在していればOK return path; // path の親ディレクトリの親ディレクトリ dir = dir.getParentFile(); if(dir == null) continue; path = new File(dir, name); if(path.exists()) // soffice.exe が存在していればOK return path; }
C:\Program Files (x86)\LibreOffice 4\program\classes\ などの場所に置いてあるライブラリを使うことを前提と作られているため、この jar を別のところに置き、それをクラスパスに追加して使おうとすると soffice.exe が見つけられず上記のエラーが発生したということのようです。
なので、対処としては
- C:\Program Files (x86)\LibreOffice 4\program\classes\unoil.jar などをクラスパスに追加する(ファイルでなくディレクトリの追加でも可)か、または
- soffice.exe の場所を明示的に指定する(Bootstrap.bootstrap を使わず起動〜接続処理を自前で書く)。
- または、自前で書くのがめんどくさい場合は Java solution "no office executable found!" (View topic) • Apache OpenOffice Community Forum に置いてある bootstrapconnector.jar を使う
あたりになると思います。
検証用テストコード
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertThat; import org.junit.Test; import com.sun.star.comp.helper.Bootstrap; // juh.jar import com.sun.star.uno.XComponentContext; // ridl.jar public class BootstrapTest { @Test public void test() throws Exception{ ClassLoader loader = com.sun.star.comp.helper.Bootstrap.class.getClassLoader(); java.net.URL urls[] = ((java.net.URLClassLoader)loader).getURLs(); for(java.net.URL url : urls){ System.err.println(url); } XComponentContext remoteContext = Bootstrap.bootstrap(); assertThat(remoteContext, is(notNullValue())); } }
環境
- Windows 7 Home Premium SP1 64bit
- LibreOffice 4.2.5(SDK も同じ)
- LibreOffice_4.2.5_Win_x86.msi
- LibreOffice_4.2.5_Win_x86_sdk.msi
- Java 7