Plugin
出典: AgileKnowledge
プラグインは grails に機能を追加する仕組みです. grails では標準で用意される機能も基 本的にはプラグインとして実現されています. つまり, grails はプラグインの集合と考える ことができます.
プラグインの仕組みは src/commons/org.codehaus.groovy.grails.plugins に, デフォルト で提供されるプラグインは src/groovy/org.codehaus.groovy.grails.plugins にあります.
目次
1 デフォルト・プラグイン 2 GrailsPlugin
3 GrailsPluginManager 4 プラグインの中身
4.1 構造 4.2 設定 4.3 解釈 4.4 変更監視 4.5 メタ情報 5 マネージャの仕事 6 UML
デフォルト・プラグイン
後者のディレクトリにある XXXGrailsPlugin.groovy がプラグインの実体です. ここでは以 下のようなプラグインが標準で提供されていることが分かります.
Codecs
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/CodecsGrailsPlugin.groovy Controllers
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/web/ControllersGrailsPlugin.groovy Converters
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/converters/ConvertersGrailsPlugin.groovy
Core
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/CoreGrailsPlugin.groovy Datasource
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/datasource/DataSourceGrailsPlugin.groovy DomainClass
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/DomainClassGrailsPlugin.groovy Filters
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/web/filters/FiltersGrailsPlugin.groovy Hibernate
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/orm/hibernate/HibernateGrailsPlugin.groovy I18n
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/i18n/I18nGrailsPlugin.groovy Logging
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/LoggingGrailsPlugin.groovy Scaffolding
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/scaffolding/ScaffoldingGrailsPlugin.groovy Services
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/services/ServicesGrailsPlugin.groovy Servlets
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/web/ServletsGrailsPlugin.groovy UrlMappings
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/web/mapping/UrlMappingsGrailsPlugin.groovy WebFlow
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/groovy/org/codehaus/groovy/grails/plugins/webflow/WebFlowGrailsPlugin.groovy もちろん, 同じようにしてカスタムなプラグインを作成して組み込むことができます.
GrailsPlugin
各プラグインを規定しているのが GrailsPlugin (インタフェース) です.
GrailsPlugin
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/commons/org/codehaus/groovy/grails/plugins/GrailsPlugin.java GrailsPlugin の実装クラスは AbstractGrailsPlugin (抽象クラス) で, 通常はその具象サブ
クラスである DefaultGrailsPlugin が使われます.
AbstractGrailsPlugin
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/commons/org/codehaus/groovy/grails/plugins/AbstractGrailsPlugin.java DefaultGrailsPlugin
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/commons/org/codehaus/groovy/grails/plugins/DefaultGrailsPlugin.java
GrailsPluginManager
プラグイン全体を管理するのが GrailsPluginManager (インタフェース) です.
GrailsPluginManager
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/commons/org/codehaus/groovy/grails/plugins/GrailsPluginManager.java GrailsPluginManager の実装クラスは AbstractGrailsPluginManager (抽象クラス) で, 通
常はその具象サブクラスである DefaultGrailsPluginManager が使われます (この辺りの構 造は GrailsPlugin と同じで, 他の grails の主要クラスも似ています).
AbstractGrailsPluginManager
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/commons/org/codehaus/groovy/grails/plugins/AbstractGrailsPluginManager.java DefaultGrailsPluginManager
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/commons/org/codehaus/groovy/grails/plugins/GrailsPluginManager.java DefaultGrailsPluginManager を見ると, 標準プラグインは CorePluginFinder を使って
"classpath:org/codehaus/groovy/grails/**/plugins/**GrailsPlugin.groovy" から, カス タム・プラグインは GrailsRuntimeConfigurator を使って
"**/plugins/*/**GrailsPlugin.groovy" から作成されているものと思われます.
プラグインの中身
では,プラグインとは何ができるものなのか, GrailsPlugin を見ていきましょう. まず定数定義がありますが, これは後回しにします.
構造
次にいくつかの getter があります.
getName() getVersion()
getDependencyNames() getEvictionNames() getLoadAfterNames()
getDependentVersion(String) getManager()
getInstacne()
getObservedPluginNames() getProvidedArtefacts()
name, version はそのままですね.
dependency names はこのプラグインが必要とする他のプラグインの名前の配列です. eviction names はこのプラグインが排除する他のプラグインの名前の配列です.
load-after names はこのプラグインがロードされる以前にロードされていなければならな い他のプラグインの名前の配列です.
dependent version は依存する他のプラグインの名前を指定するとその依存するバージョ ンを返します.
manager はこのプラグインを管理する GrailsPluginManager です. instance は対応する XXXGrailsPlugin のインスタンスです.
observed plugin names はこのプラグインが変更を見張っている他のプラグインの名前の 配列です.
provided artefacts はこのプラグインが提供する artefact クラスの配列です. これらはプラグインの構造を定義しているものと考えられます.
設定
次に 'doWith' で始まるいくつかのメソッドがあります. これらはプラグインに関わる設定 を行うものです.
doWithApplicationContext(ApplicationContext)
doWithRuntimeConfiguration(RuntimeSpringConfiguration) doWithWebDescriptor(GPathResult)
doWithDynamicMethods(ApplicationContext) これらは GrailsRuntimeConfigurator#configure(), GrailsRuntimeConfigurator#reconfigure(),
GrailsReloadServletFilter#doFilterInternal() などから DefaultGrailsPluginManager を経由して適時呼ばれています.
doWithApplicationContext() はプラグインのインストール後に呼び出されます. doWithRuntimeConfiguration() は BeanBuilder のシンタックスを用いて, Spring の wiring を行います (詳細は後で述べますが, XXXGrailsPlugin.groovy では doWithSpring ク ロージャに対応します). この際, 次のような bean が設定されます.
application: GrailsApplication
manager: GrailsPluginManager plugin: DefaultGrailsPlugin
parentctx: ApplicationContext (Spring)
resolver: PathMatchingResourcePatternResolver (Spring, パタン文字列から適切な リソースを見つけてくるのに使われる)
doWithWebDescriptor() は XmlSlurper のシンタックスを用いて, WEB-INF/web.xml に変更 を加えるためのものです.
doWithDynamicMethods() は実行時に動的なメソッドを付け加えるためのものです.
application context が渡されるので, ここからたどれる任意のクラスのメタクラスをいじ ることができます.
解釈
実際のプラグインは groovy で記述されています. 例えば DomainClassGrailsPlugin を見 てみましょう. 普通だったら, DefaultGrailsPlugin のサブクラスにすると思いますが, DomainClassGrailsPlugin はスーパークラスを持っていません. では, このプラグインの実 体 (XXXGrailsPlugin.groovy) と DefaultGrailsPlugin はどういう関係にあるのでしょう か?
DefaultGrailsPlugin のコンストラクタの宣言は次のようになっています. public DefaultGrailsPlugin(Class pluginClass, Resource resource, GrailsApplication application)
ここで pluginClass が XXXGrailsPlugin.groovy です. 内部ではさらにこれを GrailsPluginClass と<tt>BeanWrapperImpl でラップして使っています (DefaultGrailsPlugin#initialisePlugin()).
GrailsPluginClass は元をたどると AbstractGrailsClass -> GrailsClass で, grails で実際 にプログラマが書くほとんどの groovy クラスを操作するためのクラス, BeanWrapperImpl は Spring Bean として扱うためのクラスです.
実際には XXXGrailsPlugin.groovy のコードが直接走ることはあまりなく (もちろんクロー ジャは利用される), DefaultGrailsPlugin が XXXGrailsPlugin の持つプロパティを解釈・ 実行する形になっています. 例えばプラグインの version を知るためには
eveluatePluginVersion() の中で, "version"(GrailsPlugin の中で VERSION という文字列 定数で定義) という名前のプロパティを get しています.
最初に述べた, GrailsPlugin の最初の定数定義の多くは XXXGrailsPlugin.groovy で定義さ れるべきプロパティの名前を表しています. これらを解釈しているのが, evaluate で始まる 以下のプライベートなメソッド群です.
evaluatePluginVersion evaluatePluginDependencies evaluatePluginLoadAfters evaluateProvidedArtefacts evaluatePluginEvictionPolicy evaluatePluginInfluencePolicy evaluateOnChangeListener evaluateObservedPlugins evaluatePluginStatus
実は grails の他の部分でも基本的な構造はこのようになっており, プログラマが .groovy で書いたコードが直接実行されるのではなく, それに対応するインタプリタがコードを解釈 実行します.
最後に XXXGrailsPlugin.groovy で定義して意味のあるプロパティをまとめると以下のよ うになります.
doWithDynamicMethods: 既出, クロージャ・プロパティ
watchedResource: 後出, プロパティ/静的プロパティ/フィールド evict: 既出, プロパティ/静的プロパティ/フィールド
status: 'enabled' または 'disabled' (大文字小文字問わず), プロパティ/静的プロパ ティ/フィールド
influences: 後出, このプラグインが影響を与える他のプラグインの名前の List, プロ パティ/静的プロパティ/フィールド
onChange: 後出, 変更があったときに実行されるクロージャ, プロパティ/静的プロパ ティ/フィールド
onConfigChange: 後出, 構成に変更があったときに実行されるクロージャ, プロパティ/ 静的プロパティ/フィールド
doWithWebDescriptor: 既出, クロージャ・プロパティ version: 既出, プロパティ
doWithSpring: 既出, クロージャ・プロパティ
doWithApplicationContext: 既出, クロージャ・プロパティ dependsOn: 既出, Map, プロパティ/静的プロパティ/フィールド artefacts: 既出, List, プロパティ
providedArtefacts: 既出, Collection, プロパティ/静的プロパティ/フィールド
ここで「プロパティ/静的プロパティ/フィールド」とある場合, メソッドやクロージャでも評価してくれない ことに注意. 全体にあまり統一されているとは言い難い.
変更監視
XXXGrailsPlugin.groovy で watchedResources (String あるいは List<String>) があれば, そこで指定したリソースが変化したときに onChange クロージャが呼ばれます
(DefaultGrailsPlugin#checkForChanges).
同じようにこのプラグインがリロードされた場合, influences で指定したプラグインもリ ロードされます.
メタ情報
プラグインを作成する (% grails package-plugin) と, プラグインに関するメタ情報を記 述した plugin.xml が生成されます. PluginMetaManager (インタフェース),
DefaultPluginMetaManager (実装クラス) は, そのメタ情報を扱うものです. PluginMetaManager
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/commons/org/codehaus/groovy/grails/plugins/PluginMetaManager.java DefaultPluginMetaManager
(http://svn.grails.codehaus.org/browse/grails/trunk/grails/src/commons/org/codehaus/groovy/grails/plugins/DefaultPluginMetaManager.java
マネージャの仕事
PluginManager の役割はプラグイン全体を束ねることにあります. まずは自分の管理下にあるプラグインに対する基本操作です.
GrailsPlugin getGrailsPlugin(name)
GrailsPlugin getGrailsPlugin(name, version) boolean hasGrailsPlugin(name)
これらはほぼ自明ですね.
次にプラグインのロード, 初期化などの仕事です. またこれらと密接に関連するのが, 変更 伝播の仕組みです.
void loadPlugins() boolean isInitialised() void refreshPlugin(name) void checkForChanges()
Collecetion getPluginObservers(GrailsPlugin) void informObservers(name, event)
loadPlugins() では, アプリケーションの GroogyClassLoader (通称 gcl) を使って, コ ア・プラグイン (標準で提供されるプラグイン) がユーザ・プラグイン (ユーザが追加した プラグイン) より先になるようにロードして, 登録します. この過程で, eviction, delayed
loading, observed plugin の登録などの処理も行われます.
また, ここで conf/Config.groovy に plugin.include, plugin.exclude エントリがあれば, それらもフィルタリングされます.
次にファサードとして, 管理下にあるプラグインの操作を呼び出す仕事があります. void doRuntimeConfiguration(RuntimeSpringConfiguration)
void doPostProcessing(ApplicationContext) void doWebDesecriptor(...)
void doDynamicMethods()
doRuntimeConfiguration() は各プラグインの doWithRuntimeConfiguration() を, doPostProcessing() は各プラグインの doWithApplicationContext() を,
doWebDescriptor() は各プラグインの doWithWebDescriptor() を, doDynamicMethods() は 各プラグインの doWithDynamicMethods() を, それぞれ呼び出しています.
最後にアーティファクトの管理があります. void doArtefactConfiguration()
void registerProvidedArtefacts(application)
アーティファクトは GrailsApplication が管理しているので, 各プラグインが提供する アーティファクトをアプリケーションに登録したり, 各プラグインの
doArtefactConfiguration() を呼んだり (これは結局 ArtefactHandler をアプリケーショ ンに登録) します.
UML
"http://wiki.metabolics.co.jp/index.php/Plugin" より作成 カテゴリ: Grails
最終更新 12:13, 2007年10月31日 (水)。
コンテンツはAttribution-NonCommercial-ShareAlike 2.1 Japan Licenseのライセンスで利用する ことができます。