S-JIS[2013-07-14] 変更履歴

拡張ポイント

Eclipseプラグイン開発の拡張ポイントの作成方法。


概要

Eclipseのプラグインでは拡張ポイントに各自のプラグインを追加していく方式になっており、自分でも拡張ポイントを定義することが出来る。
他の人がその拡張ポイントに対するプラグインを作ると、(両方のプラグインが入っているEclipseでは)自分のプラグインからそのプラグインを呼び出せる。

拡張ポイントを定義する際には、まず処理のインターフェース(クラス)を作る。
他人はそのインターフェース(クラス)を実装(継承)することになる。
そして、拡張ポイントの宣言を作成する(plugin.xmlを記述する)。
拡張ポイントのextensionの書き方(スキーマ)を定義するexsdファイルも併せて作成する。


処理クラス

呼び出す(実装される)クラス(インターフェース)を作成する。

package com.example;

public abstract ExampleExtension {

	public abstract String getValue();
}

拡張ポイントの宣言

plugin.xmlのマニフェストエディター拡張ポイントタブを選択し、「Add」ボタンで拡張ポイントを追加する。

項目 説明
Extension Point ID exampleExtension 拡張ポイントのID。
Extension Point Name extension example 拡張ポイントの名前。
Extension Point Schema schema/exampleExtension.exsd スキーマファイルのファイル名。拡張ポイントIDを入れると自動的に入力される。
Edit extension point schema when done   チェックを付けておくと、完了ボタンを押した後でスキーマファイルのエディターが開く。

スキーマファイルの定義

スキーマファイルは、デフォルトでは「extension」要素だけ定義されている。
(extension要素にはpoint・id・name属性が定義されている)

今回の例では呼び出すクラスの定義を行いたいので、classpathという要素を追加し、classという属性を定義してみる。

  1. classpath要素を追加する。
    1. 「New Element」ボタンを押す。(新しい要素を追加される)
    2. 右側のElement Detailsに値を入力する。
      項目 備考
      Name classpath 要素名
      Description exampleExtension 要素の説明
  2. classpath要素属性classを追加する。
    1. 左側の一覧から(上記で追加した)classpathを選択し、「New Attribute」ボタンを押す。(新しい属性が追加される)
    2. 右側のAttribute Detailsに値を入力する。
      項目 備考
      Name class 属性名
      Deprecated false 非推奨かどうか
      Use required 必須かどうか
      Type java 属性値の型
      Extends com.example.ExampleExtension 属性値の親クラス。
      拡張するプラグインでは、このクラスを継承しているクラスのみ指定可能になる。
      Implements   属性値のインターフェース(今回は未使用)
  3. classpath要素がextension要素の子要素になるように設定する。
    1. 左側の一覧からextension要素を選択し、「New Sequence」ボタンを押す。(新しいSequenceが追加される)
    2. 右側のCompositor Detailsに値を入力する。
      項目 備考
      Min Occurrences 0 子要素の最小の個数。
      Max Occurences Unbounded 子要素の最大の個数。Unboundedにすると無限。
      DTD Approximation (classpath)* この項目は直接は入力不可能。他の項目から自動的に生成される。
      デフォルトでは「EMPTY」となっている。
      左側の一覧でSequenceを選択し、右クリックで「New」→「classpath」を選択するとclasspathが入力される。

Sequenceというのは、要素内に子要素が並ぶ(順番に現れる)ことを意味していると思われる。
最小が0で最大が無限だと「(classpath)*」、最小が1だと「(classpath)+」になる。
Sequenceの他にChoiceというものもある。
Sequenceの下にさらに別のSequenceやChoiceを入れられる。


拡張されたクラスを呼び出す方法

実際のプラグイン(plugin.xml)に設定された値をロードしてキャッシュするクラスを用意しておくと便利。

ExtensionLoader.java:

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
public class ExtensionLoader {

	private static final String EXAMPLE_EXTENSION_POINT_ID = Activator.PLUGIN_ID + ".exampleExtension";	//拡張ポイントID
	private List<ExampleExtension> list;
	public List<ExampleExtension> getExampleExtensions() {
		if (list != null) {
			return list;
		}

		IExtensionRegistry registory = Platform.getExtensionRegistry();
		IExtensionPoint point = registory.getExtensionPoint(EXAMPLE_EXTENSION_POINT_ID);
		if (point == null) {
			throw new IllegalStateException(EXAMPLE_EXTENSION_POINT_ID);
		}

		list = new ArrayList<ExampleExtension>();
		for (IExtension extension : point.getExtensions()) {
			for (IConfigurationElement element : extension.getConfigurationElements()) {
				try {
					Object obj = element.createExecutableExtension("class");	//class属性
					if (obj instanceof ExampleExtension) {
						list.add((ExampleExtension) obj);
					}
				} catch (CoreException e) {
					Activator.getDefault().getLog().log(e.getStatus());
				}
			}
		}
		return list;
	}
}

このExtensionLoaderをActivatorクラスから取得できるようにしておく。

Activator.java:

public class Activator extends AbstractUIPlugin {
〜
	private ExtensionLoader extensionLoader;
	public void start(BundleContext context) throws Exception {
		super.start(context);
		plugin = this;

		this.extensionLoader = new ExtensionLoader();
	}
	public static ExtensionLoader getExtensionLoader() {
		return getDefault().extensionLoader;
	}
}

呼び出し側.java:

		List<ExampleExtension> list = Activator.getExtensionLoader().getExampleExtensions();
		for (ExampleExtension example : list) {
			String value = example.getValue();
			〜
		}

拡張する側の定義方法

拡張する側(呼ばれる側)は、普通のプラグインと同様。

plugin.xml:

   <extension
         point="com.example.examplePlugin.exampleExtension">
      <classpath
            class="com.example.Example1">
      </classpath>
      <classpath
            class="com.example.Example2">
      </classpath>
   </extension>

Example1.java:

public class Example1 extends ExampleExtension {

	@Override
	public String getValue() {
		return "example1";
	}
}

Eclipseプラグインへ戻る / Eclipseへ戻る / 技術メモへ戻る
メールの送信先:ひしだま