Eclipse/プラグイン開発のTIPS集/記事一覧


Wikiの一覧ではそろそろまとまりがなくなってきたので、記事一覧を作りました。

Eclipseプラグイン開発の記事一覧

メニュー/アクション関連

ビュー関連

リッチクライアント(Ecilpse/RCP)関連

外部へのリンク集

GooglePlugin?を作ったときのまとめの記事

いろいろな拡張ポイント

プラグインの公開関連

その他TIPSなど

以下、かなり書き途中*3


現在のアクセス:121091

覚え書き

とりあえずやってみる

JavaWorld?の2004年3月号に特集されていたので、Eclipseのプラグイン開発ツールを触ってみました。

Eclipseはこのプラグインの固まりで、すべての機能はプラグインで作成されているみたいです。ようするにEclipseを機能拡張したい場合はこのプラグインという作法に則って作成するわけですね。

まだ全然やり方がわかりません。とりあえずView(パースペクティブ内の一つのタイルのこと)を拡張して、選択しているファイルのファイル名を表示するプラグインを作成しています。

簡単なやり方は

  • プラグイン開発 >> プラグイン・プロジェクト >> プロジェクト名
    (プロジェクト名はたとえばnu.mine.kino.sampleとか)
  • プラグイン・コード生成プログラム >> デフォルト・プラグイン構造
    (何も追加しない単純なテンプレート)

後はすべてデフォルトでOKでよいです。ウィザードが完了すると、単純なプラグイン・プロジェクトの作成完了です。

基本的な構成はできたので、次はプラグインファイル(plugin.xml)の記述です。手順は

  • プラグインエディタの拡張タブ >> 追加 >> 汎用ウィザード >> スキーマベースの拡張
  • 拡張ポイントを org.eclipse.ui.views を選択
  • プラグインエディタの拡張タブより、org.eclipse.ui.viewsを右クリック >> 新規 >> Category を追加(Viewを属させるグループの作成)
  • さらに拡張タブより、org.eclipse.ui.viewsを右クリック >> 新規 >> View を追加(実際のViewの作成) とするとViewを追加できます。後はプロパティViewより必要事項を入力します。 ただのビューを表示するだけなら
    <extension point="org.eclipse.ui.views">
      <category
        name="サンプルMyView"   <- viewが属するカテゴリ名
        id="com.samples.myview"> <- カテゴリのID
      </category>
      <view
        name="シンプルView"   <- viewのバーのタイトル
        category="com.samples.myview"   <- viewが属するカテゴリID
        class="com.samples.myview.SimpleView"    <- viewを実装するクラス名
        id="com.samples.myview.simpleview">      <- viewのID
      </view>
    </extension>
    で十分です。プロパティViewよりclassを選択すると対応するクラス(ここではcom.samples.myview.SimpleView?)のスケルトンもウィザードが作ってくれます。

サンプルのダウンロード

ヘルプに リッチ・クライアント・プラットフォーム・アプリケーションのビルド という項目があったので、見てみるとサンプルがEclipseのCVS

:pserver:anonymous@dev.eclipse.org:/home/eclipse

からチェックアウト可能とのこと。パスワードはなしですね。

WEBからアクセスする場合は

http://dev.eclipse.org/viewcvs/index.cgi/

Ganymedeで、プラグインを手動で削除したとき

どうもプラグインのキャッシュが残っているのか、消すことも再インストールでもできないときが発生。とりあえず

${ECLILPSE_HOME}/p2/org.eclipse.equinox.p2.core

内のファイルを削除すると消えるっぽい。。

外部のライブラリを使用する

プラグインディレクトリにlibディレクトリなどを作成しておいて、plugin.xmlで

<runtime>
  <library name="hoge.jar"/>
  <library name="lib/fuga.jar"/> <-外部ライブラリ
</runtime>

とすればOKです。

プロジェクトへの参照を取得する

いわゆるEclipseのプロジェクトへの参照を取得する方法です。

IWorkspaceRoot myWorkspaceRoot =
  ResourcesPlugin.getWorkspace().getRoot();
IProject project = myWorkspaceRoot.getProject([プロジェクト名の文字列]);

デバッグするためのダイアログを出したい

IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
Shell shell = window.getShell();
MessageDialog.openInformation(shell, "タイトル","メッセージ");

が定番でしょう。windowオブジェクトはメソッドを記述するクラスによってはフィールドから得られたりしますが。。

ウィンドウに配置されているViewを取得する。

IWorkbenchPage page = workbench.getActiveWorkbenchWindow().getActivePage();
IViewReference[] references = page.getViewReferences();

