build.gradleでEclipseWTPプロジェクトを作る

## 目的
gradle でライブラリ管理、ユニットテスト、カバレッジ(とレポート)をしたいけど、メインの開発はeclipseでやりたい。
動的Webプロジェクト + Spring + Gradle のプロジェクトを gradle で作る。
Eclipseの動的webプロジェクトと `gradle eclipse` で作成されるプロジェクトを比較しながら作成した。

(ひとまず完成版でいいかな？改善点あれば随時更新する)

## 事前準備
gradle のデフォルト構成のフォルダを作成しておく。
以下の様な構成。

```フォルダ構成
プロジェクトフォルダ
├─build.gradle
└─src
  ├─main
  │  ├─java
  │  ├─resources
  │  └─webapp
  │    └─WEB-INF
  └─test
     ├─java
     └─resources
```

## build.gradle の内容

下記の内容の build.gradle を作成して、`gradle eclipse` すると、動的Webプロジェクト + Spring + Gradle のプロジェクトが作成される。
コメント中の Eclipse の操作は Pleiades で日本語化されたもの。
Java8, Tomcat8 を使う前提の設定。

`gradle cleanEclipse` するとEclipseで設定した項目が消えるので、なんとかしたい。
-> cleanEclipse* を行わず、eclipse* だけ実行すれば、Eclipseで設定変更した項目は残る。
-> cleanEclipse*を実行すると、結局Eclipseで設定した項目は消えるので、全部build.gradleに記述するべし。

