16.02.2015 Aufrufe

gmagazine_8

gmagazine_8

gmagazine_8

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

Magazine<br />

vol.8<br />

Japan Grails/Groovy User Group


Contents<br />

Series 10<br />

Groovy 臨 機 応 変 ( 第 三 回 )<br />

〜 Groovy 2.3 の 新 機 能 〜… …………………………… 2<br />

Groovy 臨 機 応 変 ( 第 四 回 )<br />

〜 Groovy 2.4 の 新 機 能 〜… …………………………… 7<br />

Series 16<br />

Gradle Plugin 探 訪<br />

~ 第 1 回 Gradle SSH Plugin ~………………………… 9<br />

Series 05<br />

Grails Plugin 探 訪<br />

〜 第 9 回 CodeNarc plugin 〜… ……………………… 14<br />

Information<br />

リリース 情 報 …………………………………………… 19


G*Magazine vol.8<br />

Groovy 臨 機 応 変 ( 第 三 回 )<br />

〜Groovy 2.3の 新 機 能 〜<br />

series<br />

10<br />

上 原 潤 二 (うえはら じゅんじ)<br />

NTT ソフトウェア 株 式 会 社 Grails 推 進 室 所 属 。JGGUG( 日 本 Grails/Groovy ユーザ 会 ) 運 営 委 員 。<br />

「Grails 徹 底 入 門 」( 翔 泳 社 )、「プログラミング GROOVY」( 技 術 評 論 社 ) 執 筆 メンバーの 1 人 。<br />

Groovy 技 術 に 関 するブログ「Gr な 日 々」を 主 宰 している。<br />

今 回 は、Groovy 2.3の 新 機 能 をピックアップして 紹 介 します。<br />

詳 しくはリリースノートを 参 照 ください。<br />

トレイト (Traits)<br />

Groovy 2.3における 目 玉 機 能 としてトレイトが 導 入 されまし<br />

た。Groovyのトレイトは、 実 装 の 継 承 が 可 能 なインターフェー<br />

スです。Java8では、インターフェースにおいて、サブクラスで<br />

定 義 しなかった 場 合 の「デフォルトのメソッド」を 定 義 すること<br />

ができるようになりましたが、Groovyのトレイトも 同 種 の 機 構<br />

であると 言 えます。しかし、Groovyのトレイトは、メソッド 以<br />

外 にもメンバー 変 数 を 定 義 ・ 使 用 したり、Proxyを 経 由 した 動 的<br />

な 実 装 をすることができます。またJDK7 以 前 のJava 上 でも 利 用<br />

することもでき、より 強 力 な 機 構 であると 言 えます。Groovyの<br />

トレイトはScalaのトレイトと 似 ています。 詳 しくは 以 下 を 参 照<br />

ください。<br />

( 参 考 リンク)<br />

• http://beta.groovy-lang.org/docs/groovy-2.3.0/html/<br />

documentation/core-traits.html<br />

• http://www.slideshare.net/uehaj/groovy-trait<br />

新 規 AST 変 換 の 導 入<br />

@TailRecursive, @Builder, @Sortable, @SourceURI の 4 つ の AST<br />

変 換 が 導 入 されました。 以 下 にそれぞれの 説 明 を 示 します。<br />

@TailRecursive<br />

メソッドの 自 己 再 帰 呼 び 出 しをループに 変 換 します。メソッド<br />

を 跨 った 相 互 末 尾 再 帰 等 には 対 応 していないなどいくつかの 制 約<br />

があります。<br />

以 下 の 自 己 末 尾 再 帰 呼 び 出 しを 含 むコードに@TailRecursiveを<br />

適 用 してみます。<br />

@TailRecursive<br />

def foo(int n, int lim) {<br />

if (n < lim) {<br />

foo(n+1, lim)<br />

}<br />

else {<br />

n<br />

}<br />

}<br />

上 は 以 下 のようにループに 変 換 されます。<br />

@groovy.transform.TailRecursive<br />

public java.lang.Object foo(int n, int lim) {<br />

_lim_ = lim<br />

_n_ = n<br />

while (true) {<br />

try {<br />

if ( _n_ < _lim_ ) {<br />

java.lang.Integer __n__ = _n_<br />

java.lang.Integer __lim__ = _lim_<br />

_n_ = __n__ + 1<br />

_lim_ = __lim__<br />

continue<br />

} else {<br />

return _n_<br />

}<br />

}<br />

catch (org.codehaus.groovy.transform.<br />

tailrec.GotoRecurHereException ignore) {<br />

continue<br />

}<br />

finally {<br />

}<br />

}<br />

return null<br />

}<br />

繰 り 返 し 数 に 比 例 してスタックを 消 費 することがなくなるの<br />

で、スタックオーバーフローを 気 にすることなく、 適 切 な 場 合 に<br />

は 再 帰 呼 び 出 しでわかりやすくロジックを 書 くことができます。<br />

2 Groovy 臨 機 応 変 ( 第 三 回 )〜 Groovy 2.3 の 新 機 能 〜


G*Magazine vol.8<br />

( 参 考 リンク)<br />

• http://beta.groovy-lang.org/docs/latest/html/gapi/groovy/<br />

transform/TailRecursive.html<br />

@Builder<br />

インスタンスを 初 期 化 するための、フルーエントなメソッド 呼<br />

び 出 しによるビルダパターンを 可 能 とする AST 変 換 です。<br />

使 用 例 を 以 下 に 示 します。<br />

import groovy.transform.builder.Builder<br />

@Builder<br />

class Book {<br />

int price<br />

String title<br />

}<br />

import groovy.transform.Sortable<br />

@Sortable<br />

class Book {<br />

int price<br />

String title<br />

}<br />

data = [new Book(price:10, title:"abc"),<br />

new Book(price:9, title:"def")]<br />

Collections.sort(data)<br />

assert data[0].price == 9 && data[0].title == "def"<br />

assert data[1].price == 10 && data[1].title == "abc"<br />

