----
//ここにコンテンツを記述します。



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


#contents


**覚え書き [#j62d232a]


***とりあえずやってみる [#k6a964ed]
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)のスケルトンもウィザードが作ってくれます。



***サンプルのダウンロード [#w152c277]
ヘルプに リッチ・クライアント・プラットフォーム・アプリケーションのビルド という項目があったので、見てみるとサンプルがEclipseのCVS
 :pserver:anonymous@dev.eclipse.org:/home/eclipse
からチェックアウト可能とのこと。パスワードはなしですね。

WEBからアクセスする場合は
 http://dev.eclipse.org/viewcvs/index.cgi/



***Ganymedeで、プラグインを手動で削除したとき [#cfdbe06a]
どうもプラグインのキャッシュが残っているのか、消すことも再インストールでもできないときが発生。とりあえず
 ${ECLILPSE_HOME}/p2/org.eclipse.equinox.p2.core
内のファイルを削除すると消えるっぽい。。




***外部のライブラリを使用する [#dc5c9f14]
プラグインディレクトリにlibディレクトリなどを作成しておいて、plugin.xmlで
 <runtime>
   <library name="hoge.jar"/>
   <library name="lib/fuga.jar"/> <-外部ライブラリ
 </runtime>
とすればOKです。


*** プロジェクトへの参照を取得する [#u15a6a98]
いわゆるEclipseのプロジェクトへの参照を取得する方法です。
 IWorkspaceRoot myWorkspaceRoot =
   ResourcesPlugin.getWorkspace().getRoot();
 IProject project = myWorkspaceRoot.getProject([プロジェクト名の文字列]);

-[[Eclipse/プラグイン開発のTIPS集/ワークスペースのリソースを取り扱う]]


***デバッグするためのダイアログを出したい [#a91aa3cd]
 IWorkbench workbench = PlatformUI.getWorkbench();
 IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
 Shell shell = window.getShell();
 MessageDialog.openInformation(shell, "タイトル","メッセージ");
が定番でしょう。windowオブジェクトはメソッドを記述するクラスによってはフィールドから得られたりしますが。。

***ウィンドウに配置されているViewを取得する。 [#z76cff34]
 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指定で取得する。 [#i39484e4]
 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を複数開く [#t81ac22d]
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 から情報をいただきました。



***プラグインのパッケージング手順 [#i4b96068]
-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に書く)

***パッケージ化するとインスタンスを生成できない。 [#kecb2ad7]
[[パッケージ化するとインスタンスを生成できない。:http://groups.yahoo.co.jp/group/eclipse-ml/message/1019?expand=1]]
私も同じトラブルに遭遇しました。

プラグインをパッケージングすると、何故かエラーになってしまうというもの。ビューを開こうとすると
 インスタンスを生成できませんでした。
と言われてしまうんだけど、エラーを調べようにもどこにエラーが表示されているのかも分からないので困っていました。

そこでネットを探していたところ、同じような内容の投稿が。とりあえずこれを見て、プラグインのログは
-ウィンドウ→ビューの表示→その他→PDEランタイム→エラー・ログ で「エラーログビュー」を開く。
-エラーログビューで、該当エラーをダブルクリックし「エラーのプロパティー」を開く。
-「状況詳細」を選択します(状況詳細はない場合もあります)。→ここにStackTraceなどが表示されます。

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

そのエラーログを見ると、xml関連のライブラリがないと。どうもプラグインをパッケージした場合と、ランタイムワークベンチで稼動しているVMのバージョンの違いが原因でした。((WebSphereStudioはJ2SE1.3だったためだ〜))
plugin.xmlに、
 <library name="lib/xercesImpl.jar"/>
 <library name="lib/xml-apis.jar"/>
を追加して、ようやく動きました。疲れた...。。。

***プラグインがロードされるタイミング [#lf696913]
http://www-6.ibm.com/jp/developerworks/opensource/040604/j_os-ecspy1.html

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

-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 :http://www.eclipsecon.org/2005/tutorials.php]] のFrequent problems with third party libraries によれば
 Thread currentThread = Thread.currentThread();
 ClassLoader oldClassLoader = currentThread.getContextClassLoader();
 
 try {
   currentThread.setContextClassLoader(plugin.getClass().getClassLoader());
   // 普通に処理を書く
 } finally {
   currentThread.setContextClassLoader(oldClassLoader);
 }
が正解っぽい??すいません。時間切れ。。



***リファクタリング >> ストリングの外部化 [#m6e7d7f7]
Eclipse自体のTIPSですが、メモメモ。

Eclipseはハードコーディングされた文字列を外部ファイル(*.properties)に外出しするリファクタリングをすることができます。で、それをやるとStringの一覧のダイアログが出るんですけど、なんかわかりにくかったんでまとめておきます。各チェックの意味は以下の通り。
|チェック|Externalize|外部化して、//$NON-NLS-1$ をつける|
|×|Ignore|以後無視するよう、//$NON-NLS-1$ をつける|
|×'|Internalize|//$NON-NLS-1$ をはずすもしくはなにもしない|




***plugin.xmlのimport要素の記述の意味 [#p33d3a4d]
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を活性化できる、ってこと?

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

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


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

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

*** org.eclipse.osgi.util.NLS でプレースホルダ(Eclipse3.1) [#z1311e44]
 if (productName == null) {
     message = "Exit application?";
 } else {
     // プレースホルダが使えるの?
     message = NLS.bind("Exit {0}?", productName);
 }
という感じで使える。。



***ビューワにコンテキストヘルプを実装する [#v62250e1]
たとえば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を押したとき、ヘルプが表示されます。

***違うプラグイン上のヘルプファイルを見たい [#me6b0414]
 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、その後をキー値としてるみたいだ((org.eclipse.help_3.1.0.jarのorg.eclipse.help.internal.context.ContextManager#getContext(String) など))。

ところで、Eclipse3.1から、
 WorkbenchHelp.displayHelp(contextId);
はdeprecatedとなったため、3.1以後は
 PlatformUI.getWorkbench().getHelpSystem()
  .displayHelp(contextId);
とするほうがよいようです。





*** ステータスバーに文字を表示する [#w46781b5]
[[リレーショナル・データベース・サーバーをEclipseに埋め込む:http://www-06.ibm.com/jp/developerworks/opensource/040220/j_os-echsql.html#N1006E]] みてて知ったTIPS

window 変数をIWorkbenchWindow の インスタンスとしたとき
 ((ApplicationWindow)window).setStatus("HSQLDB Server already running.");
で、ステータスバーに文字列を表示することが出来る



***パースペクティブを操作する [#o0831edf]
まずはパースペクティブのレジストリへのアクセス方法です。パースペクティブは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");



***パースペクティブをプログラムから切り替える [#necf3bc2]
パースペクティブをセットするメソッドがIWorkbenchWindowとかIWorkbenchPageにあるはず、、と思って探したら、ありました。
 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().
 setPerspective(descriptor);<-descriptorはIPerspectiveDescriptor でレジストリから取って来る                  

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


***リンク付きのラベルを使用する [#d932a074]
Eclipse3.1から導入された、ウィジェット上にリンクを表示するLinkクラスの使い方です。
#ref(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のイベントを見て処理をすればよいようです。クリックしたらウィザードを起動するとか、ベタにブラウザを起動するとか、なんでもできますね。


***各ビューで選択されているオブジェクトを取得する [#waa835e9]
Eclipseには、[[ISelectionProviderという、「選択されているオブジェクトを外部に公開するクラス」を、Viewごとに設定する>Eclipse/プラグイン開発のTIPS集/org.eclipse.ui.ISelectionListener]]ことができます。このオブジェクトはViewごとに存在するので、各Viewのこのインスタンスを取得できれば、選択されているオブジェクトを
 getSite().getSelectionProvider().getSelection();
と取得できます。


さらにもっと便利なメソッドがありました。
 ISelection selection = page.getSelection([viewid]);
で一発で取得できます。pageはIWorkbenchPageのインスタンスです。これは便利!!


***プラグインに、プロキシの機能を追加する [#s3b276f6]
自分でコーディングするのももったいないので、すでにあるモノを使用します。
 org.eclipse.wst.internet.proxy_1.0.100.v200606130645.jar
 org.eclipse.wst.internet.proxy.nl1_1.0.100.v200606220026.jar
を追加すれば、プロクシサーバの設定をする設定画面などが現れます。。

***ウィンドウを隠す [#i0c79970]
タスクトレイだけのアプリを作る場合とか。
 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()
                .setVisible(false);
で消えるけど、ALT+TABのアプリ一覧にはでちゃうなあ。。

***別のロケールで起動する。 [#y6b05451]
 C:\xxx\eclipse.exe  -nl en_US -vmargs -Xmx768M
などと、  -nl en_US と指定すると、USロケールで起動する。

***ワークスペースの場所を聞いてくるようにする。 [#h1cb54b5]
開発中にEclipseからEclipseを起動すると、通常はワークスペースの場所を聞いてこないけれど、プログラム引数に
 -data @noDefault
とすれば聞いてくるようになります。


***org.eclipse.core.resources.IFileからjava.io.Fileを取得する。 [#de3bbabf]
fileがIFileインスタンスだとして
 File instance = file.getLocation().toFile();
でOK!
-[[Builderの作り方>http://www.limy.org/program/eclipse/plugin/make_builder.html]]



***IJavaProject からプロジェクトのエンコーディングを取得する。 [#w0055e43]

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プラグイン開発のコンテンツ一覧
#ls2










#include(Eclipse/プラグイン開発のTIPS集/GooglePlugin)




**[[Eclipseプラグイン開発:http://yoichiro.cocolog-nifty.com/eclipse/]] [#yd461a90]
#showrss(http://yoichiro.cocolog-nifty.com/eclipse/index.rdf,,24,1)

**[[Eclipse開発 Blog:http://eclipse3.seesaa.net/]] [#yd461a90]
#showrss(http://eclipse3.seesaa.net/index20.rdf,,24,1)





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

#topicpath


SIZE(10){現在のアクセス:&counter;}

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS