Eclipseプラグイン開発の感想

2010年後半に、拙作のHTTPデバッグ用ソフトウェアであるDoorman@JUMPERZ.NETをEclipseプラグインに移植した(詳しくはこちら)。これは筆者にとって初めてのEclipseプラグイン開発であった。そのとき感じたことを簡単にこのエントリにまとめてみたい。

Doorman@JUMPERZ.NETというソフトウェアは、2007年に筆者が拙著「ウェブアプリケーションセキュリティ」執筆の際に作成したものである。ローカルマシンで動作するGUIのHTTPプロキシサーバであり、ウェブブラウザとウェブサーバの間に位置し、そこを通り過ぎるHTTPリクエストとレスポンスをユーザが自由に見たり書き換えたりすることで、ウェブ開発の際のデバッガとして使用することができる。筆者はウェブアプリケーション開発者でもあるので、自分自身の開発の際などにも便利に使っている。

2007年のリリース時、このソフトウェアはSWTという技術をプラットフォームとして採用した。SWTはStandard Widget Toolkitの略で、JavaでのGUIアプリケーションの際に利用できるオープンソースのライブラリの1つである。SWTはJava標準のGUIライブラリであるSwingとは異なり、クロスプラットフォーム開発(WindowsやMacOS,Linux)が可能であるにもかかわらず、動作時のルック&フィールはネイティブアプリケーションのそれとまったく同じとなる(JNIを通じて下層でネイティブコードを呼び出している)。筆者は個人的にSwingのルック&フィールがまったく好きになれず、JavaでGUIアプリケーションを開発したいがSwingはあり得ないと考えていたため、SWTはまさに福音であった。SWTは元々IBMが強力なIDEを開発するための基礎として開発したものであり、その血脈は現在もEclipseに力強く受け継がれている。SWTをオープンソース化してくれたIBMにここで感謝の意を表しておきたい。

開発開始当初はEclipseのように柔軟なGUIアプリケーションにしたいと考えていたので、Eclipse RCP(Rich Client Platform)として開発を開始した。しかしEclipseフレームワークが想像していたよりもかなり大規模であり、またRCPの配布形式が当時の筆者にとってはわかりにくいものに見えたため、少し勉強してみたものの諦めたという経緯がある。とにかく早く動くものを開発したかったため、結局GUIのライブラリとしてのSWTのみを使用し、アプリケーションのベースとなる部分は単にシンプルなJavaのアプリケーションとして開発したのである。このような経緯があったため、開発がとりあえず完了してからも、心の中ではいつかEclipseのプラグインかRCPアプリケーションにしてみたいと考えていた。

2010年に筆者は35回目の誕生日を迎え、いわゆるプログラマーの定年に達することとなった。ちょうどプログラマーとして独立してから10年が経過したこともあり、個人的なキャリアの振り返りを行っていたタイミングでもあった。二ヶ月ほどゆっくり時間をかけ、これから自分がどのような技術にどんな風に触れていくべきか考えをまとめた。そして出した結論は、「今まで手を出していなかった様々なプラットフォームにも、浅く広く触れていこう」というものである。それまでの筆者はどちらかというとかなり限定した狭い範囲(Javaでの開発やHTTP、セキュリティなどの分野)を深く掘り下げるのが好きであり、反面、手を出さないジャンルには徹底的に手を出していなかった。ちょうどKindleやiPadなどの新しい形のデバイスを手にすることで新しい刺激を受けていたこともあり、開発者としての自分ももっと積極的に新しいジャンルに踏み出していこうと考えたのである。

