ツールAPI(javax.tools)でJavadoc出力 #java8
ちょうど1ヶ月前に、カスタムDocletでJavadoc情報をCSV出力というエントリーを書きました。
今回は、Java8から使えるようになった、javax.tools.DocumentationTool
を使ってJavadocを実行するプログラムを試します。
環境
- Windows7 Professional 32bit
- Java8 ea (b121)
概要
Java8の新機能「Javadoc APIのjavax.toolsへの追加」(Java SE 8 (5) - プラットフォーム、セキュリティー、他参照)により、tools.jar
を使わなくてもJavadocをプログラムから呼び出すプログラムが書けるようになりました。
ただし、実行するときは、これまでと同じく、クラスパスにtools.jar
を設定する必要があります。コンパイル時に不要になったということです。
プログラム例
- javax.tools.DocumentationToolを使ったプログラム
// import java.io.File; // import java.io.IOException; // import java.io.Writer; // import java.util.Arrays; // import java.util.EnumSet; // import javax.tools.Diagnostic; // import javax.tools.DiagnosticCollector; // import javax.tools.DocumentationTool; // import javax.tools.JavaFileObject; // import javax.tools.StandardJavaFileManager; // import javax.tools.StandardLocation; // import javax.tools.ToolProvider; // throws IOException // File outputDir = new File(...); // File srcDir = new File(...); // String rootPackage = ...; if (!outputDir.exists()) if (!outputDir.mkdirs()) throw new IOException("can't make dir: " + outputDir); DocumentationTool tool = ToolProvider.getSystemDocumentationTool(); DiagnosticCollector<JavaFileObject> diag = new DiagnosticCollector<>(); try (StandardJavaFileManager fileManager = tool.getStandardFileManager(diag, null, null)) { fileManager.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outputDir)); fileManager.setLocation(StandardLocation.SOURCE_PATH, Arrays.asList(srcDir)); Writer out = null; // use STDERR(System.err) Class<?> docletClass = null; // use default doclet Iterable<String> options = Arrays.asList("-private"); Iterable<? extends JavaFileObject> compilationUnits = fileManager.list( // StandardLocation.SOURCE_PATH, // location rootPackage, // package name EnumSet.of(JavaFileObject.Kind.SOURCE), // kinds true); // recurse DocumentationTool.DocumentationTask task = tool.getTask(out, fileManager, diag, docletClass, options, compilationUnits); if (task.call()) System.out.println("OK"); else for (Diagnostic<? extends JavaFileObject> o : diag.getDiagnostics()) System.out.println(o.getMessage(null)); }
入力パラメーターは、
outputDir
: 出力先ディレクトリ(例./doc
)srcDir
: Javadoc生成対象ソースファイルのルートディレクトリ(相対パスでも可)rootPackage
: Javadoc生成対象クラスのルートパッケージ
を設定します。
このまま実行すると、
compiler message file broken: key=javadoc.err.msg arguments=javadoc, docletクラスcom.sun.tools.doclets.standard.Standardが見つかりません, {2}, {3}, {4}, {5}, {6}, {7} エラー1個
というエラーが出てしまいます。(メッセージがちょっと変ですね。)
デフォルトドックレットは、tools.jar
に含まれるcom.sun.tools.doclets.standard.Standard
が使用されているので、実行時クラスパスにtools.jar
を設定する必要があります。
この例では、オプション要素として、コマンドラインパラメーターと、カスタムドックレットの指定があります。
options
は、コマンドラインから指定するのと同じように、文字列配列をコマンドラインパラメーターとして設定することができます。例えば、outputDir
は、ここで設定することもできます。上記の例では、パッケージスコープを-private
に設定しています。
もう1つのカスタムドックレットは、従来の場合と同様に、カスタムドックレットのクラスを指定します。ただし、カスタムドックレットをコンパイルする場合は、tools.jar
などのドックレット実装がクラスパスに設定されている必要があります。
その他補足。
compilationUnits
は、StandardJavaFileManager#getJavaFileObjects
メソッドで相対パス文字列を使って取得することもできます。
- パス文字列を使って
Iterable<? extends JavaFileObject>
を取得する
// import省略 Function<String, String> f = x -> "../anotherproj/src/net/argius/" + x + ".java"; String[] paths = Stream.of("Class1", "Class3").map(f).toArray(String[]::new); Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(paths);
以上です。