Mavenプラグインでライセンスヘッダを付与・更新する

今回は、[License Maven Plugin](http://code.mycila.com/license-maven-plugin/)(Mavenプラグイン)を使ってソースコードのヘッダ部分にライセンスヘッダを付与＋更新する方法を紹介したいと思います。

> **Note:**
>
> **2017/4/4 :追記**
> License Maven Plugin 2.11ベースから3.0ベースに変更しました。（基本的な使い方は同じです）

# プロジェクトの用意

今回は、Spring Bootアプリケーションに対してライセンスヘッダを付与してみます。Spring Bootアプリケーションは、[SPRING INITIALIZR](https://start.spring.io/)から作れます。プロジェクトの作成方法は、[こちら](http://qiita.com/kazuki43zoo/items/ea79e206d7c2e990e478#%E9%96%8B%E7%99%BA%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)を参考にしてください。（バージョンがちょっと古いですが・・・）

なお、本投稿で作成したプロジェクト＋α（Thymeleaf)は、GitHubで公開してます。

* https://github.com/kazuki43zoo/qiita-materials/tree/master/others/demo-license


# License Maven Pluginの適用

MavenのPOMファイルに、License Maven Pluginの定義を追加しましょう。

```xml:pom.xml

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
		<!-- ↓ ここから追加 -->
		<plugin>
			<groupId>com.mycila</groupId>
			<artifactId>license-maven-plugin</artifactId>
			<version>3.0</version>
			<configuration>
				<header>${project.basedir}/license.txt</header> <!-- (1) -->
				<excludes> <!-- (2) -->
					<exclude>.mvn/**</exclude>
					<exclude>mvnw*</exclude>
				</excludes>
			</configuration>
		</plugin>
		<!-- ↑ ここまで追加 -->
	</plugins>
</build>
```

| No | 説明 |
| --- | --- |
| (1) | ライセンスヘッダのテンプレートファイルを指定します。ファイルは後で追加します。 |
| (2) | ライセンスヘッダの付与対象から除外したいるファイルを指定します。ここでは、デフォルトで除外対象になっていないファイルを指定します。 |

> **Note: Built-inのテンプレートファイル**
>
> メジャーなライセンスのテンプレートファイルは、プラグインの中に内包されています。内包されているライセンスについては、[公式サイト] (http://code.mycila.com/license-maven-plugin/#license-templates)をご覧ください。例えば、Apache 2用のテンプレートファイルを使用する場合は、`<header>com/mycila/maven/plugin/license/templates/APACHE-2.txt</header>`といった感じで指定すればOKです。


# テンプレートファイルの用意

License Maven Pluginのコンフィギュレーションで指定したファイルを作成します。

```text:license.txt
   Copyright 2017 the original author or authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
```

ここでは、固定値ばかりですが、プレースホルダーを使用してプロパティ値（環境変数値、Mavenのプロパティ、Javaのシステムプロパティ値など）を埋め込むこともできます。（詳しくは、[公式サイト](http://code.mycila.com/license-maven-plugin/#properties-and-placeholders)をご覧ください）

> **Note:ファイル名の埋め込み**
>
> ファイルヘッダにファイル名を付与するケースを見たことがありますが、このプラグインでもファイル名を埋め込むことができます。ファイル名を埋め込みたい場合は、埋め込みたい場所に`${file.name}`を指定するだけです :blush: 

# ライセンスヘッダを付与してみる

準備は完了したので、プラグインを実行してライセンスヘッダを付与してみましょう。

```bash
$ ./mvnw license:format
```

プラグイン実行後に各ファイルを開くと、以下のようにファイルヘッダが付与されました :laughing: 

Javaファイルは・・・

```java
/**
 *    Copyright 2017 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoLicenseApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoLicenseApplication.class, args);
	}

}
```

プロパティファイルは・・・・

```properties
#
#    Copyright 2017 the original author or authors.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#

# ...
```

XMLファイルは・・・

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!--

       Copyright 2017 the original author or authors.

       Licensed under the Apache License, Version 2.0 (the "License");
       you may not use this file except in compliance with the License.
       You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing, software
       distributed under the License is distributed on an "AS IS" BASIS,
       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       See the License for the specific language governing permissions and
       limitations under the License.

-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- ... -->
</project>
```

もちろん、ここで紹介した以外の拡張子にも対応しています :wink: 
サポートしている拡張子やスタイルについては、[公式サイト](http://code.mycila.com/license-maven-plugin/#supported-comment-types)をご覧ください。

# アーティファクトのビルドとの連携

ヘッダの付与（更新）は、デフォルトだと明示的にプラグインを実行する必要がありますが、アーティファクトのビルド(`./mvnw package`など)の際に実行したい場合があります。そういった場合は、以下のような定義を追加することで実現することができます。

```xml:pom.xml
<plugin>
	<groupId>com.mycila</groupId>
	<artifactId>license-maven-plugin</artifactId>
	<version>3.0</version>
	<configuration>
		<header>${project.basedir}/license.txt</header>
		<excludes>
			<exclude>.mvn/**</exclude>
			<exclude>mvnw*</exclude>
		</excludes>
	</configuration>
	<!-- ↓ ここから追加 -->
	<executions>
		<execution>
			<phase>initialize</phase>
			<goals>
				<goal>format</goal>
			</goals>
		</execution>
	</executions>
	<!-- ↑ ここまで追加 -->
</plugin>
```

こうすることで、ソースコードをコンパイルする前にライセンスヘッダを付与することができます。

> **Note: 実行phaseについて**
> 
>  本投稿では`<phase>`要素に`initialize`を指定しましたが、ライセンスヘッダを付与したいタイミングにあわせて指定値は変更してください。


# Copyright YearをGitの履歴と連動させる

ここまでの例ではCopyright Yearは固定値(2017)を指定していましたが、Gitの履歴から取得した値に置き換えることができます。Gitの履歴と連動させたい場合は、[license-maven-plugin-git](https://github.com/mycila/license-maven-plugin/tree/master/license-maven-plugin-git)を利用します。

> Note:SVNユーザーは？
>
> 本投稿では扱いませんが、[SVNと連動するプラグイン](https://github.com/mycila/license-maven-plugin/tree/master/license-maven-plugin-svn)も提供されています。

```xml
<inceptionYear>2017</inceptionYear> <!-- ← これ追加 (プロジェクト開始年を指定) -->
<!-- ... -->
<build>
	<plugins>
		<!-- ... -->
		<plugin>
			<groupId>com.mycila</groupId>
			<artifactId>license-maven-plugin</artifactId>
			<version>3.0</version>
			<configuration>
				<header>${project.basedir}/license.txt</header>
				<excludes>
					<exclude>.mvn/**</exclude>
					<exclude>mvnw*</exclude>
				</excludes>
			</configuration>
			<!-- ... -->
			<!-- ↓ ここから追加 -->
			<dependencies>
				<dependency>
					<groupId>com.mycila</groupId>
					<artifactId>license-maven-plugin-git</artifactId>
					<version>3.0</version>
				</dependency>
			</dependencies>
			<!-- ↑ ここまで追加 -->
		</plugin>
	</plugins>
</build>
```

ライセンスヘッダのテンプレートファイルをGit連携に対応させましょう。

## `license.git.copyrightLastYear`の利用

Copyright Yearをファイルの最終更新年にしたい場合は、`license.git.copyrightLastYear`プロパティが利用します。

```text:license.txt
   Copyright ${license.git.copyrightLastYear} the original author or authors.
   ...
```

```text:出力例
   Copyright 2017 the original author or authors.
   ...
```

## `license.git.copyrightYears`の利用

Copyright Yearを`2017-2018`のように、プロジェクト開始年(`project.inceptionYear`)-ファイル最終更新年(`license.git.copyrightLastYear`)にしたい場合は、`license.git.copyrightYears`プロパティが利用できます。

```text:license.txt
   Copyright ${license.git.copyrightYears} the original author or authors.
   ...
```

以下の２パターンで出力されます。

```text:出力例(プロジェクト開始年==ファイル最終更新年の場合)
   Copyright 2017 the original author or authors.
   ...
```

or

```text:出力例(プロジェクト開始年!=ファイル最終更新年の場合)
   Copyright 2017-2018 the original author or authors.
   ...
```

# コメント形式のカスタマイズ

Javaファイルのデフォルトのコメント形式は、JavaDoc(`/** */`)形式なのですが、私の経験では `/* */`形式の方が多いイメージなので、Javaファイルのコメント形式を`/* */`に変更する簡易的な方法を紹介しておきます。
Javaファイルの形式コメントを`/* */`にしたい場合は、`<mapping>`要素の中に拡張子(`java`)と適用するコメントスタイル(`SLASHSTAR_STYLE`)を紐付けるだけです。

```xml
<plugin>
	<groupId>com.mycila</groupId>
	<artifactId>license-maven-plugin</artifactId>
	<version>3.0</version>
	<configuration>
		<header>${project.basedir}/license.txt</header>
		<excludes>
			<exclude>.mvn/**</exclude>
			<exclude>mvnw*</exclude>
		</excludes>
		<!-- ↓ ここから追加 -->
		<mapping>
			<java>SLASHSTAR_STYLE</java>
		</mapping>
		<!-- ↑ ここまで追加 -->
	</configuration>
	<!-- ... -->
</plugin>
```

この状態でpluginを実行すると・・・

```java
/*
 *    Copyright 2017 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoLicenseApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoLicenseApplication.class, args);
	}

}
```

といった感じで、`/* */`形式のコメントに変更できます。
さらに・・・あらかじめ用意されているスタイルの定義自体をカスタマイズすることもできます。本エントリーではスタイル定義のカスタマイズの説明は割愛しますが、カスタマイズが必要な場合は[公式マニュアル](http://code.mycila.com/license-maven-plugin/#changing-header-style-definitions)をご覧ください。


# まとめ

みなさんライセンスヘッダはどうやって付与・更新してますか？ 手動？ オレオレsedスクリプト？
さすがに手動で付与しているケースは少ないと思いますが、Mavneプラグインを使うと簡単に付与＋更新できます。この機会に是非使ってみてください :wink: 

# 参考サイト

* http://code.mycila.com/license-maven-plugin/
* https://github.com/mycila/license-maven-plugin/tree/master/license-maven-plugin-git