そこで、とりあえずは自分の技術の拠点であるJavaを中心に、今まで触っていなかった方面に手を伸ばしてみることにした。10年ぶりに新しいプログラミング言語の勉強を始めることにし、その対象としてClojureを選択した。ここで勉強の対象をRubyやPythonにしなかった理由は、ClojureがJavaとはとても異なる性質を持っているからだ。RubyやPythonは所詮C言語の流れをくんだ王道的なOOPの言語であり、C++、JavaScript、Perlを少し、そしてJavaを十分に経験している筆者にとってはそれほど違和感を感じる言語ではない。せっかく新しい言語を覚えるのであれば、今までに経験した言語とはまったく性質の異なるものにしようと考えた。Clojureは言語としてJavaとはまったく異なっている反面、JVM上で動作するという非常に大きなアドバンテージがある。安定性、速度、マルチコアへの対応、クロスプラットフォーム性、そして既存のJavaライブラリ(筆者は10年間かけてそれなりに自分で使いやすいと思うライブラリを構築してしまっている)を活かせることなど、実案件で使えそうな条件も整っている。また「ハッカーと画家」を読んだ経験と、筆者がベッチーこと苫米地氏のファンであることから、LISPをいつか勉強していたいと思っていたことなどもClojureへのモチベーションを後押ししてくれた。Clojureは(かなり独自色はあるが)JVM上で動作するLISPである。

その後Clojureの学習は順調に進めることができ、今ではデータ処理などを行う際の書き捨てツールなどはすべてClojureで書くようになった。「新しい技術に積極的に手を出していく」という目標に対する第一歩が順調に踏み出せたことでうまくモチベーションが回るようになり、次は以前からやりたいと思っていたEclipseプラグイン(あるいはRCP)に手を出すことにした。

Eclipseプラットフォームはこの数年の間にIDE環境として不動の地位を築き上げた(既にIDE市場の製品の70%はEclipseベースであるという記述も見たことがある)。筆者は2002年頃からEclipseを使っているので、そこそこ古株の利用者である。当時はPCのパワーが現在よりかなり劣っていたため、Eclipseは起動するだけで1分かかるようなこともあり、非常に重いという評判だった。しかしEclipseでのJava開発ではエディタでの編集やコードの保存に合わせてコンパイルがさくさくと進み、C++での開発のように、アプリケーション全体のコンパイルに時間がかかるようなことがなかった。そのため、筆者がそれ以前にやっていたBorland C++ Builderでの開発よりも、よほど軽い感触で開発できるという印象を持っていた。

Eclipseは初期はJava開発環境として知られていたが、少しずつ着実に汎用IDEプラットフォームとして成長していたようだ。数十から数百といった数のモジュールを破綻することなく扱うためにOSGiをベースとして選択し、プラグインベースで拡張可能なプラットフォームとして独自の路線を歩み始めた。その結果、筆者が出会っただけでもAdobeのFlex、AptanaのAptana Studio、(元)BorlandのJBuilderなどのIDEがEclipseをベースとして開発されるようになった。このことからEclipseプラットフォームは今後も長く安定して提供されるだろうと確信することができた。10年間ただ利用するだけだったEclipseプラットフォームだが、せっかくJavaプログラマーであるので、プラグインによって自分の好きなように機能を拡張できるようになればそれはきっと素晴らしいことになるだろう。そのような想いで、2007年に一度は挫折したEclipseプラットフォームでの開発に再びチャレンジすることにした。

移植前のDoorman@JUMPERZ.NETはスタンドアローンのJavaアプリケーションであり、GUIライブラリとしてSWTを使用している形となる。そのためロードされるクラスは最低限アプリケーションの動作に必要なものだけとなっており、起動は2〜5秒程度で済む(それでもJavaアプリケーションなので、ネイティブのバイナリで起動するアプリケーションよりよほど遅いが)。また、必要となるファイルもjarファイルとswtのライブラリのみで、数MBだけである。しかしEclipseプラグインにしてしまうと、起動するためには当然Eclipseを起動する必要があり、これは遅いマシンでは(2011年現在でも)20秒近くかかる可能性がある。また、使うためにはEclipse本体のパッケージをインストールする必要があり、ファイルの数もサイズも膨大なものとなる。これらのポイントはEclipseプラグインにすることのデメリットだと言える。一方でメリットとしてはクロスプラットフォームでのインストールの容易さがあり、またViewやPerspectiveといった優れたインターフェースを使えるという点がある(これらの点については後述)。