for (int i = 0; i < references.length; i++) {
  IViewPart view = references[i].getView(false); <- Viewへの参照が取得できました
  MessageDialog.openInformation(window.getShell(), "ViewのtoString()", view.toString());
}

ウィンドウに配置されているViewを、ID指定で取得する。

IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchPage workbenchPage = workbench
       .getActiveWorkbenchWindow().getActivePage();
//IWorkbenchPage workbenchPage = editor.getSite().getPage();
try {
  HogeView view =
    (HogeView) workbenchPage.showView("HogeViewのID");
} catch (PartInitException e) {
}

おなじViewを複数開く

Eclipse3.0から(だと思う)同じウィンドウを複数開くことができるようです。

IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchPage workbenchPage = workbench
        .getActiveWorkbenchWindow().getActivePage();
try {
  HogeView view =
    (HogeView) workbenchPage
    .showView("HogeViewのID", "HogeViewの別のID(Uniqueならよい?)",
    IWorkbenchPage.VIEW_ACTIVATE);
} catch (PartInitException e) {
}

http://d.hatena.ne.jp/muimy/20040804 から情報をいただきました。

プラグインのパッケージング手順

  • build.propertiesに、パッケージしたいものを記述する(bin.includesにlib/hoge.jarとかicons/*とか)
  • plugin.xmlの右クリック >> Antビルドファイルの作成 でbuild.xml作成
  • javac要素はソースコードのエンコーディングが考慮されてないので、追加(encoding="EUC-JP"など)。
  • ant zip.pluginでZIPが作成される。
  • 完了。

トラブル(↓メモ書き状態)

  • plugin.xmlの右クリック>>Antビルドファイルの作成 は、コンパイルのエンコーディングが考慮されない(encoding="EUC-JP"などを追加する必要あり)
  • build.propertiesに、パッケージしたいものを記述する(bin.includesに書く)

パッケージ化するとインスタンスを生成できない。

パッケージ化するとインスタンスを生成できない。 私も同じトラブルに遭遇しました。

プラグインをパッケージングすると、何故かエラーになってしまうというもの。ビューを開こうとすると

インスタンスを生成できませんでした。

と言われてしまうんだけど、エラーを調べようにもどこにエラーが表示されているのかも分からないので困っていました。

そこでネットを探していたところ、同じような内容の投稿が。とりあえずこれを見て、プラグインのログは

  • ウィンドウ→ビューの表示→その他→PDEランタイム→エラー・ログ で「エラーログビュー」を開く。
  • エラーログビューで、該当エラーをダブルクリックし「エラーのプロパティー」を開く。
  • 「状況詳細」を選択します(状況詳細はない場合もあります)。→ここにStackTrace?などが表示されます。

というところまで分かりました。感謝!!

そのエラーログを見ると、xml関連のライブラリがないと。どうもプラグインをパッケージした場合と、ランタイムワークベンチで稼動しているVMのバージョンの違いが原因でした。*1 plugin.xmlに、

<library name="lib/xercesImpl.jar"/>
<library name="lib/xml-apis.jar"/>

を追加して、ようやく動きました。疲れた...。。。

プラグインがロードされるタイミング

http://www-6.ibm.com/jp/developerworks/opensource/040604/j_os-ecspy1.html

拡張ポイントクラス(IExtension)から、そのクラスローダでメソッドを実行する

  • 2.1バージョン
    // IExtensionからそれが宣言されているプラグインをIPluginDescriptorとして取り出す。
    IPluginDescriptor descriptor =
      extension.getDeclaringPluginDescriptor();
    // そのプラグイン用のクラスローダを取得。
    ClassLoader classLoader = descriptor.getPluginClassLoader();
    DOMConfigurator configurator = (DOMConfigurator) classLoader
       .loadClass("org.apache.log4j.xml.DOMConfigurator")
       .newInstance();
  • 3.0バージョン
    String namespace = extension.getNamespace();
    Bundle bundleOfExtension = Platform.getBundle(namespace);
    DOMConfigurator configurator = (DOMConfigurator) bundleOfExtension
       .loadClass("org.apache.log4j.xml.DOMConfigurator")
       .newInstance();

どうも、↑こうやってもDOMConfiguratorはlog4j.jarの入ってるプラグインで実行されているっぽい。。EclipseCon2005 TUTORIALS 26 Developing for the Rich Client Platform のFrequent problems with third party libraries によれば

Thread currentThread = Thread.currentThread();
ClassLoader oldClassLoader = currentThread.getContextClassLoader();

try {
  currentThread.setContextClassLoader(plugin.getClass().getClassLoader());
  // 普通に処理を書く
} finally {
  currentThread.setContextClassLoader(oldClassLoader);
}

が正解っぽい??すいません。時間切れ。。

リファクタリング >> ストリングの外部化

Eclipse自体のTIPSですが、メモメモ。

Eclipseはハードコーディングされた文字列を外部ファイル(*.properties)に外出しするリファクタリングをすることができます。で、それをやるとStringの一覧のダイアログが出るんですけど、なんかわかりにくかったんでまとめておきます。各チェックの意味は以下の通り。

チェックExternalize外部化して、//$NON-NLS-1$ をつける
×Ignore以後無視するよう、//$NON-NLS-1$ をつける
×'Internalize//$NON-NLS-1$ をはずすもしくはなにもしない

plugin.xmlのimport要素の記述の意味

Eclipse付属のマニュアルは以下のようになっています。

それぞれの依存性は、<import> エレメントを使用して指定されます。これには以下の属性が含まれています。

  • plugin - 必要なプラグインの ID
  • version - (オプション) バージョン指定
  • match - バージョン・マッチング規則。 version 属性が指定されていない場合は無視されます。依存性が 指定されたバージョンと 正確に一致するプラグインのみ、サービスまたは修飾子がこれよりも新しいプラグイン、すべての互換バージョン (プラグインの最新マイナー・バ ージョンを含む)、またはこのプラグインよりも新しいバージョンのどれによって満たされるかを決定します。
  • export - このプラグインのユーザーに依存プラグイン・クラスを可視にする ((再度) エクスポートする) かどうかを指定します。デフォルトでは、依存クラスはエクスポートされません (可視になりません)
  • optional - この依存性が、厳密に強制されるかどうかを指定します。 <true> に設定すると、依存性は満たされず、依存性は無視されます。

とくに

export
たぶん、プラグインBをimportするプラグインAがあるとき、プラグインBがimportするプラグインCを、Aから使えるようにするか、ってことだと思う。。
A -> B -> C
プラグインBで、プラグインCのexportをtrueにしておけば、AはCをimportしなくてもつかえるってこと?
optional
プラグインAでimportするプラグインBをoptionalにしておけば、プラグインディレクトリにプラグインBがなくてもプラグインAを活性化できる、ってこと?

未使用の依存関係の検索でいるモノが出てきちゃう

Log4jのライブラリをさまざまなプラグインで使用するので、ひとつのプラグインにしているんだけど、そのプラグインがいっつも不要なプラグインで出てきちゃう。。jarを共有するためだけの場合は、使ってることが検出できないのかな。

ワークスペース内のプラグインプロジェクトを、全て「クラスパスの更新」をやったら、検出できるようになった。ふしぎだ。

フィーチャー・バージョンの意味

  • フィーチャー・バージョンをプラグインに強制 :すべてフィーチャーのバージョンになる
  • プラグインからバージョンをコピー :feature.xmlにワークスペースのプラグインプロジェクトのバージョンを適用する
  • フィーチャーで定義されたバージョンをプラグインに強制 :feature.xmlに書いてあるバージョンをワークスペースのプラグインプロジェクトに適用する

1番目と最後の違いは、1番目はフィーチャー自体のバージョンに他のバージョンをあわせるので、全てのプラグインのバージョンは同じになります。最後のはxmlファイルに書いてあるそれぞれプラグインのバージョンをそれぞれのプラグインに適用する、という違いですね。

org.eclipse.osgi.util.NLS でプレースホルダ(Eclipse3.1)

if (productName == null) {
    message = "Exit application?";
} else {
    // プレースホルダが使えるの?
    message = NLS.bind("Exit {0}?", productName);
}

という感じで使える。。

ビューワにコンテキストヘルプを実装する

たとえばnu.mine.kino.pluginというプラグインでコンテキストヘルプ(F1のイベントを拾ってヘルプを表示する機能)を使用するには以下のようにします。

viewer.addHelpListener(new HelpListener() {
  public void helpRequested(HelpEvent e) {
    String contextId = "nu.mine.kino.plugin.workbench_window_context";
    nu.mine.kino.pluginはプラグインID
    workbench_window_contextは後述のcontext.xml内のキー値。
    WorkbenchHelp.displayHelp(contextId);
  }
});

実際のコンテキストに表示される内容は拡張ポイントorg.eclipse.help.contextsで指定します。 nu.mine.kino.plugin#plugin.xmlに

<extension point="org.eclipse.help.contexts">
  <contexts file="context.xml">
  </contexts>
</extension>

とします。

で、context.xmlは以下のよう:

<?xml version="1.0" encoding="UTF-8"?>
<?NLS TYPE="org.eclipse.help.contexts"?>
<contexts>
  <context id="workbench_window_context"> <-さっきのキー値。
    <description>ヘルプです。</description>
     <topic label="てすとワークベンチ" href="concepts/concepts-2.htm"/>
     <topic label="てすとパースペクティブ" href="concepts/concepts-4.htm"/>
     <topic label="てすとワークベンチの管理" href="tasks/tasks-1.htm"/>
  </context>
</contexts>

こうするとviewer上でF1を押したとき、ヘルプが表示されます。

違うプラグイン上のヘルプファイルを見たい

viewer.addHelpListener(new HelpListener() {
  public void helpRequested(HelpEvent e) {
    String contextId = "nu.mine.kino.doc.workbench_window_context";
    // nu.mine.kino.doc はこのソースのプラグインとは別のプラグインとします
    WorkbenchHelp.displayHelp(contextId);
  }
});

nu.mine.kino.doc#plugin.xmlには以下の内容を記述しておきます。

<extension point="org.eclipse.help.contexts">
  <contexts file="context.xml" >
  </contexts>
</extension>

context.xmlの書き方は同じでかまいません。

いろいろ処理を調べてみたところ、どうも指定したcontextIdの最後のドットを見てパースし、手前までをプラグインID、その後をキー値としてるみたいだ*2

ところで、Eclipse3.1から、

WorkbenchHelp.displayHelp(contextId);

はdeprecatedとなったため、3.1以後は

PlatformUI.getWorkbench().getHelpSystem()
 .displayHelp(contextId);

とするほうがよいようです。

ステータスバーに文字を表示する

リレーショナル・データベース・サーバーをEclipseに埋め込む みてて知ったTIPS

window 変数をIWorkbenchWindow? の インスタンスとしたとき

((ApplicationWindow)window).setStatus("HSQLDB Server already running.");

で、ステータスバーに文字列を表示することが出来る

パースペクティブを操作する

まずはパースペクティブのレジストリへのアクセス方法です。パースペクティブはorg.eclipse.ui.IPerspectiveRegistry? というレジストリで管理されています。

IPerspectiveRegistry pRegistry = 
    PlatformUI.getWorkbench().getPerspectiveRegistry();

でレジストリへの参照を取得できます。

続いてパースペクティブ自体にアクセスします。パースペクティブは、何となくわかってきましたがIPerspectiveDescriptor?と一対一対応します。IPerspectiveDescriptor?には

public String getDescription();
public String getId();
public ImageDescriptor getImageDescriptor();
public String getLabel();

などのメソッドがあります。

IPerspectiveDescriptor?への参照は以下のように取得できます。

  • 一覧を取得
    IPerspectiveDescriptor[] perspectives = pRegistry.getPerspectives();
  • キー値指定で個別に取得
    IPerspectiveDescriptor descriptor = 
       pRegistry.findPerspectiveWithId("plugin.xmlのパースペクティブID");

パースペクティブをプログラムから切り替える

パースペクティブをセットするメソッドがIWorkbenchWindow?とかIWorkbenchPage?にあるはず、、と思って探したら、ありました。

PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().
setPerspective(descriptor);<-descriptorはIPerspectiveDescriptor でレジストリから取って来る                  

なげぇよ、長すぎるよ。あもちろんwindowとか取れる場合はPlatformUIとかからやらなくていいですけどね。めんどくさくなると、すぐPlatformUIよんでしまう。。

リンク付きのラベルを使用する

Eclipse3.1から導入された、ウィジェット上にリンクを表示するLinkクラスの使い方です。

link.png

コード

Link link = new Link(container, SWT.NONE);
link.setText("<a>リンク</a>, <a>portable</a> 
  <a href=\"native\">operating systems</a> on which it is implemented.");
link.addListener(SWT.Selection, new Listener() {
    public void handleEvent(Event event) {
        System.out.println("Selection: " + event.text);
        ↑event.textで、href属性があればその中の文字列(上ならnative)、
          href属性がなければ<a>○○</a>の中に囲まれた「○○」が取得できる
    }
});

このようにして、SWT.Selectionのイベントを見て処理をすればよいようです。クリックしたらウィザードを起動するとか、ベタにブラウザを起動するとか、なんでもできますね。

各ビューで選択されているオブジェクトを取得する

Eclipseには、ISelectionProviderという、「選択されているオブジェクトを外部に公開するクラス」を、Viewごとに設定することができます。このオブジェクトはViewごとに存在するので、各Viewのこのインスタンスを取得できれば、選択されているオブジェクトを

getSite().getSelectionProvider().getSelection();

と取得できます。

さらにもっと便利なメソッドがありました。

ISelection selection = page.getSelection([viewid]);

で一発で取得できます。pageはIWorkbenchPage?のインスタンスです。これは便利!!

プラグインに、プロキシの機能を追加する

自分でコーディングするのももったいないので、すでにあるモノを使用します。

org.eclipse.wst.internet.proxy_1.0.100.v200606130645.jar
org.eclipse.wst.internet.proxy.nl1_1.0.100.v200606220026.jar

を追加すれば、プロクシサーバの設定をする設定画面などが現れます。。

ウィンドウを隠す

タスクトレイだけのアプリを作る場合とか。

PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()
               .setVisible(false);

で消えるけど、ALT+TABのアプリ一覧にはでちゃうなあ。。

別のロケールで起動する。

C:\xxx\eclipse.exe  -nl en_US -vmargs -Xmx768M

などと、 -nl en_US と指定すると、USロケールで起動する。

ワークスペースの場所を聞いてくるようにする。

開発中にEclipseからEclipseを起動すると、通常はワークスペースの場所を聞いてこないけれど、プログラム引数に

-data @noDefault

とすれば聞いてくるようになります。

org.eclipse.core.resources.IFileからjava.io.Fileを取得する。

fileがIFileインスタンスだとして

File instance = file.getLocation().toFile();

でOK!

IJavaProject? からプロジェクトのエンコーディングを取得する。

javaProjectをIJavaProject?だとします。

try {
    IWorkspace workspace = ResourcesPlugin.getWorkspace();
    IProject project = workspace.getRoot()
                        .getProject(javaProject.getElementName());
    System.out.println(project.getDefaultCharset());
} catch (CoreException e1) {
    // TODO 自動生成された catch ブロック
    e1.printStackTrace();
}

なんだか回りくどいですが、、、、。

Eclipse/プラグイン開発のTIPS集/GooglePlugin


Google Web APIs でプラグインを作る

Eclipseプラグイン開発の練習として、Google Web APIsを使ったプラグインを作ってみました。要件としては

  • Eclipseでコーディング中に、Googleにアクセスしたい。
  • エディタ上のテキストを選択して、ポップアップメニューからGoogle検索
  • 検索結果一覧から、ダブルクリックとかポップアップメニューでブラウザを起動して、そのサイトを表示する。
  • 結果一覧からドラッグ&ドロップでURLを作りたい

といった感じですかね。

shortcut.png


shortcut2.png

Eclipse自体を見ていると、プラグイン開発はGUI部分とビジネスロジックのCore部分を分けて作るのが基本みたいです。なので今回作成するプラグイン構成は

  • nu.mine.kino.plugin.google.core
  • nu.mine.kino.plugin.google.ui

な感じにしました。

インストール

更新サイトよりインストール可能です。 URLはこちら。

Eclipse3.1で開発しているので、今のところ3.1でしか稼動しないかも?

ライセンス

基本的にCPLとか、適当にやっちゃいたいところですが、Google Web APIsが個人・非商用のみOKなのでそれに準じる、とするべきなんですかねえ。Google Web APIsのライセンスについてはTerms and Conditions for Google Web API Serviceをご確認ください*4

結局、ライセンスはとりあえず無難にGPLにすることにしました。


現在のアクセス:132163

Eclipseプラグイン開発

Eclipse開発 Blog


  • SpringのクラスをラップしてSpring Pluginを作ろうと思ったんだけど、ApplicationContext?自体がこのプラグインのクラスローダでロードされるから、Springを使用したいプラグイン側のクラスが見えないっ。。そもそもXMLファイル自体をSpringプラグインのパスで探しちゃうし。。それぞれのプラグインでjarを持つのももったいないしなあ -- きの? 2006-03-09 19:55:29 (木)
Top / Eclipse / プラグイン開発のTIPS集

現在のアクセス:125940


*1 WebSphereStudio?はJ2SE1.3だったためだ〜
*2 org.eclipse.help_3.1.0.jarのorg.eclipse.help.internal.context.ContextManager?#getContext(String) など
*3 つうかじかんねー
*4 具体的にはgoogleapi.jarを使わないでWSDLから直接ライブラリを作成してるので、このライセンスに準じるべきなのかどうかなどもようわからんです

添付ファイル: filelink.png 1290件 [詳細] fileshortcut2.png 878件 [詳細] fileshortcut.png 916件 [詳細] fileclose.png 1010件 [詳細] fileworkbench_decomposed.gif 956件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-05-18 (月) 01:25:41 (2934d)