def book = Book.builder().price(100).title(" 我 輩<br />

は 猫 である").build()<br />

上 記 以 外 に、いくつかのパターンでのサポートメソッドをAST<br />

変 換 の 引 数 で 指 定 することもできます。たとえば、setterをチェ<br />

インさせていくようなパターンのビルダメソッドを 生 成 すること<br />

もできます。<br />

( 参 考 リンク)<br />

• http://beta.groovy-lang.org/docs/latest/html/gapi/groovy/<br />

transform/builder/Builder.html<br />

@Sortable<br />

指 定 したクラスに 対 して 以 下 を 行 います。<br />

( 参 考 リンク)<br />

• http://beta.groovy-lang.org/docs/latest/html/gapi/groovy/<br />

transform/Sortable.html<br />

@SourceURI<br />

StringやURLクラス 型 の 変 数 定 義 に 指 定 すると、その 変 数 の 値<br />

に Groovy スクリプト 自 身 の URI が 初 期 設 定 されます。<br />

import groovy.transform.SourceURI<br />

@SourceURI String src<br />

println src<br />

• compareTo メソッドを 生 成 し、インターフェース Comparable<br />

を 実 装 する。<br />

• それぞれのフィールドに 関 して 比 較 するComparatorを 返 すメ<br />

ソッド (comparatorByXXX()) を 生 成 する。<br />

• → 返 されたComparator は、java.util.Collections.sort(List list,<br />

Comparator c) や、java.util.Arrays.sort(T[] a, Comparator<<br />

super T> c) に 渡 してソート 処 理 に 適 用 できる。<br />

コード 例 を 以 下 に 示 します。<br />

上 記 のスクリプトを、ファイルに 保 存 して 実 行 するとfile:で<br />

始 まるURIが 表 示 されます。あるいは、スクリプトをWebサー<br />

バに 置 き、URLを 指 定 してgroovyコマンドを 実 行 すると、その<br />

URL が 表 示 されます。さらに、 以 下 のように -e オプションでスク<br />

リプトを 指 定 したり、GroovhShell.evaluate(String) でスクリプト<br />

を 実 行 すると、@SourceURI は data: で 始 まるデータ URI を 生 成 し<br />

ます。<br />

$ groovy -e 'import groovy.transform.SourceURI; @<br />

SourceURI String src; println src'<br />

data:,import%20groovy.transform.SourceURI;%20@<br />

SourceURI%20String%20src;%20println%20src<br />

( 参 考 リンク)<br />

• http://beta.groovy-lang.org/docs/latest/html/gapi/groovy/<br />

transform/SourceURI.html<br />

Groovy 臨 機 応 変 ( 第 三 回 )〜 Groovy 2.3 の 新 機 能 〜<br />

3


G*Magazine vol.8<br />

ライブラリの 拡 張 ・ 改 善<br />

パラメータ<br />

説 明<br />

■■マークアップテンプレートエンジン<br />

新 種 のテンプレートエンジン、マークアップテンプレートエン<br />

ジン (groovy.text.markup.MarkupTemplateEngine) が 追 加 されま<br />

した。マークアップテンプレートエンジンは、DOM 的 な 構 造 を<br />

記 述 するための DSL の 一 種 であるとも 言 えます。 参 考 リンクにあ<br />

る 例 を 以 下 に 示 します。<br />

yieldUnescaped ''<br />

html(lang:'en') {<br />

head {<br />

meta('http-equiv':<br />

'"Content-Type" content="text/html; charset=utf-8"')<br />

title('My page')<br />

}<br />

body {<br />

p('This is an example of HTML contents')<br />

}<br />

}<br />

これは 以 下 のような XML を 生 成 するとのことです。<br />

My pageThis is an example of HTML<br />

contents<br />

マークアップテンプレートエンジンは、MarkupBuilderと 同 様<br />

に、クロージャや 疑 似 メソッドの 呼 び 出 しを 使 用 してツリー 構 造<br />

を 記 述 ・ 構 築 し、 文 字 列 表 現 に 落 とすことができます。 加 えて、<br />

以 下 の 特 長 があります。<br />

• 静 的 コンパイルで 高 速 化<br />

• 静 的 型 チェックが 可 能<br />

• 整 形 ( インデント、エスケープ ) 機 能 付 き<br />

• テンプレート 記 述 を 別 ファイルにして include なども 可 能<br />

( 参 考 リンク)<br />

• http://beta.groovy-lang.org/docs/groovy-2.3.1/html/<br />

documentation/markup-template-engine.html<br />

■■JSON Slurper<br />

Groovy 2.3ライブラリではいくつかの 性 能 改 善 がなされてお<br />

り、 特 に、JSON 処 理 が 従 来 より 最 大 20 倍 高 速 化 され、Javaベー<br />

スのライブラリの 中 で 最 速 の 部 類 となっているとのことです。<br />

JSON Slurper については、 以 下 のパラメータを 指 定 できるよう<br />

になりました。<br />

INDEX_OVERLAY<br />

高 速 。REST 呼 び 出 し・WebSocket メッ<br />

セージ・AJAX などに 適 している。シ<br />

リアライズされたオブジェクトの 展<br />

開 処 理 を 特 に 高 速 化 している。<br />

LAX コメントや、クオート 無 しのマップ<br />

のキーを 許 す。<br />

CHAR_BUFFER<br />

CHARACTER_SOURCE<br />

int,date,long などの 貪 欲 (eager) な<br />

パース 処 理 が 特 長 。 既 存 の Slurper の<br />

動 作 に 近 い。<br />

2MB を 越 える JSON ファイルの 処 理 に<br />

適 する。<br />

これらのパラメータは 以 下 のように 指 定 します( 参 考 リンクに<br />

示 した API リファレンスより 引 用 )。<br />

parser = new JsonSlurper().setType(<br />

JsonParserType.INDEX_OVERLAY );<br />

( 参 考 リンク)<br />

• http://beta.groovy-lang.org/docs/groovy-2.3.0/html/gapi/<br />

groovy/json/JsonParserType.html<br />

■■ConfigSlurper の 拡 張<br />

Grails で 定 義 されていて 利 用 可 能 であるような、prod/dev/test<br />

といった「 環 境 」を、 新 たに 定 義 し 指 定 できるようになりました。<br />

( 参 考 リンク)<br />

• http://mrhaki.blogspot.jp/2014/05/groovy-goodness-extendconfigslurper.html<br />

Java8,7 の 対 応<br />

■■Java8<br />

実 行 環 境 として JDK 8 が 公 式 にサポートされました。<br />

■■Java7<br />

Java 7 の NIO2 に 対 応 しました。 例 えば、いくつかの GDK メソッ<br />

ドで、java.io.File の 代 りに java.io.Path クラスが 使 用 できます。<br />

以 下 はリリースノートからの 例 です。<br />

path.withReader { Reader r -> ... }<br />

path.eachLine { String line -> ... }<br />

path.eachFileRecurse { Path p -> ... }<br />

path


G*Magazine vol.8<br />

JUnit 4 対 応<br />

groovy.test.GroovyAssert に 以 下 の 静 的 メソッドが 追 加 されました (GROOVY-6588)。これらは、 従 来 より GroovyTestCase のインスタ<br />

ンスメソッドとしては 対 応 するものが 定 義 されていたのですが、JUnit4でテストクラスをGroovyTestCaseから 継 承 させない 場 合 に 使<br />

用 するための、 静 的 メソッドが 定 義 されたクラス groovy.test.GroovyAssert では 定 義 されていませんでした。<br />

メソッド<br />

説 明<br />

static void assertScript(String script) 文 字 列 のスクリプトを 実 行 結 果 を assert する<br />

static boolean notYetImplemented(Object caller) 試 験 の 成 功 / 失 敗 を 逆 転 させて 扱 う (Fail なら Pass とし、Pass なら Fail とする。<br />

static Throwable shouldFail(Class clazz, String script) 文 字 列 のスクリプトを 実 行 し 指 定 した 例 外 が 発 生 したら Pass とする<br />

static Throwable shouldFail(String script) 文 字 列 のスクリプトを 実 行 し 例 外 が 発 生 したら Pass とする<br />

Closure 引 数 に 対 する 静 的 型 チェック<br />

従 来 、クロージャを 引 数 としてとるメソッドにおいて、クロー<br />

ジャ 型 の 引 数 の 引 数 に 型 を 宣 言 する 方 法 がありませんでした。<br />

例 えば、<br />

void foo(Closure clos) {<br />

// クロージャclos の「 引 数 の 型 」を 宣 言 する 方 法 がない。<br />

clos("ABC")<br />

// 引 数 clos のクロージャには、 常 に 1 つの 文 字 列 が 引 数<br />

として 与 えられるのだが…。<br />

}<br />

というメソッドが 定 義 されているとき、 以 下 のコード:<br />

@TypeChecked<br />

def func() {<br />

foo { it -> it.toUpperCase()<br />

// 静 的 型 エラー。it の 型 は Object とみなされる。<br />

}<br />

}<br />

は、クロージャ 引 数 itの 型 を 知 る 方 法 が 無 く、itに 対 する<br />

toUpperCase()の 呼 び 出 しが 静 的 型 チェックや 静 的 コンパイルで<br />

エラーになるので、 以 下 のように 型 を 指 定 する 必 要 がありました。<br />

foo { String it -><br />

it.toUpperCase()<br />

}<br />

しかし、foo の 宣 言 時 に @ClosureParam を 以 下 のように 使 用 す<br />

ることで、itの 型 は 推 論 されるようになり、 型 を 明 示 的 に 指 定 す<br />

る 必 要 がなくなります。<br />

void foo(@ClosureParams(value=SimpleType.class,<br />

options="java.lang.String") Closure clos) {<br />

clos("ABC")<br />

}<br />

話 はジェネリクスが 入 ってくるともうちょっとややこしくなり<br />

ます [1] 。 次 の 例 です。<br />

["a","b","c"].collect { it.toUpperCase() }<br />

この 場 合 、「クロージャの 引 数 の 型 」は、レシーバの List の「 要<br />

素 の 型 」と 一 致 していなければなりません。<br />

collect は、GDK メ ソ ッ ド と し て、DefaultGroovyMethods.<br />

java(DGM) 中 で、 以 下 のように 定 義 されています。<br />

public static List collect(Collection<br />

self,<br />

@ClosureParams(FirstParam.FirstGenericType.class)<br />

Closure transform) {<br />

return (List) collect(self,<br />

new ArrayList(self.size()), transform);<br />

}<br />

「@ClosureParams(FirstParam.FirstGenericType.class)<br />

transform」では、クロージャの 引 数 transform の 引 数 の 型 は、 第<br />

一 引 数 (FirstParam)すなわちレシーバであるコレクションselfの<br />

ジェネリックス 型 引 数 (S) である、と 宣 言 しています。ちなみに T<br />

はクロージャの 戻 り 値 の 型 です。<br />

@ClosureParamsを 使 用 することで、ライブラリ 側 の 定<br />

義 は 煩 雑 になりますが、それを 呼 び 出 すコードにおいて@<br />

TypeChecked、@CompileStatic はより 賢 く 振 舞 うようになり、<br />

コードを 簡 潔 にすること、 及 び 動 的 Groovyコードに 適 用 した 際<br />

の 修 正 を 減 らすことに 貢 献 してくれます。<br />

なお、Groovy 2.4 beta 4 では、 同 様 の 指 定 が @DelegatesTo ア<br />

ノテーションでも 可 能 になりました。(GROOVY-6956)<br />

( 参 考 リンク)<br />

• http://melix.github.io/blog/2014/01/closure\_param\_<br />

inference.html<br />

• [1] Java8ではGenericsの 引 数 型 に 対 してアノテーションが 付<br />

与 できるようになったので、このような 間 接 的 な 指 定 方 法 では<br />

なく 直 接 指 定 できるはずである。あるいはGroovy 自 体 の 拡 張<br />

で 同 種 の 指 定 も 可 能 であっただろう。しかしながら、Groovy<br />

のコンパイル・ 動 作 環 境 はJava8には 限 定 されておらず、ま<br />

た ClosureParams を 使 用 す る 主 な 場 所 は Java で 定 義 さ れ た<br />

DGM(DefaultGroovyMethods.java) で あ る た め、Java 7 以 前 で<br />

も 使 用 できるこの 方 法 が 採 用 された。<br />

Groovy 臨 機 応 変 ( 第 三 回 )〜 Groovy 2.3 の 新 機 能 〜<br />

5


G*Magazine vol.8<br />

ツールの 拡 張<br />

■■Groovysh の 拡 張 と 変 更<br />

Groovyshは 着 々と 拡 張 されています。まず、 補 完 が 賢 くなり<br />

ました(GROOVY-6399,GROOVY-6395)。たとえば、マップのキー<br />

を 補 完 できるようになりました。<br />

% groovysh<br />

groovy:000> m = [abc:123, def:456]<br />

groovy:001> m.a [ タブを 押 す ]<br />

any( abc<br />

groovy:001> m.ab [ タブを 押 す ]<br />

groovy:001> m.abc // 補 完 される<br />

この 機 能 は、DOMツリーやASTなど、ツリーをたどりながら<br />

表 示 させる 場 合 に 絶 大 な 効 果 を 発 揮 します。<br />

また、 機 能 の 変 更 として、groovysh 中 でのコマンド (load, edit,<br />

aliasなど)にはプリフィックス「:」が 必 要 となりました。 変 数 名<br />

や 関 数 名 と 重 なることがなくなります。 (GROOVY-6397)<br />

% groovysh<br />

groovy:000> :load test.groovy // 従 来 はコロン 無 し<br />

の「load」で 実 行 していた<br />

■■GroovyConsole の 拡 張<br />

GroovyConsole には 以 下 の 拡 張 がなされています。<br />

• プリファレンスAPIを 通 じてフォントが 指 定 できるようになっ<br />

たとのことです。ただしフォント 指 定 のためのGUIはまだ 用 意<br />

されていません。(GROOVY-6303)<br />

• 選 択 範 囲 で 実 行 (Run Selection) したときに、import 文 を 意 識<br />

してくれるようになりました。つまり、 選 択 範 囲 にimport 文<br />

が 含 まれていなくても、 同 じソース 中 の 冒 頭 位 置 などに 含 まれ<br />

ているimportがあたかも 選 択 範 囲 中 にも 指 定 されているかの<br />

ように 解 釈 して 実 行 してくれます。<br />

• コメント・コメント 解 除 の 機 能 とショートカットキーが 追 加 さ<br />

れました。(GROOVY-6459)<br />

ドキュメントの 改 善<br />

その 他 、ドキュメントが 抜 本 的 に 改 善 されています。 改 善 され<br />

た 内 容 は、 現 時 点 ではGroovyのβ 版 ドキュメントページで 公 開<br />

されていますが、 将 来 的 には 公 式 サイトの 内 容 に 置 換 されます。<br />

( 参 考 リンク)<br />

• http://beta.groovy-lang.org/download.html<br />

6 Groovy 臨 機 応 変 ( 第 三 回 )〜 Groovy 2.3 の 新 機 能 〜


G*Magazine vol.8<br />

Groovy 臨 機 応 変 ( 第 四 回 )<br />

〜Groovy 2.4の 新 機 能 〜<br />

series<br />

10<br />

上 原 潤 二 (うえはら じゅんじ)<br />

NTT ソフトウェア 株 式 会 社 Grails 推 進 室 所 属 。JGGUG( 日 本 Grails/Groovy ユーザ 会 ) 運 営 委 員 。<br />

「Grails 徹 底 入 門 」( 翔 泳 社 )、「プログラミング GROOVY」( 技 術 評 論 社 ) 執 筆 メンバーの 1 人 。<br />

Groovy 技 術 に 関 するブログ「Gr な 日 々」を 主 宰 している。<br />

今 回 は、Groovy 2.4の 新 機 能 を、 現 時 点 で 公 開 されている<br />

Groovy 2.4 beta4までのリリースノートから 抜 粋 して 紹 介 します。<br />

正 式 リリースまでにはさらに 機 能 が 追 加 されるでしょうから、<br />

正 確 には Groovy 2.4 の 機 能 の 一 部 ということになります。<br />

( 参 考 リンク)<br />

• https://jira.codehaus.org/secure/ReleaseNote.jspaprojectId=1<br />

0242&version=20369<br />

• https://jira.codehaus.org/secure/ReleaseNote.jspaprojectId=1<br />

0242&version=20433<br />

• https://jira.codehaus.org/secure/ReleaseNote.jspaprojectId=1<br />

0242&version=20544<br />

• https://jira.codehaus.org/secure/ReleaseNote.jspaprojectId=1<br />

0242&version=20612<br />

Android 対 応<br />

Groovy 2.4ではAndroidアプリケーションを 開 発 できるよう<br />

になりました。GroovyをAndroidで 動 作 させるための 試 みは 過<br />

去 にもいくつかありましたが、 今 回 はパッチなどではなく、 公<br />

式 のGroovyメインラインで 対 応 されているのが 特 徴 です。 基 本<br />

的 には、Static Compile 配 下 で 動 作 する 機 能 を 使 用 します。この<br />

Android 対 応 に 合 せて SwissKnife、grooid-tools などの 開 発 用 ラ<br />

イブラリもでてきています。(GROOVY-6861)<br />

( 参 考 リンク)<br />

• https://github.com/Arasthel/SwissKnife<br />

• https://github.com/karfunkel/grooid-tools<br />

ライブラリの 拡 張<br />

toUnique(),toSorted() の 追 加 。<br />

Listなど、Iterableなコレクションに 対 するGDKメソッドの 追<br />

加 です。(GROOVY-6945)<br />

従 来 からJDKに 存 在 したList#sort()は 破 壊 的 操 作 でしたが、<br />

toSorted はイミュータブルな、「ソートしたものを 返 す 操 作 」です。<br />

また、toUnique() も 同 様 に、 重 複 要 素 を 削 除 したものを 返 し、も<br />

とのコレクションを 変 更 しません。またこれらはIterableなコレ<br />

クション 一 般 もしくは 配 列 に 対 する 適 用 も 可 能 です。<br />

Java8では、コレクションに 対 するsortメソッドが 新 規 に 追 加<br />

されましたが、GDK の sort と 名 前 が 被 るので、 混 乱 を 避 けるため<br />

にという 意 味 合 いもあるようです。<br />

例 )<br />

assert [4,1,2,2,3,3,4].toUnique() == [4,1,2,3]<br />

assert [4,1,2,2,3,3,4].toSorted() == [1,2,2,3,3,4,4]<br />

■■init(), dropRight()、takeRight() の 追 加<br />

Scala の 同 名 メソッドの 導 入 です。(GROOVY-6867)<br />

メソッドの 説 明 を 以 下 に 示 します。<br />

メソッド 意 味 例 (a = [1,2,3] のとき )<br />

init() 末 尾 以 外 。 assert a.init()==[1,2]<br />

dropRight() 末 尾 の 指 定 個 数 を 削 除 assert a.dropRight(2) == [1]<br />

takeRight() 末 尾 の 指 定 個 数 を 取 得 assert a.takeRight(2) == [2,3]<br />

■■System.currentTimeSecond() の 追 加<br />

エポックからの 経 過 「 秒 数 」を 返 すメソッドSystem.<br />

currentTimeSecond() が 追 加 さ れ ま し た。JDK の System.<br />

currentTimeMillis の 1000 分 の 1 を 返 します。(GROOVY-6294)<br />

groovy:000> System.currentTimeSeconds()<br />

===> 1416000159<br />

groovy:000> System.currentTimeMillis()<br />

===> 1416000167901<br />

Groovysh の 拡 張<br />

groovysh が 地 道 に 拡 張 されています。<br />

• groovyshではメソッド 補 完 が 効 くようになっているのです<br />

が、 補 完 候 補 の 表 示 にANSIのエスケープシーケンスを 使 っ<br />

て、インスタンスメソッドはボールド 表 示 、staticメソッドや<br />

superクラスのメソッドは 通 常 表 示 となるようになりました。<br />

(GROOVY-6563)<br />

• 以 前 の Groovysh では、 行 の 単 位 で Groovy の 式 を 評 価 するため、<br />

シェル 変 数 以 外 の 型 宣 言 した 変 数 を 行 をまたがって 使 用 するこ<br />

とができませんでしたが、 可 能 となります。(GROOVY-6623)<br />

Groovy 臨 機 応 変 ( 第 四 回 )〜 Groovy 2.4 の 新 機 能 〜<br />

7


G*Magazine vol.8<br />

( 例 ) 以 下 が 可 能 となる。<br />

String s = "abc"<br />

println s<br />

• groovysh の 起 動 時 に、-e オプションで 任 意 の Groovy コードを<br />

実 行 できるようになりました。また、コマンドラインに 指 定 し<br />

た groovy スクリプトを 読 み 込 むようになりました。<br />

( 例 )<br />

> cat test.groovy<br />

println "hello"<br />

> groovysh -e 'println 1+1' test.groovy<br />

Groovy Shell (2.4.0-beta-3, JVM: 1.8.0_25)<br />

Type ':help' or ':h' for help.<br />

-------------------------------------------------<br />

------------------------------------<br />

groovy:000> println 1+1<br />

2<br />

===> null<br />

groovy:000> :load test.groovy<br />

hello<br />

===> null<br />

groovy:000><br />

SelfType アノテーション<br />

トレイトの 定 義 において、そのトレイトを 実 装 するクラスが<br />

実 装 していなけれならないクラスもしくはインターフェースを @<br />

SelfTypeというアノテーションで 指 定 できるようになりました。<br />

SelfTypeアノテーションによって、 以 下 の 利 点 が 得 られるように<br />

なります。<br />

• トレイトが、どんなクラス・インターフェース(およびそのサ<br />

ブクラス)に 注 入 可 能 であるかを 制 約 する。この 制 約 を 満 して<br />

いないクラスがそのトレイトを 実 装 しようとするとコンパイル<br />

エラーとなる。<br />

• その 結 果 、トレイトで 定 義 するメソッド 中 で、 使 用 できるはず<br />

のメソッド 群 が 静 的 に 予 期 できるようになり、 実 装 クラスのメ<br />

ソッドを 自 由 に 呼 び 出 せる。<br />

• トレイトのメソッド 中 でのthisの 型 が 静 的 に 確 定 するので、<br />

thisを 他 のメソッドに 渡 す 際 などに 静 的 型 チェック 可 能 にな<br />

る。<br />

import groovy.transform.*<br />

import java.util.concurrent.CopyOnWriteArrayList<br />

@CompileStatic<br />

@SelfType(List)<br />

trait LispLikeList {<br />

Object car() {<br />

first()<br />

}<br />

Collection cdr() {<br />

tail()<br />

}<br />

}<br />

class LispLikeCoWList extends<br />

CopyOnWriteArrayList implements LispLikeList {<br />

LispLikeCoWList(list) {<br />

super(list)<br />

}<br />

}<br />

def list1 = new LispLikeCoWList([1,2,3])<br />

assert list1.car() == 1<br />

assert list1.cdr() == [2,3]<br />

( 参 考 リンク)<br />

- http://docs.groovy-lang.org/2.4.0-beta-4/html/<br />

documentation/core-traits.html#_self_types<br />

Macro Groovy<br />

その 他 、AST 変 換 におけるASTの 生 成 を 簡 易 に 書 けるようにす<br />

る「Macro Groovy」 機 能 の、Groovy 公 式 機 能 としての 導 入 が 検<br />

討 されています。この 過 程 で、ASTの 木 のパターンマッチングサ<br />

ポートも 検 討 されているようです。<br />

( 参 考 リンク)<br />

• https://github.com/bsideup/MacroGroovy<br />

• http://groovy.329449.n5.nabble.com/State-of-the-macrostd5721429.html#a5721475<br />

要 は、トレイトと 静 的 Groovy(@CompileSattic, @TypeChecked)<br />

との 相 性 がより 高 まったということです。<br />

コード 例 は 以 下 のとおり。<br />

Groovy 2.4 正 式 版 は 本 記 事 執 筆 後 に 公 開 されました。 冒 頭<br />

にお 断 りしているように、Groovy 2.4 正 式 版 では 本 記 事 で<br />

記 載 した 以 外 にも 多 数 の 機 能 が 追 加 されております。また、<br />

Macro Groovy の 採 用 は 2.4.0 時 点 では 見 送 られています。 悪<br />

しからずご 了 承 ください。<br />

( 参 考 リンク )<br />

http://docs.codehaus.org/display/GROOVY/Groovy+2.4+release+notes<br />

8 Groovy 臨 機 応 変 ( 第 四 回 )〜 Groovy 2.4 の 新 機 能 〜


G*Magazine vol.8<br />

Gradleプラグイン 探 訪<br />

〜 第 1 回 Gradle SSH Plugin〜<br />

series<br />

16<br />

須 江 信 洋 (すえ のぶひろ)<br />

日 本 Grails/Groovy ユーザーグループ サポートスタッフ。『Groovy イン ・ アクション』( 毎 日 コミュニケーションズ) 翻 訳<br />

チーム、および『プログラミング GROOVY』( 技 術 評 論 社 )「Gradle 徹 底 入 門 ( 翔 泳 社 )」 執 筆 チームの 一 員 。 本 稿 は 著 者<br />

個 人 の 考 えおよび 経 験 に 基 づいて 記 述 したものであり、 所 属 する 会 社 や 組 織 の 意 見 を 表 すものではありません<br />

Gradle SSH Plugin は、Gradle のビルドスクリプトから SSH に<br />

よるリモート 操 作 や、SFTPによるファイル 転 送 を 行 うためのプ<br />

ラグインです。ビルドプロセスにおけるファイル 転 送 やサービス<br />

起 動 ・ 停 止 など、さまざまな 操 作 を 自 動 化 することができます。<br />

操 作 対 象 のサーバーには SSH でアクセス 可 能 であればよく、 特<br />

別 なエージェントやデーモンなどを 導 入 する 必 要 がないため、 導<br />

入 の 敷 居 が 低 いことも 特 徴 です。 加 えて、パスワード 認 証 や 公 開<br />

鍵 認 証 、SSH エージェント、SOCKS プロキシ 対 応 など、さまざま<br />

な 利 用 パターンに 対 応 しています。<br />

また、Gradle SSH Plugin の SSH 接 続 機 能 だけを 単 体 で 切 り 出<br />

した Groovy SSH というライブラリも 提 供 されており、Gradle と<br />

は 無 関 係 に 単 体 のGroovyスクリプトから 利 用 することも 可 能 で<br />

す。<br />

クイックスタート<br />

開 発 者 の @int128 氏 がテンプレートプロジェクトを 提 供 してく<br />

れていますので、 参 考 にするとよいでしょう。<br />

本 稿 では、テンプレートプロジェクトに 少 し 手 を 入 れて<br />

VagrantでSSH 可 能 な 仮 想 マシンを 準 備 するサンプルを 用 意 しま<br />

したので、そちらを 利 用 してGradle SSH Pluginの 動 作 を 確 認 し<br />

てみましょう。 以 下 のコマンドでサンプルを 入 手 してください。<br />

git clone -b gmag-8 https://github.com/nobusue/<br />

gradle-ssh-plugin-template.git<br />

サンプルコード 内 のbuild.gradleは 以 下 のようになっていま<br />

す。<br />

Gradle SSH Plugin 概 要<br />

開 発 者 : @int128 ( いわてぃ ) 氏<br />

最 新 バージョン : 0.4.5 (2014/11/24 時 点 )<br />

プロジェクト Web サイト :<br />

• Gradle SSH Plugin [https://gradle-ssh-plugin.github.io/]<br />

• Groovy SSH [https://groovy-ssh.github.io/]<br />

ライセンス : Apache License Version 2.0<br />

本 プラグインのバージョン0.4.xはGradle2.0 以 降 が 必 要 です。<br />

Gradle1.xから 利 用 する 場 合 はバージョン0.3.xを 利 用 してくださ<br />

い。<br />

Gradle SSH Plugin を 使 うメリット<br />

Java で 実 装 された SSH ライブラリはいくつかありますが、 標 準<br />

入 出 力 の 処 理 など 低 レベルの 処 理 を 自 分 で 実 装 しなければなりま<br />

せん。<br />

Gradle SSH Plugin は 独 自 の DSL( 以 降 「SSL DSL」と 表 記 します )<br />

を 提 供 することでこのような 煩 雑 さをなくし、かつ 処 理 対 象 のグ<br />

ループ 化 などを 見 通 しよく 実 装 できるように 工 夫 されています。<br />

( 内 部 では JSch を 利 用 しています。)<br />

SSH DSL の 文 法 は Groovy SSH と 共 通 なので、Gradle から 利 用<br />

するだけでなく、 高 機 能 なシェルスクリプトのように 利 用 するこ<br />

とも 可 能 です。<br />

Gradle プラグイン 探 訪 〜 第 1 回 Gradle SSH Plugin 〜<br />

9


G*Magazine vol.8<br />

plugins {<br />

id 'org.hidetake.ssh' version '0.4.5'<br />

}<br />

合 は、remotes ブロックの 内 容 を 適 宜 修 正 してください。)<br />

vagrant up<br />

./gradlew showPlatformVersion<br />

remotes {<br />

targethost {<br />

host = '192.168.33.10'<br />

user = 'vagrant'<br />

identity = file("${System.properties['user.<br />

home']}/.vagrant.d/insecure_private_key")<br />

}<br />

}<br />

ssh.settings {<br />

logging = 'stdout'<br />

}<br />

task showPlatformVersion


G*Magazine vol.8<br />

:showPlatformVersion FAILED<br />

FAILURE: Build failed with an exception.<br />

* Where:<br />

Build file '/Users/nobusue/work/gmag/gradle-sshplugin-template/build.gradle'<br />

line: 21<br />

* What went wrong:<br />

Execution failed for task ':showPlatformVersion'.<br />

> assert uname.contains('precise64')<br />

| |<br />

| false<br />

Linux precise32 3.2.0-23-generic-pae<br />

#36-Ubuntu SMP Tue Apr 10 22:19:09 UTC 2012 i686<br />

i686 i386 GNU/Linux<br />

'uname -a' の 結 果 に 'precise64' が 含 まれていないため、assert<br />

が 失 敗 して 例 外 が 発 生 しています。<br />

これは 非 常 に 単 純 な 例 ですが、 例 えばシェルコマンドの 実 行 結<br />

果 をGroovyで 解 析 して、その 結 果 を 次 のシェルコマンドの 入 力<br />

として 渡 すことも 可 能 です。うまく 使 いこなすと、 非 常 に 高 度 な<br />

処 理 を 自 動 化 することができます。<br />

Gradle SSH Plugin の 機 能<br />

Gradle SSH Pluginは 多 くの 機 能 を 提 供 しているため、ここで<br />

は 特 に 利 用 頻 度 が 高 いと 思 われるものについてまとめます。<br />

詳 細 についてはユーザーガイドを 参 照 するとよいでしょう。<br />

また、SSH DSLの 利 用 方 法 についてはacceptance-test のコー<br />

ドも 参 考 になります。<br />

リモートホストおよび 接 続 定 義<br />

remotes ブロックで 定 義 します。remotes. で Remote 型 の<br />

オブジェクトとして 参 照 可 能 です。<br />

以 下 のパラメータを 指 定 できます。<br />

キー 型 説 明<br />

host String( 必 須 ) ホスト 名 or IP アド<br />

レス<br />

port Integer ポート 番 号 ( デフォ<br />

ルト 22)<br />

gateway Remote SSH ポートフォ<br />

ワードを 行 う<br />

proxy Proxy SOCKS/HTTP プロ<br />

キシを 指 定<br />

user String( 必 須 ) ユーザー 名<br />

password String パスワード<br />

identity File 秘 密 鍵 ファイル<br />

passphrase String 秘 密 鍵 のパスフ<br />

レーズ<br />

agent Boolean Putty or ssh-agent<br />

を 利 用<br />

knownHosts File known hosts<br />

ファイル ( デ<br />

フォルト ~/.ssh/<br />

known_hosts)<br />

allowAnyHosts 設<br />

定 時 はチェックを<br />

無 効 化<br />

retryCount Integer 接 続 リトライ 回 数<br />

( デフォルトはリト<br />

ライなし )<br />

retryWaitSec Integer リトライ 間 隔 ( 秒<br />

数 、デフォルト 0)<br />

プロキシ 定 義<br />

proxies ブロックで 定 義 します。proxies. で Proxy 型 のオブ<br />

ジェクトとして 参 照 可 能 です。SOCKSおよびHTTPに 対 応 してい<br />

ます。<br />

以 下 のパラメータを 指 定 できます。<br />

キー 型 説 明<br />

host String( 必 須 ) ホスト 名 or IP アド<br />

レス<br />

port Integer( 必 須 ) ポート 番 号<br />

type ProxyType( 必 須 ) プロキシのタイプ<br />

(SOCKS or HTTP)<br />

user String ユーザー 名<br />

password String パスワード<br />

socksVersion Integer SOCKS バージョン<br />

(4 or 5, デフォルト<br />

5)<br />

Gradle プラグイン 探 訪 〜 第 1 回 Gradle SSH Plugin 〜<br />

11


G*Magazine vol.8<br />

ロール 定 義<br />

role()でリモートサーバーを 役 割 ごとにグループ 化 できます。<br />

各 Remote に 対 してロールは 複 数 指 定 可 能 です。<br />

ssh.remotes {<br />

server1 {<br />

role('web')<br />

role('all')<br />

host = 'x.x.x.x'<br />

user = 'root'<br />

}<br />

server2 {<br />

role('web')<br />

role('all')<br />

host = 'y.y.y.y'<br />

user = 'root'<br />

}<br />

server2 {<br />

role('db')<br />

role('all')<br />

host = 'z.z.z.z'<br />

user = 'root'<br />

}<br />

}<br />

ロールを 定 義 しておくと、remotes.role() でリモートサーバー<br />

をまとめて 指 定 できます。<br />

ssh.run {<br />

session(remotes.role('web')) {<br />

// operations for web<br />

}<br />

session(remotes.role('web','db')) {<br />

// operations for web and db<br />

}<br />

session(remotes.role('all')) {<br />

// operations for all<br />

}<br />

}<br />

オペレーション 実 行<br />

ssh.runブロックでSSH 接 続 およびオペレーションの 実 行 を 定<br />

義 します。<br />

SSH 接 続 ごとに session ブロックを 定 義 し、 内 部 でオペレーショ<br />

ンを 記 述 します。<br />

task sshTask


G*Magazine vol.8<br />

def hostname = execute 'hostname -f'<br />

println hostname<br />

execute('hostname -f') { result -> println result<br />

}<br />

$ curl -L -O https://github.com/int128/groovy-<br />

ssh/releases/download/v0.1.7/groovy-ssh-0.1.7-<br />

all.jar<br />

$ java -jar groovy-ssh-0.1.7-all.jar sshTasks.<br />

groovy<br />

また、オペレーション 実 行 時 には 以 下 のパラメータを 指 定 でき<br />

ます。<br />

キー 型 説 明<br />

dryRun Boolean ドライランを 有 効<br />

にします ( デフォル<br />

ト false)<br />

pty Boolean PTY( 擬 似 端 末 ) を 有<br />

効 にします ( デフォ<br />

ルト false)<br />

logging String ログ 出 力 先 を 指 定<br />

します ( デフォルト<br />

slf4j)<br />

outputStream OutputStream コマンドの 標 準 出<br />

力 のリダイレクト<br />

先 を 指 定 します<br />

errorStream OutputStream コマンドの 標 準 エ<br />

ラー 出 力 のリダイ<br />

レクト 先 を 指 定 し<br />

ます<br />

encoding String 入 出 力 エンコー<br />

ディングを 指 定 し<br />

ます ( デフォルト<br />

UTF-8)<br />

interaction Closure 対 話 処 理 のための<br />

クロージャを 指 定<br />

します<br />

extensions List of classes ミックスインする<br />

拡 張 モジュールの<br />

クラスを 指 定 しま<br />

す<br />

Groovy SSHでSSH DSLを 実 行 する 場 合 にはコンテキストの 指<br />

定 が 必 要 です。 以 下 のように"ssh."を 記 述 するようにしてくださ<br />

い。<br />

ssh.remotes {<br />

server {<br />

host = 'x.x.x.x'<br />

user = 'someone'<br />

identity = new File('~/.ssh/id_dsa')<br />

}<br />

}<br />

ssh.settings {<br />

logging = 'stdout'<br />

}<br />

ssh.run {<br />

session(ssh.remotes.server1) {<br />

execute 'hostname -f'<br />

}<br />

}<br />

まとめ<br />

Gradle SSH Plugin/Groovy SSH ライブラリは Gradle による 作 業<br />

の 自 動 化 だけでなく、シェルスクリプトの 高 機 能 な 代 替 物 として<br />

Groovy を 利 用 可 能 にする、 可 能 性 を 秘 めたプロダクトです。<br />

ドキュメントが 英 語 のみということもあってか、なぜか 日 本 よ<br />

りも 海 外 で 人 気 があるようですが、この 機 会 にぜひ 試 してみてく<br />

ださい。<br />

対 話 処 理<br />

オペレーションの 実 行 結 果 に 対 してパターンマッチングを 行 う<br />

ことで、 対 話 的 な 処 理 を 実 現 できます。expectコマンドと 類 似<br />

の 処 理 が 可 能 です。<br />

詳 細 についてはユーザーガイドを 参 照 してください。<br />

Groovy SSH ライブラリ 利 用 時 の 注 意 事 項<br />

Groovy SSHライブラリはGradleに 依 存 しておらず、 単 体 で 利<br />

用 することができます。<br />

使 い 方 は 簡 単 で、Groovy SSHのJARファイルをダウンロード<br />

し、java -jar で 実 行 するだけです。<br />

Gradle プラグイン 探 訪 〜 第 1 回 Gradle SSH Plugin 〜<br />

13


G*Magazine vol.8<br />

Grails Plugin 探 訪<br />

第 9 回<br />

~ CodeNarc プラグイン ~<br />

URL: http://grails.org/plugin/codenarc<br />

プラグインのバージョン : 0.22<br />

対 応 する Grails のバージョン : 1.3 以 上<br />

杉 浦 孝 博<br />

最 近 は Grails を 使 用 したシステムの 保 守 をしている 自 称 プログラマ。<br />

日 本 Grails/Groovy ユーザーグループ 事 務 局 長 。<br />

共 著 『Grails 徹 底 入 門 』、 共 訳 『Groovy イン・アクション』<br />

はじめに<br />

今 回 ご 紹 介 するGrailsプラグインは、CodeNarcプラグインで<br />

す。<br />

本 記 事 は、 次 の 環 境 で 動 作 確 認 をしております。<br />

plugins {<br />

....<br />

compile ':codenarc:0.22'<br />

}<br />

• OS : Windows 7 SP1, Mac OS X 10.9.5<br />

• Java : 1.8.0_25<br />

• Grails : 2.4.4<br />

なお、コマンドの 実 行 結 果 については、 紙 面 の 都 合 上 、 出 力 結<br />

果 を 省 略 しており、 実 際 の 出 力 と 異 なる 場 合 があります。ご 了 承<br />

願 います。<br />

CodeNarc プラグインとは<br />

CodeNarcプラグインは、Groovyのソースコードに 対 して 静 的<br />

コード 分 析 を 行 うための 機 能 を 提 供 するプラグインです。<br />

既 存 のツールであるCodeNarc を 使 用 し 静 的 コード 分 析 を 行 い<br />

ます。<br />

なお、CodeNarc については、Vol.1 から Vol.3 まで 連 載 があり<br />

ますので、そちらも 参 照 してください。<br />

静 的 コード 分 析 の 実 行<br />

静 的 コード 分 析 は、 次 のコマンドを 実 行 します。<br />

$ grails codenarc<br />

デフォルトでは、 分 析 結 果 は target/CodeNarcReport.html とい<br />

うレポートファイルに 出 力 されます。<br />

サンプルコードで 静 的 コード 分 析<br />

実 際 に 試 してみましょう。<br />

サンプルプロジェクトの 作 成<br />

サンプルのプロジェクトを 作 成 します。<br />

$ grails create-app testcodenarc<br />

プラグインのインストール<br />

CodeNarcプラグインのインストールは、Grailsのバージョン<br />

が 1.x の 場 合 、 次 のコマンドを 入 力 してインストールします。<br />

$ grails install-plugin codenarc<br />

Grails のバージョンが 2.x の 場 合 、BuildConfig.groovy の plugins<br />

に「compile ':codenarc:0.22'」を 追 加 します。<br />

サンプルのドメインクラスの 作 成<br />

次 にサンプルのドメインクラスを 作 成 します。 今 回 もいつもの<br />

様 に、 本 (Book) のドメインクラスとします。<br />

$ cd testcodenarc<br />

$ grails create-domain-class Book<br />

Book ドメインクラスのコードは 次 のとおりです。<br />

14<br />

Grails Plugin 探 訪 第 9 回 ~ CodeNarc プラグイン ~


G*Magazine vol.8<br />

package testcodenarc<br />

class Book {<br />

String title<br />

int price<br />

String isbn13<br />

}<br />

static constraints = {<br />

title blank: false<br />

price min: 0<br />

isbn13 blank: true<br />

}<br />

コントローラ、ビューの 生 成<br />

ドメインクラスから、コントローラとビューを 自 動 生 成 します。<br />

$ grails generate-all testcodenarc.Book<br />

静 的 コード 分 析 の 実 行<br />

自 動 生 成 したコードも 含 め、 静 的 コード 分 析 を 実 行 します。<br />

$ grails codenarc<br />

...<br />

..Running CodeNarc (rulesets/basic.xml,rulesets/<br />

exceptions.xml,<br />

rulesets/imports.xml,rulesets/grails.<br />

xml,rulesets/unused.xml) ...<br />

.CodeNarc finished; report(s) generated: [target/<br />

CodeNarcReport.html]<br />

ご 覧 のとおり、 自 作 したドメインクラス、 自 動 生 成 されたコン<br />

トローラももちろんですが、テストコードもGroovyコードです<br />

ので、 分 析 の 対 象 となっているのがわかります。<br />

静 的 コード 分 析 結 果 の 参 照<br />

出 力 されたファイル target/CodeNarcReport.html を Web ブラ<br />

ウザで 開 きます。<br />

Grails Plugin 探 訪 第 9 回 ~ CodeNarc プラグイン ~<br />

15


G*Magazine vol.8<br />

CodeNarc プラグインの 設 定<br />

CodeNarcプラグインは、デフォルトの 設 定 でも 十 分 使 えます<br />

が、 場 合 によっては 設 定 を 変 更 したい 場 合 があると 思 います。そ<br />

のような 場 合 は、BuildConfig.groovy に「codenarc.」で 始 まるプ<br />

ロパティに 設 定 を 記 述 します。<br />

変 更 できる 内 容 は 次 のとおりです。<br />

• レポートの 形 式 やファイルパスなど<br />

• CodeNarc ルールセット<br />

• 分 析 対 象 のソースコード<br />

• CodeNarc のルールのプロパティ<br />

• ルール 違 反 数 の 上 限<br />

レポートの 設 定<br />

レポートは、デフォルトではHTML 形 式 でtarget/<br />

CodeNarcReport.html ファイルに 出 力 されます。<br />

codenarc.reports = {<br />

MyXmlReport('xml') {<br />

outputFile = 'target/CodeNarc-Report.xml'<br />

title = 'Sample Report by XML'<br />

}<br />

MyHtmlReport('html') {<br />

outputFile = 'target/CodeNarc-Report.<br />

html'<br />

title = 'Sample Report by HTML'<br />

}<br />

MyTextReport('text') {<br />

outputFile = 'target/CodeNarc-Report.<br />

text'<br />

title = 'Sample Report by Text'<br />

}<br />

}<br />

分 析 結 果 のレポートについては、 形 式 やファイルのパス、タイ<br />

トルを 変 更 することができます。<br />

レポート 形 式 については、HTML 形 式 以 外 に、XML 形 式 とテキ<br />

スト 形 式 もサポートしています。<br />

レポートは、1 つだけでなく、 複 数 指 定 することができます。<br />

設 定 の 仕 方 は、<br />

codenarc.reports = {<br />

レポート 名 ( レポート 形 式 ) {<br />

outputFile = レポートのファイルパス<br />

title = レポートのタイトル<br />

}<br />

...<br />

}<br />

と、クロージャで 設 定 します。レポート 名 は 任 意 の 名 前 、レポー<br />

ト 形 式 は 次 の 表 のとおり、ファイルパスは 相 対 パスの 場 合 、アプ<br />

リケーションのルートディレクトリからのパスとなります。<br />

HTML<br />

XML<br />

テキスト<br />

任 意 の 出 力<br />

形 式<br />

'html'<br />

'xml'<br />

'text'<br />

値<br />

CodeNarc の ReportWriter イン<br />

タフェースを 実 装 したクラス<br />

の 完 全 修 飾 クラス 名<br />

例 を 見 てみましょう。 次 のとおり 設 定 を 記 述 すれば、target ディ<br />

レクトリに3つのレポートファイルが 作 成 されることになりま<br />

す。<br />

CodeNarc ルールセットファイルの 設 定<br />

CodeNarcのルールセットファイルは、デフォルトでは 次 の<br />

ファイルが 使 用 されます。<br />

• rulesets/basic.xml<br />

• rulesets/exceptions.xml<br />

• rulesets/imports.xml<br />

• rulesets/grails.xml<br />

• rulesets/unused.xml<br />

CodeNarcのルールセットファイルの 設 定 を 変 更 したい 場 合 、<br />

BuildConfig.groovy に「codenarc.ruleSetFiles」プロパティを 記 述<br />

します。<br />

codenarc.ruleSetFiles プロパティに 指 定 するファイルは、クラ<br />

スパスから 参 照 できる 必 要 があります。ファイルシステム 上 の<br />

ファイルをし 指 定 した 場 合 、 次 のように「file:」を 先 頭 に 付 加 し<br />

ます。<br />

codenarc.ruleSetFiles="file:grails-app/conf/<br />

MyRuleSet.groovy"<br />

codenarc.ruleSetFiles プロパティに 複 数 ファイルを 指 定 したい<br />

場 合 、カンマ(,)で 区 切 って1つの 文 字 列 で 指 定 するか、リスト 形<br />

式 で 複 数 の 文 字 列 で 指 定 します。<br />

16<br />

Grails Plugin 探 訪 第 9 回 ~ CodeNarc プラグイン ~


G*Magazine vol.8<br />

codenarc.ruleSetFiles="rulesets/basic.<br />

xml,rulesets/exceptions.xml," +<br />

rulesets/imports.xml,rulesets/grails.<br />

xml,rulesets/unused.xml"<br />

codenarc.extraIncludeDirs プロパティで 任 意 のディレクトリを<br />

対 象 にした 場 合 、リスト 形 式 で 指 定 します。 例 えば、grails-app/<br />

jobs ディレクトリを 指 定 したい 場 合 、 次 のように 指 定 します。<br />

codenarc.extraIncludeDirs=['grails-app/jobs']<br />

codenarc.ruleSetFiles=[<br />

"rulesets/basic.xml",<br />

"rulesets/exceptions.xml",<br />

"rulesets/imports.xml",<br />

"rulesets/grails.xml",<br />

"rulesets/unused.xml"<br />

]<br />

CodeNarc のルールのプロパティ<br />

CodeNarcの 各 ルールはいくつかプロパティを 持 っており、<br />

BuildConfig.groovy 中 に codenarc.properties プロパティを 記 述 し<br />

て、ルールのプロパティ 値 を 変 更 することができます。<br />

形 式 は 次 のとおりです。<br />

ルール 名 . プロパティ 名 = プロパティ 値<br />

分 析 対 象 のソースコード<br />

分 析 対 象 のソースコードは、デフォルトでは、 分 析 対 象 となる<br />

Groovyコードは 次 のディレクトリ 配 下 のGroovyファイルが 対 象<br />

となります。<br />

• src/groovy<br />

• grails-app/controllers<br />

• grails-app/domain<br />

• grails-app/services<br />

• grails-app/taglib<br />

• grails-app/utils<br />

• test/unit<br />

• test/integration<br />

分 析 対 象 のソースコードを 変 更 したい 場 合 、 次 の 表 に 示 すプロ<br />

パティをBuildConfigに 記 述 します。プロパティの 値 としてtrue<br />

を 指 定 した 場 合 は 指 定 したディレクトリ 配 下 のGroovyファイル<br />

が 分 析 対 象 となり、falseを 指 定 した 場 合 は 分 析 対 象 とはなりま<br />

せん。<br />

プロパティ 名 対 象 ディレクトリ デフォルト 値<br />

codenarc.processSrcGroovy src/groovy true<br />

codenarc.processControllers<br />

codenarc.processDomain<br />

codenarc.processServices<br />

codenarc.processTaglib<br />

grails-app/<br />

controllers<br />

grails-app/<br />

domain<br />

grails-app/<br />

services<br />

grails-app/<br />

taglib<br />

true<br />

true<br />

true<br />

true<br />

codenarc.processTestUnit test/unit true<br />

codenarc.processTestIntegration test/integration true<br />

codenarc.processViews<br />

codenarc.extraIncludeDirs<br />

-<br />

grails-app/<br />

views<br />

任 意 のディレク<br />

トリ<br />

false<br />

—<br />

例 えば、ドメインクラスが equals メソッド、toString メソッ<br />

ドを 持 つことを 示 すルール、GrailsDomainHasEquals ルールと<br />

GrailsDomainHasToString ルールを 無 効 にしたい 場 合 は、 次 のよ<br />

うに 指 定 します。<br />

codenarc.properties = {<br />

GrailsDomainHasEquals.enabled = false<br />

GrailsDomainHasToString.enabled = false<br />

}<br />

また、CodeNarcのルールのプロパティを 別 ファイルですでに<br />

持 っている 場 合 、そのファイルパスを BuildConfig.groovy 中 の<br />

codenarc.propertiesFile プロパティに 記 述 することで 同 等 のこと<br />

を 実 現 できます。<br />

先 程 の 例 は、 次 と 同 等 です。<br />

// grails-app/conf/BuildConfig.groovy<br />

codenarc.propertiesFile = 'grails-app/conf/<br />

codenarc.properties'<br />

// grails-app/conf/codenarc.properties<br />

GrailsDomainHasEquals.enabled = false<br />

GrailsDomainHasToString.enabled = false<br />

ルール 違 反 数 の 上 限<br />

CodeNarcのルールにはプライオリティが 設 定 されており、プ<br />

ライオリティ 毎 に 違 反 数 の 上 限 を 設 定 することができます。デ<br />

フォルトは、Integer.MAX_VALUE です。 上 限 を 越 えた 場 合 、 次<br />

のメッセージが 標 準 出 力 に 出 力 され、 静 的 コード 分 析 が 失 敗 とな<br />

ります。ただし、 静 的 コード 分 析 は 最 後 まで 実 行 され、レポート<br />

ファイルも 出 力 されるようです。<br />

FAILED -- Exceeded maximum number of priority 2<br />

violations: (p1=0; p2=11; p3=3)<br />

違 反 数 の 上 限 を 設 定 する 場 合 、BuildConfig.groovy に 次 のよう<br />

に 設 定 します。<br />

Grails Plugin 探 訪 第 9 回 ~ CodeNarc プラグイン ~<br />

17


G*Magazine vol.8<br />

// プライオリティ1の 違 反 数 の 上 限<br />

codenarc.maxPriority1Violations=10<br />

// プライオリティ2の 違 反 数 の 上 限<br />

codenarc.maxPriority2Violations=20<br />

// プライオリティ3の 違 反 数 の 上 限<br />

codenarc.maxPriority3Violations=30<br />

ルール 違 反 数 の 上 限 超 過 時 の 動 作<br />

ルール 違 反 数 の 上 限 を 超 過 した 場 合 、デフォルトでは、 先 程 の<br />

失 敗 メッセージを 標 準 出 力 に 出 力 し、System.exit(1)を 呼 び 出 し<br />

て 終 了 します。この 動 作 を 変 更 し、 例 外 をスローして 終 了 するこ<br />

ともできます。<br />

BuildConfig.groovy で codenarc.systemExitOnBuildException プ<br />

ロパティを 指 定 することで、 動 作 を 変 更 することができます。プ<br />

ロパティ 値 としてtrueを 指 定 した 場 合 、デフォルトの 動 作 と 同<br />

様 、 失 敗 メッセージを 標 準 出 力 に 出 力 し、System.exit(1)を 呼 び<br />

出 して 終 了 します。プロパティ 値 としてfalseを 指 定 した 場 合 、<br />

例 外 をスローして 終 了 します。<br />

codenarc.systemExitOnBuildException = false<br />

おわりに<br />

今 回 は 静 的 コード 分 析 を 行 うプラグインをご 紹 介 いたしまし<br />

た。Groovyコードの 静 的 コード 分 析 ツールとして 定 評 のある<br />

CodeNarcを 使 用 していますので、 一 度 お 試 ししてはいかがで<br />

しょうか。<br />

18 Grails Plugin 探 訪 第 9 回 ~ CodeNarc プラグイン ~<br />

18


G*Magazine vol.8<br />

Grails<br />

リリース 情 報 2014.11.29<br />

Grails は、Groovy や Hibernate などをベースとしたフルスタック<br />

の Web アプリケーションフレームワークです。<br />

URL: http://grails.org/<br />

バージョン : 1.3.9, 2.1.5, 2.2.5, 2.3.11,2.4.4<br />

■ 更 新 情 報<br />

• 2.2.5 では、ユーザガイドの "withFormat" セクションに<br />

"form"mime-type についての 記 述 が 追 加 されたり、いくつか<br />

バグ 対 応 が 行 われています。<br />

• 2.2.5 リリースノート : https://grails.org/2.2.5+Release+Notes<br />

• 山 本 さんのブログ : http://d.hatena.ne.jp/<br />

mottsnite/20140304/1393946239<br />

• 2.3.11 では、いくつかバグ 対 応 が 行 われています。<br />

• 2.3.11 リリースノート : https://grails.<br />

org/2.3.11+Release+Notes<br />

• 山 本 さんのブログ : http://d.hatena.ne.jp/<br />

mottsnite/20140626/1403777424<br />

• 2.4.4 では、@DirtiesRuntime アノテーションが 追 加 されたり、<br />

ユニットテストでの forwardedUrl の 値 が 変 更 になったり、<br />

いくつかバグ 対 応 が 行 われています。<br />

• 2.4.4 リリースノート : https://grails.org/2.4.4+Release+Notes<br />

• 山 本 さんのブログ : http://d.hatena.ne.jp/<br />

mottsnite/20141028/1414514707<br />

Groovy<br />

Groovy は、JavaVM 上 で 動 作 する 動 的 言 語 です。<br />

URL: http://groovy.codehaus.org/<br />

バージョン : 1.8.9, 2.0.8, 2.1.9, 2.2.2, 2.3.8, 2.4.0-beta-4<br />

■ 更 新 情 報<br />

• 2.2.2 では、@Delegate を 使 用 した 際 スタックトレースに 行<br />

番 号 が 出 力 されるようになったり、いくつかバグ 対 応 が 行 わ<br />

れています。<br />

• 2.2.2 リリースノート :https://jira.codehaus.org/secure/<br />

ReleaseNote.jspaprojectId=10242&version=19832<br />

• 2.3.8 では、BigInteger.power(Biginteger) メソッドが 追 加 さ<br />

れたり、いくつかバグ 対 応 が 行 われています。<br />

• 2.3.8 リリースノート : http://jira.codehaus.org/secure/<br />

ReleaseNote.jspaprojectId=10242&version=20648<br />

• 2.4.0-beta-4 では、JSON ビルダーの 実 装 が 書 きなおされたり、<br />

trait 用 に @SelfType アノテーションが 追 加 されたり、いくつ<br />

かバグ 対 応 が 行 われています。<br />

• 2.4.0-beta-4リリースノート : http://jira.codehaus.org/secure/<br />

ReleaseNote.jspaprojectId=10242&version=20612<br />

Griffon<br />

Griffonは、デスクトップアプリケーションを 開 発 するためのア<br />

プリケーションフレームワークです。<br />

URL: 1.x http://griffon.codehaus.org/], 2.x [http://new.griffonframework.org/index.html<br />

バージョン : 1.5.0, 2.0.0<br />

■ 更 新 情 報<br />

• 1.5.0 では、Groovy のバージョンが 2.2.1 に、Spring のライブ<br />

ラリのバージョンが 3.2.7 にそれぞれ 変 更 されています。<br />

• 1.5.0 リリースノート : http://docs.codehaus.org/display/<br />

GRIFFON/Griffon+1.5.0<br />

• 2.0.0 では、 依 存 するプラグインが 最 新 のバージョンにアッ<br />

プグレードされています。<br />

• 2.0.0 リリースノート : http://new.griffon-framework.org/<br />

news/griffon_2.0.0.html<br />

Gant<br />

Gant は、XML の 代 わりに Groovy で Ant タスクを 記 述 し 実 行 する<br />

ビルド 管 理 ツールです。<br />

URL: http://gant.codehaus.org/<br />

バージョン : 1.9.11<br />

■ 更 新 情 報<br />

• 1.9.11 での 更 新 内 容 は 不 明 です。<br />

GMaven<br />

GMaven は、Maven 用 の Groovy プラグインです。<br />

URL: 1.x http://gmaven.codehaus.org/], 2.x [http://groovy.github.<br />

io/gmaven/<br />

バージョン : 1.4, 2.0<br />

Gradle<br />

Gradleは、Groovyでビルドスクリプトを 記 述 し 実 行 するビルド<br />

管 理 ツールです。<br />

URL: http://www.gradle.org/<br />

バージョン : 2.2.1<br />

■ 更 新 情 報<br />

• 2.2.1 では、OS X と Java 7 の 組 み 合 わせでオフライン 時 に<br />

Gradle デーモンが 起 動 しない 問 題 に 対 応 しました。<br />

• 2.2.1 リリースノート : http://www.gradle.org/docs/2.2.1/<br />

release-notes<br />

Gaelyk<br />

Gaelyk は、Groovy で 記 述 する Google App Engine for Java 用 のラ<br />

イトウェイトなフレームワークです。<br />

URL: http://gaelyk.appspot.com/<br />

バージョン : 2.1.2<br />

■ 更 新 情 報<br />

• 2.1.2 では、Groovy 2.3 に 対 応 し、いくつかバグ 対 応 が 行 われ<br />

ています。<br />

• 2.1.2 リリースノート : http://gaelyk.appspot.com/download<br />

Google App Engine SDK for Java<br />

Google App Engine SDK for Java は、Java で Google App Engine<br />

用 の Web アプリケーションを 開 発 するための SDK です。<br />

URL: https://cloud.google.com/appengine/<br />

バージョン : 1.9.15<br />

■ 更 新 情 報<br />

• 1.9.15 では、Datastore の 統 計 情 報 にエンティティのカウン<br />

トが 表 示 されないバグ 対 応 が 行 われています。<br />

• 1.9.15 リリースノート : https://code.google.com/p/<br />

googleappengine/wiki/SdkForJavaReleaseNotes<br />

GPars<br />

GPars は、Groovy に 直 感 的 で 安 全 な 並 行 処 理 を 提 供 するシステム<br />

です。<br />

URL: http://gpars.codehaus.org/<br />

バージョン : 1.2.1GA<br />

■ 更 新 情 報<br />

• 1.2.1GA での 更 新 内 容 は 不 明 です。<br />

Groovy++<br />

Groovy++ は、Groovy 言 語 に 対 して 静 的 な 機 能 を 拡 張 します。<br />

URL: http://code.google.com/p/groovypptest/<br />

バージョン : 0.9.0<br />

リリース 情 報<br />

19


G*Magazine vol.8<br />

Spock<br />

Spock は、Java や Groovy 用 のテストと 仕 様 のためのフレームワー<br />

クです。<br />

URL: http://code.google.com/p/spock/<br />

バージョン : 0.7<br />

GroovyServ<br />

GroovyServは、Groovy 処 理 系 をサーバとして 動 作 させることで<br />

groovy コマンドの 起 動 を 見 た 目 上 高 速 化 するものです。<br />

URL: http://kobo.github.com/groovyserv/<br />

バージョン : 1.0.0<br />

■ 更 新 情 報<br />

• 1.0.0 では、ログファイルや authtoken ファイルのパスを<br />

GROOVYSERV_WORK_DIR や GROOVYSERV_LOG_DIR 環 境 変<br />

数 で 明 示 することができたり、パッケージ 名 が 変 更 になった<br />

り、バグ 対 応 が 行 われています。<br />

• 1.0.0 チェンジログ : http://kobo.github.io/groovyserv/<br />

changelog.html<br />

Geb<br />

Gebは、Groovyを 使 用 したWebブラウザを 自 動 化 する 仕 組 みで<br />

す。<br />

URL: http://www.gebish.org/<br />

バージョン : 0.10.0<br />

■ 更 新 情 報<br />

• 0.10.0 では、 要 素 の CSS プロパティにアクセスするために<br />

Navigator に css() が 追 加 されたり、いくつかバグ 対 応 が 行 わ<br />

れています。<br />

• 0.10.0 リリースノート : http://www.gebish.org/manual/<br />

current/project.html#0100<br />

Easyb<br />

Easyb は、 ビ ヘ イ ビ ア 駆 動 開 発 (Behavior Driven<br />

Development:BDD) 用 のフレームワークです。<br />

URL: http://www.easyb.org/<br />

バージョン : 1.5<br />

Gmock<br />

Gmock は、Groovy 用 のモック・フレームワークです。<br />

URL: http://code.google.com/p/gmock/<br />

バージョン : 0.8.3<br />

HTTPBuilder<br />

HTTPBuilder は、HTTP ベースのリソースに 簡 単 にアクセスするた<br />

めの 方 法 です。<br />

URL: http://groovy.codehaus.org/modules/http-builder/<br />

バージョン : 0.7.2<br />

■ 更 新 情 報<br />

• 0.7.2 での 更 新 内 容 は 不 明 です。<br />

CodeNarc<br />

CodeNarc は、Groovy 向 けの 静 的 コード 解 析 ツールです。<br />

URL: http://codenarc.sourceforge.net/<br />

バージョン : 0.22<br />

■ 更 新 情 報<br />

• 0.22 では、 新 しく 4 つのルールや IDE のテキストレポートタ<br />

イプが 追 加 され、いくつかバグ 対 応 が 行 われています。<br />

• 0.22 リリースアナウンス : http://groovy.329449.n5.nabble.<br />

com/ANN-Announcing-CodeNarc-0-22-td5721472.html<br />

GMetrics<br />

GMetricsは、Groovyソースコードのサイズや 複 雑 さを 計 算 した<br />

り 報 告 するためのツールです。<br />

URL: http://gmetrics.sourceforge.net/<br />

バージョン : 0.6<br />

GContracts<br />

GContracts は、Groovy で 契 約 プログラミングを 行 うためのフレー<br />

ムワークです。<br />

URL: http://gcontracts.org/<br />

バージョン : 1.2.12<br />

GroovyFX<br />

GroovyFX は、JavaFX を Groovy で 書 きやすくするためのフレー<br />

ムワークです。<br />

URL: http://groovyfx.org/<br />

バージョン : 0.4.0<br />

■ 更 新 情 報<br />

• 0.4.0 では、ビルダーに catch-all ビーン・ノードが 追 加 され<br />

たり、TableView や ComboBox のバグ 対 応 が 行 われています。<br />

• 0.4.0 リリースノート : http://jira.codehaus.org/browse/GFX/<br />

fixforversion/19127<br />

GBench<br />

GBench は、Groovy のためのベンチマーク・フレームワークです。<br />

URL: http://code.google.com/p/gbench/<br />

バージョン : 0.4.2<br />

■ 更 新 情 報<br />

• 0.4.2 では、 新 しいシステムプロパティをサポートしたり、<br />

いくつかバグ 対 応 が 行 われています。<br />

• 0.4.2 リリースノート : https://code.google.com/p/gbench/<br />

wiki/ReleaseNotes042<br />

Betamax<br />

Betamaxは、HTTP 通 信 の 内 容 を 保 存 し 再 生 するテストツールで<br />

す。<br />

URL: http://freeside.co/betamax/<br />

バージョン : 1.1.2<br />

Caelyf<br />

Caelyf は、Groovy で 記 述 する Cloud Foundry 用 のライトウェイト<br />

なツールキットです。<br />

URL: http://caelyf.net/<br />

バージョン : 1.3.1<br />

■ 更 新 情 報<br />

• 1.3.1 では、Groovy 2.3.7、Gradle 2.1 に 対 応 し、GPars 1.2.1<br />

を 同 梱 しました。<br />

• 1.3.1 リリースメッセージ : https://groups.google.com/<br />

forum/#!msg/caelyf/UW3XNI-jdjo/OwNxJCU9-sEJ<br />

Vert.x<br />

Vert.xは、 非 同 期 アプリケーション 開 発 のためのフレームワーク<br />

20<br />

リリース 情 報


G*Magazine vol.8<br />

です。<br />

URL: http://vertx.io/<br />

バージョン : 2.1.5<br />

■ 更 新 情 報<br />

• 2.1.5 では、Groovy 言 語 モジュールが 2.1.1 にアップグレー<br />

ドされたり、SSLv2Hello プロトコルがサポートされたり、<br />

いくつかバグ 対 応 が 行 われています。<br />

• 2.1.5 リリースメッセージ : https://groups.google.com/<br />

forum/#!topic/vertx/x7Dlhkc8tuA<br />

GVM (Groovy enVironment Manager)<br />

GVMは、 様 々なGroovy 関 連 のツールをインストールし、 複 数<br />

のバージョンを 切 り 替 えて 使 用 するためのツールです。<br />

URL: http://gvmtool.net/<br />

バージョン : -<br />

Gaiden<br />

Gaidenは、Markdownでドキュメントを 作 成 するするための<br />

ツールです。<br />

URL: https://github.com/kobo/gaiden/<br />

バージョン : 1.0<br />

▼ぐるーびーたん 第 6 話 までのあらすじ<br />

プログラマを 目 指 して 熊 本 から 上 京 したぐるーびー<br />

たん。その 若 さ 故 、 色 々 飛 びつくのは 良 いこと !<br />

※この 作 品 は、たいがいフィクションです。 実 在 の<br />

人 物 、 団 体 とは 関 係 ありません。<br />

21


■ 企 業 スポンサー<br />

個 人 サポータ 制 度 のお 知 らせ<br />

JGGUG では , 昨 年 に 引 き 続 き 2015 年 度 も 個 人 サポータを 募 集 いたします。.<br />

個 人 サポータとなっていただいた 方 には、 一 年 間 にわたってJGGUGが 発 行 する G* Magazine( 年 数 回 刊 。 基 本 的 に 電 子<br />

版 として 配 布 予 定 )に 個 人 サポータとしてお 名 前 を 掲 載 します( 掲 載 を 希 望 しない 旨 お 申 し 出 いただけば 掲 載 しません)。<br />

個 人 サポータとなるには、まず supporters@jggug.org にメイルで<br />

• お 名 前<br />

• 予 定 金 額<br />

G* Magazine へのご 芳 名 掲 載 の 可 否<br />

をお 知 らせください。 追 って、 運 営 委 員 より 振 込 先 の 情 報 などを 返 信 します。<br />

皆 様 のサポートをお 待 ちしております。<br />

日 本 Grails/Groovy ユーザーグループ<br />

代 表 山 田 正 樹<br />

G* Magazine vol.8 2015.2<br />

http://www.jggug.org<br />

発 行 人 : 日 本 Grails/Groovy ユーザーグループ<br />

編 集 長 : 川 原 正 隆<br />

編 集 :G* Magazine 編 集 委 員 ( 杉 浦 孝 博 、 奥 清 隆 )<br />

デザイン:㈱ニューキャスト<br />

表 紙 : 川 原 正 隆<br />

編 集 協 力 :JGGUG 運 営 委 員 会<br />

Mail:info@jggug.org<br />

© 2015 JGGUG 掲 載 記 事 の 再 利 用 については<br />

Creative Commons ライセンスによります。<br />

Publisher:Japan Grails/Groovy User Group<br />

Editor in Chief:Masataka Kawahara<br />

Editors:G* Magazine Editors Team<br />

(Takahiro Sugiura, Kiyotaka Oku)<br />

Design:NEWCAST inc.<br />

CoverDesign:Masataka Kawahara<br />

Cooperation:JGGUG Steering Committee<br />

Mail:info@jggug.org

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!