筆者はAmazonが提供するKindleのサービスが非常に気に入っており、Eclipseプラグインの開発やOSGi、RCP関連などの洋書を電子書籍として購入し、基本的に開発に必要となる知識を英語(洋書の電子書籍と英語のウェブサイト)で得ることを決めた。このようなルールを決めてしまえば、いやでも英語力が高まることになる。また、元々これらのジャンルは日本ではそれほど人気がなく、日本語での情報が不足しているという面もあった。当初は慣れない英語の電子書籍ということで疲れることもあったが、次第に順応することができた。その省スペース性や可搬性の高さなど、電子書籍、そしてKindleの魅力に徐々にハマっていくことになった。

Eclipseプラットフォームの魅力はなんといってもその柔軟なウィンドウ(View)配置能力である。それぞれのウィンドウはViewと呼ばれ、マウスによって自由に(本当に自由に)各View間のレイアウトを変更することができる。複数のViewを同じ位置に配置すれば上部のタブで管理できるようになるため、画面が狭い場合でも工夫して作業しやすいレイアウトを作成することができる。複数のViewの配置によって決定されるアプリケーション全体のレイアウトはPerspectiveと呼ばれる概念で捉えられ、Perspectiveに名前を付けて保存しておくことができる。そのため開発時やデバッグ時などに違うレイアウトを使いたい場合でもワンタッチでアプリケーション全体のレイアウトを変更することができる。この15年の間にさまざまなGUI環境に触れてきたが、Eclipseの、このViewとPerspectiveからなる仕組みはかなり完璧に近いGUIインターフェースであると考えている。