```build.gradle
apply plugin: 'war'
apply plugin: 'eclipse-wtp'
apply plugin: 'jacoco'

// エンコーディング
def defaultEncoding = 'UTF-8'
[compileJava, compileTestJava]*.options*.encoding = defaultEncoding

// ソースと実行ファイルのJava バージョン
def jdkVersion = 1.8
sourceCompatibility = jdkVersion
targetCompatibility = jdkVersion

// 依存関係の解決
repositories {
    mavenCentral()
}

// 依存ライブラリの設定
dependencies {
    // ここはお好みで
}

//// eclipseの設定を毎回リセットする場合は下記の設定を有効にするか
//// gradle cleanEclipse eclipse を実行する
// tasks.eclipse.dependsOn(cleanEclipse)

// eclipse プロジェクトの設定
import org.gradle.plugins.ide.eclipse.model.SourceFolder
eclipse {
    // .project の設定
    project {
        // nature の追加
        // eclipse-wtp にデフォルトで含まれている nature
        natures 'org.eclipse.wst.jsdt.core.jsNature'

        // spring project nature を追加
        natures 'org.springframework.ide.eclipse.core.springnature'

        // MyBatis nature を追加
        //natures 'net.harawata.mybatipse.MyBatisNature'

        // Gradle nature を追加
        natures 'org.springsource.ide.eclipse.gradle.core.nature'

        // buildCommand の追加
        // eclipse-wtp にデフォルトで含まれている buildCommand
        buildCommand 'org.eclipse.wst.jsdt.core.javascriptValidator'
        // spring のbuildCommand を追加
        buildCommand 'org.springframework.ide.eclipse.core.springbuilder'
    }

    // gradleで取得したjarのパスを絶対パスにしない
    // 事前に GRADLE_USER_HOME を設定しておく必要がある
    // Windows: [ウィンドウ]->[設定] を開く
    // Mac    : [Eclipse]->[環境設定]を開く
    // 設定ウィンドウが開いたら [Java]->[ビルド・パス]->[クラスパス変数] を選択する
    // [新規]ボタンを押下して [名前]:GRADLE_USER_HOME, [パス]:gradleを配置したパス を設定する
    pathVariables 'GRADLE_USER_HOME': gradle.gradleUserHomeDir

    // .classpath の設定
    classpath {
        // 依存している jar の source と javadoc をダウンロードする
        downloadSources = true    // デフォルトは false
        downloadJavadoc = true    // javadoc のパスは絶対パスになる

        // Java のビルドパスにEARライブラリーを追加
        // 動的Webプロジェクトには含まれているので、必要ならば追加
        // containers 'org.eclipse.jst.j2ee.internal.module.container'

        // Java のビルドパスにサーバー・ランタイムを追加
        containers 'org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v8.0'

        file {
            // ソースパスの設定を削除
            beforeMerged { classpath ->
                // classpath.entries.clear()
                classpath.entries.removeAll { it.kind == "src" }
            }

            // 出力パスを gradle のデフォルトに合わせる
            whenMerged { classpath ->
                classpath.entries.findAll { it instanceof SourceFolder && it.path.startsWith("src/main/java")      }*.output = "build/classes/main"
                classpath.entries.findAll { it instanceof SourceFolder && it.path.startsWith("src/main/resources") }*.output = "build/resources/main"
                classpath.entries.findAll { it instanceof SourceFolder && it.path.startsWith("src/test/java")      }*.output = "build/classes/test"
                classpath.entries.findAll { it instanceof SourceFolder && it.path.startsWith("src/test/resources") }*.output = "build/resources/test"
                classpath.entries.removeAll { it.kind == "output" }
            }

            // Web App ライブラリー のJARにソースがアタッチされない問題の対応(classpathの一番最後に追加する)
            withXml { xml ->
                def node = xml.asNode()
                node.remove( node.find { it.@path == 'org.eclipse.jst.j2ee.internal.web.container' } )
                node.appendNode( 'classpathentry', [ kind: 'con', path: 'org.eclipse.jst.j2ee.internal.web.container', exported: 'true'])
            }
        }
    }

    // .settings/org.eclipse.jdt.core.prefs の設定
    // eclipse側で設定を変更したあと cleanEclipse* タスクを実行すると、その変更は失われる
    // eclipseJdt だけを実行すれば、eclipse側で変更した設定はマージされる
    jdt {
        // 毎回固定の設定を行う場合は下記のようにする(テンプレは自前で用意しておく)
        /*
        file {
            def props = new Properties()
            props.load(new FileInputStream("${projectDir}/template/org.eclipse.jdt.core.prefs"))
            withProperties { properties -> properties.putAll(props) }
        }
        */
    }

    wtp {
        // .settings/org.eclipse.wst.common.component の設定
        // [プロジェクト]→[プロパティ]->[デプロイメント・アセンブリー]の設定
        /*
        componet {
            // いまのところ明示的に設定する項目はなし
        }
        */

        // プロジェクトファセットの設定
        // プロジェクトのプロパティ->[プロジェクト・ファセット]を設定する
        // .settings/org.eclipse.wst.common.component の設定
        facet {
            // fixed facet jsdt
            facet type: org.gradle.plugins.ide.eclipse.model.Facet.FacetType.fixed, name: 'wst.jsdt.web'
            // Java
            facet name: 'jst.java', version: jdkVersion
            // 動的 web モジュール
            facet name: 'jst.web', version: '3.1'
            // JavaScript
            facet name: 'wst.jsdt.web', version: '1.0'

            // ランタイムの設定
            // 設定の[サーバー]->[ランタイム環境]で設定したサーバを指定する
            file {
                withXml { provider ->
                    if (!provider.asNode().runtime) {
                        NodeBuilder builder = new NodeBuilder()
                        provider.asNode().children().add(0, builder.runtime(name: "Apache Tomcat v8.0"))
                    }
                }
            }
        }
    }
}
```

## classpath について

- Eclipse側でビルドパスを変更した場合、`eclipseClasspath` タスクを実行した時に設定を上書きする。Eclipse側ではビルドパスを変更せず、dependencies に記述することで対応。

## 参照した URL
- https://docs.gradle.org/current/dsl/org.gradle.plugins.ide.eclipse.model.EclipseModel.html
- http://irtakt.hatenablog.com/entry/2014/05/04/233312
- http://stackoverflow.com/questions/12836089/why-is-eclipse-not-attaching-3rd-party-libs-source-files-to-a-wtp-faceted-gradle
- http://wadahiro.hatenablog.com/entry/20120321/1332287707