Groovyの@grabってなんぞや?

Groovyで、JNAを使うのに調べたときに、以下のソースがあって
参考にさせてもらった。
Groovy+JNA

@Grab('net.java.dev.jna:jna:3.2.2')
import com.sun.jna.*;
import com.sun.jna.win32.*;

interface CLibrary extends Library {
  CLibrary INSTANCE = Native.loadLibrary("msvcrt", CLibrary.class);
   int _chdir(String dir);
}

CLibrary.INSTANCE._chdir(args[0])
println "pwd".execute().text

が、1つ疑問が残ったので、調べてみた。

1行目の@Grabってなんぞや??

http://docs.codehaus.org/pages/viewpage.action?pageId=138543162

Grapeは、モジュールのバージョン識別に関しては(用語の変更はありますが)、Ivyのやり方に従っています。


* group - モジュールが所属するモジュールグループ。MavenのgroupIdやIvyのOrganizationに相当。/groovy[x][\..*]^/ にマッチするグループは予約されていて、Groovyの標準モジュールとして特別な意味を持つ場合がある。
* module - ロードするモジュールの名前。MavenのartifactIdやIvyのartifactに相当。
* version - 利用するモジュールのバージョン。'1.1-RC3' のようなリテラルバージョンかIvyの範囲。例えば '[2.2.1,)' はバージョン2.2.1以降の意味。



ダウンロードされたモジュールは、キャッシュルート ~/.groovy/grape の下に、Ivyの標準メカニズムに従って保存されます。



使用方法
アノテーション
アノテーションが許されている場所であればどこでも、いくつでもgroovy.lang.Grabアノテーションを付けて、そのコードが特定のライブラリに依存していることをコンパイラに知らせることができます。これは、Groovyコンパイラのクラスローダにそのライブラリを追加する効果があります。このアノテーションは、スクリプト内の他のあらゆるクラス解決に先だって検出・評価されるので、@Grabアノテーションによって取り込まれたクラスも適切に解決されます。



import com.jidesoft.swing.JideSplitButton
@Grab(group='com.jidesoft', module='jide-oss', version='[2.2.1,2.3.0)')
public class TestClassAnnotation {
public static String testMethod () {
return JideSplitButton.class.name
}
}



対象クラス(スクリプト要素へのアノテーションの場合はScriptクラス)のstaticイニシャライザに、適切な grab(...) 呼び出しが追加されます。

ふむふむ



こんな感じか?
import com.sun.jna.*;
import com.sun.jna.win32.*;
@Grab(group='net.java.dev.jna', module='jna', version='3.2.7')
println org.codehaus.groovy.runtime.InvokerHelper.getVersion()
結果はエラー・・・・
[D:\workspace\groovy_SandBox]groovy GrabAnnotation.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, D:\workspace\groovy_SandBox\GrabAnnotation.groovy: 30: unexpected token: println @ line 30, column 1.
   println org.codehaus.groovy.runtime.InvokerHelper.getVersion()
   ^

1 error

おろ?



こうか??
@Grab(group='net.java.dev.jna', module='jna', version='3.2.7')
import com.sun.jna.*;
import com.sun.jna.win32.*;
println org.codehaus.groovy.runtime.InvokerHelper.getVersion()
結果はエラー・・・・
[D:\workspace\groovy_SandBox\]groovy GrabAnnotation.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, D:\workspace\groovy_SandBox\GrabAnnotation.groovy: 27: unexpected token: import
@ line 27, column 1.
   import com.sun.jna.*;
   ^

1 error

あれ??



なんか構文間違ってる?@grabを抜かす
import com.sun.jna.*;
import com.sun.jna.win32.*;

println org.codehaus.groovy.runtime.InvokerHelper.getVersion()
結果は正しく動く
[D:\workspace\groovy_SandBox]groovy GrabAnnotation.groovy
1.6.5
Groovy 1.7.5だと?
import com.sun.jna.*;
import com.sun.jna.win32.*;
@Grab(group='net.java.dev.jna', module='jna', version='3.2.7')