Doorman@JUMPERZ.NETの移植を開始する際にまず迷ったのが、これをEclipseプラグインにするか、あるいは独立したRCPアプリケーションとするかという点である。もともと独立したアプリケーションであったのでRCPアプリケーションにするつもりだったのだが、最終的にはEclipseプラグインとして開発することに決めた。これは次のような理由からである。

  • プラグインは単体のjarファイルにまとめることができるため、配布やインストール・アンインストールの方法がシンプルでわかりやすい
  • Eclipseがインストールされていれば、ファイルをコピーしてEclipseを再起動するだけでインストールができる
  • Windows/MacOS/Linux/32bit/64bit等の環境を考慮せずにjarファイルのみ配布できる(各環境に合わせたEclipseのパッケージはeclipse.orgで配布されており、誰でも利用可能である)
  • RCPの配布がやや複雑でわかりにくい
  • 元々はRCPという形態は存在せず、プラグイン開発が元祖である
  • RCPではなくプラグインとして開発することを決め、Kindleで購入したAddison-Wesleyの「Eclipse Plug-ins Third Edition」「OSGi and Equinox」などを読むところからスタートした。長らくEclipseを使っていたが、それがOSGiという基盤を持っていたことはこの段階まで知らなかった。OSGiではBundleという刺激的な概念が登場する。単なるjarファイルやパッケージ名によるモジュール化だけではエンタープライズ級の巨大なアプリケーション開発には不十分であると考え、自らが外部に提供する機能や依存する他のBundle、あるいはそのバージョンなどを明記するというアプローチである。以下に例を示す。

    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: DoormanHook
    Bundle-SymbolicName: net.jumperz.app.MDoormanHook;singleton:=true
    Bundle-Version: 1.0.0.qualifier
    Bundle-Activator: net.jumperz.app.MDoormanHook.Activator
    Bundle-Vendor: JUMPERZ.NET
    Require-Bundle: org.eclipse.ui,
     org.eclipse.core.runtime,
     net.jumperz.app.MDoorman;bundle-version="1.0.0"
    Bundle-RequiredExecutionEnvironment: J2SE-1.5
    Bundle-ActivationPolicy: lazy
    Export-Package: net.jumperz.app.MDoormanHook,
     net.jumperz.app.MDoormanHook.view
    Bundle-ClassPath: .,
     lib/clojure.jar

    これはDoorman@JUMPERZ.NETの移植後に作成された2つのプラグインのうち、片方のMANIFEST.MFファイルの中身である。自らのBundleの名前(Bundle-Name)やバージョン(Bundle-Version)、依存する外部のBundle(Require-Bundle)、実行時に最低限必要となるJavaのバージョン(Bundle-RequiredExecutionEnvironment)などが記述されている。これらのメタ情報がコンパイルされたクラスファイル群と一緒になっていることで、単なるパッケージやjarファイルによるアーカイブよりも明確に、Javaコードの管理されたモジュール化が実現されることになる。Eclipseプラグインはどれもこのようなメタ情報を持っている。Eclipseがインストールされているディレクトリの下のplugins/の中から興味があるプラグインを探し、メタ情報を見てみるだけでもなかなか興味深いかもしれない。

    また、プラグイン(=Bundle)がどのようなViewを持っているか、等のプラグイン内部のメタ情報もXMLファイルの形で管理されており、こちらもコードとは別に明確に宣言されている。以下に例を示す。

    <?xml version="1.0" encoding="UTF-8"?>
    <?eclipse version="3.4"?>
    <plugin>
       <extension
             point="org.eclipse.ui.views">
          <view
                category="Doorman.category1"
                class="net.jumperz.app.MDoormanHook.view.MHookView"
                icon="src/net/jumperz/app/MDoormanHook/resource/doorman.gif"
                id="net.jumperz.app.MDoormanHook.view.MHookView"
                name="Hook"
                restorable="true">
          </view>
       </extension>
       <extension
             point="net.jumperz.app.MDoorman.Hook">
          <client
                class="net.jumperz.app.MDoormanHook.MHookFactoryImpl">
          </client>
       </extension>
    </plugin>

    これらのメタ情報について、開発者は直接ファイルを編集する必要はない。プラグイン開発の際に必ず使用するであろうGUIツールであるEclipseプラグインエディタを使用することで、自動的にXMLファイルの中身が編集されていく。プラグインエディタの使い方は独自の作法が多く、開発者はまずこれを覚えないと開発を進めることができない。そのため初めての場合はチュートリアル的な参考書などが必須となるだろう。基本的にはプラグインエディタはわかりやすいツールだが、たまにプラグインエディタが何をやっているのか不明な場合などもある。このような場合、プラグインエディタによって変更が自動的に反映されたXMLファイル側を直接読むことで、その意味が明確になる場合などもある。

    このようにメタ情報がXMLファイル等で管理される開発では、Javaのクラス名が要素として重要なものとして扱われることが多い。これはある意味仕方がないことではあるが、メインとなるクラスだけではなく、Viewなどについてもすべてクラス名がXMLファイル中に記述されるようになっている。クラス名そのものがアプリケーションにおいて重要な意味を持ってしまうというのは、筆者にとっては少し抵抗があることだったが、これも作法だと思って受け入れるしかないだろう。クラス名そのものが意味を持ってしまうことは、ClojureのようにJVM上で動作する別の言語を使ってEclipseプラグインを開発しようとする場合に邪魔になることが考えられる(わざわざJavaのクラスを生成しなければならないため)。筆者はDoorman@JUMPERZ.NETの移植に際してClojureでの開発(移植)にチャレンジしてみたかったのだが、Eclipseプラグイン開発がプラグインエディタというツールやJavaのクラスファイル名への依存が大きかったため、これは諦めることとなった。ただし、これは手間をかければ不可能ではないかもしれないので、興味がある人にはぜひチャレンジして欲しい。

    Eclipseプラットフォームにおける開発において、とても良い印象をうけたのは、Preference(設定)関係である。Eclipseでは設定情報をPreferenceダイアログで管理できる。設定情報にはツリー構造を持たせることが可能であり、項目の分類を適切にすることで使いやすいインターフェースを実現できる。また、項目数が多くなってもテキスト入力欄から気軽に検索して目的の設定を見つけることができるため、多数のプラグインをインストールした後でも非常に使いやすいものになっている。Eclipseプラグイン開発では、このPreferenceまわりについての作法に従うことで、非常に簡潔に、使いやすい設定ダイアログを開発することができる。データのセーブ・ロードなどをプラットフォーム任せにすることができるため、殆どコードを記述する必要がない。この部分の出来の良さにはとても感銘を受けた。

    しかし一方で、メニューに関する作法には疑問を持った。メニューというのはアプリケーションの使用状況に合わせて表示する項目を変えたり、あるいはEnable/Disableを切り替えたりすることが多い。この切り替えのルーチンは、結局の所コードを書くことで管理するのがプログラマーにとってはもっともわかりやすいと感じる。プラグインエディタにはGUIベースでこれをやろうとする仕組みが存在しているのだが、これがどうにも使いにくい。しばらく格闘したのだが、結局諦めて自分のコードで片付けてしまった。このように作法に従うと楽な場面もあり、一方で作法が難しすぎると感じる場面もあった。

    また、Eclipse自体が既に長い歴史を持っていることから、参照しているプラグイン開発用の情報が既に古くなってしまっているケースがある。特にウェブサイトを参考にする際にはそのページがいつごろ書かれたものなのかに注意が必要だ。このような意味では、(電子)書籍は記述された時期が特定でき、書籍内を通じて統一されているため使いやすい。

    先述したようにEclipseプラグインはOSGiのBundleであり、高度なモジュール化がウリの一つである。そこで移植作業が順調に進んできた頃、プラグイン間の連携機能についても学んでみることにした。Doorman@JUMPERZ.NETが以前持っていた機能はほぼすべて1つのプラグイン(いわば本体)として移植し、さらに追加で開発した新機能を別のプラグインとして実装することとした。本体の名前はMDoorman、別プラグインの名前がMDoormanHookとなる。

    MDoormanは自身のHTTPプロキシサーバにおいて、リクエストあるいはレスポンスを受信したタイミングで特別な処理(Hook)を実装するための拡張機能を持つことにする。この拡張機能はMDoormanプラグインに拡張ポイント(ExtensionPoint)として定義される。他のプラグインはこの拡張ポイントに定められた実装を行うことでMDoormanプラグインと連携した動作を行うことができるようになる。筆者自身が両方のプラグインを実装することで、Eclipseプラグインにおいて拡張ポイントを提供する側と、それを使用する側の両方の実装を学ぶことができると考えた。

    拡張ポイントの作法は筆者が予想していたよりもはるかに複雑であり、結局こちらのサイトのチュートリアルをほぼそのまま実装することで何とかやりたい動きを実現することができるようになった。拡張ポイントまわりは(あくまで予想だが)より多くのパターンの拡張をサポートするために多機能となっているのだと考えている。完全に把握するためにはかなりの学習が必要になりそうだと感じた。

    今回拡張ポイントを利用する側のプラグインであるMDoormanHookはユーザに対して「Hook」という名前のViewを提供する。ユーザは自身のコードをこのViewを使って登録することで、プロキシサーバを通過するリクエストやレスポンスを書き換えることができるようになる。MDoorman本体は(もちろん当然なのだが)MDoormanHookなしでも動作することができる。MDoormanHookプラグインをインストールすればHookのViewと連携し、アンインストールすれば何事もなかったかのように本体だけで動作する。筆者はGUIのツールにおいてこのようにきれいに機能を拡張可能な機構を使った経験がなかったため、はじめに動作を確認した際にはなかなかに感動させられた。モジュール間の区切りが鮮明になるため、エンタープライズ級のアプリケーションでは特に役に立つだろう。

    先述したように、MDoormanHookを使うことで、ユーザはプロキシサーバ上を通過するリクエストやレスポンスを変更することができる。わかりやすい例として、User-Agentの書き換えなどがある。この書き換えはClojureのコードを記述することで実現される。

    元々のアイデアではJavaとClojureのコードの両方をサポートするつもりだったのだが、Javaについてはうまく行かなかった。拡張ポイントの向こうとこちらが異なるプラグインであることから、クラスローダが異なっていることがあり、結果としてJavaのコードを動的にコンパイルして動作させることができなかった(MDoorman本体側で記述すれば可能なのだが、それでは今回の目的である「Hookの機能は別プラグインで実装する」ということから外れてしまう)。こちらのプラグインで動的に生成したクラスを向こうのプラグインに渡す、ということができないのだ。このことから、クラスローダが直接影響するような仕組みをEclipseプラグインで操る場合には注意が必要であることがわかった。またClojureそのものについても、このクラスローダがプラグインごとに異なっているという問題が影響を及ぼすケースがあり、例えばClojure開発用のEclipseプラグインであるcounterclockwiseはMDoormanHookと共存させようとした場合にエラーが出てしまうケースがあるようだ。

    拡張ポイントの実装を終えた後には、アップデート機能の検討に取り組んだ。ここではFeatureという概念が登場する。Eclipseプラットフォームが提供するアップデート機能を使うためには、アップデート用のウェブサイトや、Featureを使ったプラグインの管理が必要となる。標準的な手続きにしたがってアップデート用のウェブサイトまで構築し、実際にインストールやアップデート作業を行ってみたのだが、最終的にはこれは使わないことにした。理由は下記のようなものである。

  • いくつかの環境で、アップデートのテスト中に、ネットワークの通信中のステータスのままEclipseが固まってしまうことがあった
  • すべてがうまく行く場合でも、手順があまりシンプルでなく、ユーザにとって本当にわかりやすいかどうか疑問が残った(単にjarファイルのコピーでインストールできた方が簡単では?)
  • このように様々な経緯を経て移植作業を完了させることができた。WindowsでもMacOSでもLinuxでも何の問題もなくアプリケーションが動作する様子は圧巻である。すべての環境でネイティブアプリケーションとまったく同じLook&Feelとなり、またインストールもEclipseさえ入っていれば簡単に終了する。特に筆者にとって開発経験がまったくないMacOS上できちんと自分が開発したアプリケーションが動作したことは軽いカルチャーショックであり、クロスプラットフォーム性を持つJava、あるいはEclipseの凄さを再認識させられることとなった。

    今回開発したアプリケーションは「Doorman Eclipse Plugin」と名付けた。2011年にはSSL関連の作業に便利な新機能も実装した。また、近いうちにClojureだけでなく、JavaScriptでも拡張コードが書けるようにする予定である(実装にはJavaに含まれているrhinoを使う予定)。

    また、この後筆者はAndroidアプリケーションの開発にも触れてみることにしたのだが、その際にこのEclipseプラグインの開発経験が役に立った。Android開発はEclipseプラグイン開発と同様に、IDE(もちろんEclipseだ)にヘビーに依存する開発手法となっている。また、GUIのエディタツールでの操作がXMLファイルを更新する部分などもそっくりである。おそらくAndroidの開発環境はEclipseのプラグイン開発を参考に設計されたのではと思う。そしてAndroidの開発環境はまさにEclipseプラグインそのものとなっており、その動作の仕組みなどを把握する際にも今回のEclipseプラグイン開発経験が役に立ちそうだ。

    このように、筆者にとっては得るところの非常に多い開発経験となった。最近ではあまり「Eclipseプラグインを開発しよう!」のような記事を見かけなくなってしまったが、2011年現在でもまったく問題なくおすすめできる最新の技術であると思う。

    Advertisements

    One Comment on “Eclipseプラグイン開発の感想”

    1. […] 以前のエントリにまとめたように、以前はスタンドアローンのアプリケーションであったDoorman@JUMPERZ.NETを「Doorman Eclipse Plugin」という名前のEclipseプラグインに移植した(というか、プラットフォームをEclipseに変更した)。そこで、せっかくAppStore的な場所があるのならば使ってみようと思い、手続きを行ってみた。自作アプリケーションを公開する場合、今どきの開発者ならばAppleのAppStoreかGoogleのAndroidマーケットあたりが普通だと思うが、筆者は斜め上のEclipse Marketplaceである。 […]


    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s