$ javadoc -doclet MyDoclet -docletpath . MyClass.javaで、start() が呼ばれる
package com.mycompany.docletexam;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.DocErrorReporter;
import com.sun.javadoc.Doclet;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.Parameter;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.SourcePosition;
import com.sun.javadoc.Type;
/**
* メソッド列挙 Doclet. 使い方 javadoc -encoding UTF-8 -sourcepath src/main/java -public
* -doclet com.mycompany.docletexam.MethodListGenerator -docletpath
* lib/MyDoclet.jar -d .\doc\summary.csv -ignore-get-set -ignore-gui
*
* -encodieng : ソースのエンコーディング (javadoc共通) -sourcepath : ソースの格納場所 (javadoc共通)
* -public pkg1 pkg2 ... / -private pkg1 pkg2 ... : 対象パッケージ (javadoc共通) -doclet
* : (必須) カスタム Docklet クラス -docletpath : (必須) カスタム Docklet が動作するために必要な Classpath
* -d : (必須) 出力先 -ignore-get-set : (任意) getXXX と setXXX の組がある場合には、メソッド一覧には出力しません
* -ignore-gui : (任意) java.awt.* の子孫クラスと、それらを引数・返値とするメソッドをメソッド一覧には出力しません
*
* ant や maven からも使えます。(サンプルは本クラスの pom.xml, build.xml)
*/
public class MethodListGenerator extends Doclet {
/**
* 処理開始
* @param rootDoc RootDoc
* @return true 出力成功<br/>false 失敗
*/
public static boolean start(final RootDoc rootDoc) {
try {
MethodListGenerator test = new MethodListGenerator();
test.printOption(rootDoc);
test.printDoclet(rootDoc);
System.out.println("...done");
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* オプションの個数を返す. -d が 2 を返すほかは、com.sun.javadoc.Doclet と同じです
*
* @param option
* @return オプションの個数
*/
public static int optionLength(final String option) {
if (option.matches("-d")) {
return 2;
} else if (option.matches("-ignore-get-set")) {
return 1;
} else if (option.matches("-ignore-gui")) {
return 1;
}
return Doclet.optionLength(option);
}
/**
* オプションの検証.
*
* @param options コマンドオプション
* @param reporter エラー
* @return true : 合格<br/>false : 不合格
*/
public static boolean validOptions(final String[][] options,
DocErrorReporter reporter) {
// -d があったら、com.sun.javadoc.Doclet#validOptionsを呼び出す
for (String[] option : options) {
if ("-d".equals(option[0])) {
return Doclet.validOptions(options, reporter);
}
}
reporter.printError("-d オプションで、出力先 cvs ファイル名を指定してください");
return false;
}
/**
* 起動オプションの表示
*/
private void printOption(final RootDoc rootDoc) {
System.out.println("Options:");
for (String[] param : rootDoc.options()) {
System.out.format("\t%s\r\n", Arrays.toString(param));
}
}
/**
* Docletの表示
*/
private void printDoclet(final RootDoc rootDoc) throws IOException {
File report = new File(findOptionValue(rootDoc, "-d"));
boolean ignoreGetSet = findOptionFlag(rootDoc, "-ignore-get-set");
boolean ignoreGui = findOptionFlag(rootDoc, "-ignore-gui");
// ディレクトリを作成する
File dir = report.getParentFile();
if (dir != null && !dir.exists()) {
dir.mkdirs();
}
// MS-Excel で開けるように MS932 で出力
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(report), "MS932"));
int no = 1;
for (ClassDoc classDoc : rootDoc.classes()) {
bw.write(String.format("#,\"%s\",\"\",\"%s\"\r\n",
classDoc.qualifiedName(), getFirstLine(classDoc.commentText())));
if (ignoreGui && isGuiComponet(classDoc)) {
continue;
}
for (MethodDoc methodDoc : classDoc.methods()) {
//メソッド名
String methodName = methodDoc.name();
if (ignoreGetSet) {
if (methodName.startsWith("get") && findSetter(classDoc, methodDoc)) {
// 対抗する setter がある getter は無視する
continue;
}
if (methodName.startsWith("set") && findGetter(classDoc, methodDoc)) {
// 対抗する getter がある setter は無視する
continue;
}
}
//ソース位置
SourcePosition mtdPosition = methodDoc.position();
int mtdLine = mtdPosition.line();
//修飾子
String modifiersName = methodDoc.modifiers();
//戻り値
Type returnType = methodDoc.returnType();
if (ignoreGui && isGuiComponet(returnType.asClassDoc())) {
continue;
}
String returnName = returnType.typeName();
if (returnType.dimension() != null) {
returnName += returnType.dimension();
}
//パラメータ
String paramName = "";
for (Parameter parameter : methodDoc.parameters()) {
if (ignoreGui && isGuiComponet(parameter.type().asClassDoc())) {
continue;
}
paramName += "".equals(paramName) ? parameter.toString() : ", " + parameter.toString();
}
bw.write(
String.format("%d,\"\",\"%s %s %s(%s)\",\"%s\",%d\r\n",
no++, modifiersName, returnName, methodName, paramName,
getFirstLine(methodDoc.commentText()), mtdLine));
}
}
bw.close();
System.out.println("REPORT : " + report.getAbsolutePath());
}
/**
* classDoc が AWT コンポーネントを継承しているかどうかを調べます.
*
* @param classDoc 検査対象
* @return true : AWT コンポーネント <br/> false : AWT コンポーネントでない
*/
private boolean isGuiComponet(final ClassDoc classDoc) {
if (classDoc == null) {
return false;
}
if (classDoc.qualifiedName().startsWith("java.awt")) {
return true;
}
return isGuiComponet(classDoc.superclass());
}
/**
* doclet のコマンドオプションにフラグ option があるかを調べます.
*
* @param rootDoc rootDoc
* @param option 調査対象の option
* @return true : あり <br/> false : なし
*/
private String findOptionValue(final RootDoc rootDoc, final String option) {
for (String[] param : rootDoc.options()) {
if (param[0].equals(option)) {
return param[1];
}
}
return null;
}
/**
* doclet のコマンドオプションに項目 option があるかを調べます.
*
* @param rootDoc rootDoc
* @param option 調査対象の option
* @return option の値
*/
private boolean findOptionFlag(final RootDoc rootDoc, final String option) {
for (String[] param : rootDoc.options()) {
if (param[0].equals(option)) {
return true;
}
}
return false;
}
/**
* Javadoc の 1行目を取得します.
*
* @param doc Javadoc
* @return 1行目
*/
private String getFirstLine(final String doc) {
if (doc == null) {
return "";
}
// 1行目を取り出し、HTMLタグ (<br/>) があれば削除する
// " は "" にする (CSVの制約)
String[] parts = doc.split("[\r\n]");
return parts[0]
.replaceAll("<.*>", "")
.replaceAll("\"", "\"\"");
}
/**
* setter に対応する getter があるかどうかを調べます.
*
* @param getter
* @return
*/
private boolean findGetter(final ClassDoc classDoc, final MethodDoc setter) {
//メソッド名
String methodName = setter.name();
return findMethod(classDoc, methodName.replace("set", "get"));
}
/**
* getter に対応する setter があるかどうかを調べます.
*
* @param getter
* @return
*/
private boolean findSetter(final ClassDoc classDoc, final MethodDoc getter) {
//メソッド名
String methodName = getter.name();
return findMethod(classDoc, methodName.replace("get", "set"));
}
/**
* class に、引数が arg で返値が ret のメソッド method があるかどうかを調べます
*
* @param classDoc Class
* @param method メソッド名
* @return true あり<br/>false なし
*/
private boolean findMethod(final ClassDoc classDoc, final String method) {
for (MethodDoc methodDoc : classDoc.methods()) {
//メソッド名
String methodName = methodDoc.name();
if (method.equals(methodName)) {
return true;
}
}
return false;
}
}
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.docletexam</groupId>
<artifactId>doclet</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>doclet</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.7</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.3</version>
<configuration>
<locales>ja</locales>
<inputEncoding>UTF-8</inputEncoding>
<outputEncoding>UTF-8</outputEncoding>
<reportPlugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration>
<doclet>com.mycompany.docletexamt.MethodListGenerator</doclet>
<encoding>UTF-8</encoding>
<access>private</access>
<docletPath>target/doclet-0.0.1-SNAPSHOT.jar</docletPath>
<additionalparam>-d doc\report.csv -ignore-get-set -ignore-gui</additionalparam>
</configuration>
</plugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
</project>
$ javadoc -doclet com.mycompany.docletexam.MethodListGenerator -docletpath target/doclet-0.0.1-SNAPSHOT.jar -sourcepath src/main/java/ -public com.mycompany.docletexam -d summary.csv
pom.xml からも実行できる (使用例は MethodListGenerator? の pom.xml)