println org.codehaus.groovy.runtime.InvokerHelper.getVersion()
結果はエラー・・・
1.7.5
[D:\workspace\groovy_SandBox]groovy GrabAnnotation.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
D:\workspace\groovy_SandBox\GrabAnnotation.groovy: 31: unexpected token: println @ line 31, column 1.
   println org.codehaus.groovy.runtime.InvokerHelper.getVersion()
   ^

1 error

ダメじゃん



(最初に戻す)@grabが先ならどうだ?
@Grab(group='net.java.dev.jna', module='jna', version='3.2.7')
import com.sun.jna.*;
import com.sun.jna.win32.*;

println org.codehaus.groovy.runtime.InvokerHelper.getVersion()
うーむ動いた。 ( ̄Д ̄;;
[D:\workspace\groovy_SandBox]groovy GrabAnnotation.groovy
1.7.5
1.6.5で確認

1.7.5で動作した以下のソースを1.6.5で確認してみる。

@Grab(group='net.java.dev.jna', module='jna', version='3.2.7')
import com.sun.jna.*;
import com.sun.jna.win32.*;

println org.codehaus.groovy.runtime.InvokerHelper.getVersion()

おかしいな@grabが対応されたのは、1.6のはずだし。。。
1.6.5のバグ??

1.6.5で確認

1.6系で確認してみる。

バージョン 結果
1.6.0 エラー
1.6.1 エラー
1.6.2 エラー
1.6.3 エラー
1.6.4 エラー
1.6.5 エラー
1.6.6 エラー
1.6.7 エラー
1.6.8 エラー
1.6.9 エラー

・・・( ̄. ̄;)エット( ̄。 ̄;)アノォ( ̄- ̄;)ンー なにか間違ってる??



grape listで確認

grape listってので確認が出来るみたい。

[D:\workspace\groovy_SandBox]groovy -v
Groovy Version: 1.6.5 JVM: 1.6.0_12
[D:\workspace\groovy_SandBox]grape list

net.java.dev.jna jna  [3.2.5, 3.2.7]

1 Grape modules cached
2 Grape module versions cached
[D:\workspace\groovy_SandBox]groovy -v
Groovy Version: 1.7.5 JVM: 1.6.0_12
[D:\workspace\groovy_SandBox]grape list

net.java.dev.jna jna  [3.2.5, 3.2.7]

1 Grape modules cached
2 Grape module versions cached

( ̄ー ̄?).....??ありゃ??よく分からん。




Groovy 1.7.5で続きを試す

シングルクォートが正式っぽいが、ダブルクォートでもよさそう
@Grab(group='net.java.dev.jna', module='jna', version='3.2.7')
@Grab(group="net.java.dev.jna", module="jna", version="3.2.7")
XXX以降と指定する場合
@Grab(group='net.java.dev.jna', module='jna', version='[3.2.7,)')
1.7.5で追加された短縮記法(シンタックスシュガー)
@Grab('net.java.dev.jna:jna:3.2.7')
@Grab('net.java.dev.jna:jna:[3.2.7,)')


1.7系の書き方はわかった。
どなたか、Groovy 1.6系での@grab使い方についてコメントください。m(_ _)m





実行環境

  • OS:Windows XP
  • Groovy Version: 1.6.0〜1.6.9、1.7.5
  • JVM: 1.6.0_12














Groovyの詳細についてはJavadocと以下の書籍を参考にしている。

Groovyイン・アクション
Dierk Konig Andrew Glover Paul King Guillaume Laforge Jon Skeet
毎日コミュニケーションズ
売り上げランキング: 294340



Groovyイン・アクションを読むならあった方が便利かな。

ブックストッパー

トモエ算盤
売り上げランキング: 614


薄い本は「ほんたった」で立ててる