001/* 002 * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package org.jdrupes.mdoclet.internal.api; 027 028import java.io.InputStream; 029import java.io.OutputStream; 030import java.io.OutputStreamWriter; 031import java.io.PrintWriter; 032import java.io.Writer; 033import java.nio.charset.Charset; 034import java.util.Collections; 035import java.util.EnumSet; 036import java.util.Locale; 037import java.util.Objects; 038import java.util.Set; 039 040import javax.lang.model.SourceVersion; 041import javax.tools.DiagnosticListener; 042import javax.tools.DocumentationTool; 043import javax.tools.JavaFileManager; 044import javax.tools.JavaFileObject; 045import javax.tools.StandardJavaFileManager; 046 047import jdk.javadoc.internal.tool.ToolOptions; 048 049import com.sun.tools.javac.api.ClientCodeWrapper; 050import com.sun.tools.javac.file.JavacFileManager; 051import com.sun.tools.javac.file.BaseFileManager; 052import com.sun.tools.javac.util.ClientCodeException; 053import com.sun.tools.javac.util.Context; 054import com.sun.tools.javac.util.Log; 055 056import org.jdrupes.mdoclet.internal.api.JavadocTaskImpl; 057 058/** 059 * Provides access to functionality specific to the JDK documentation tool, 060 * javadoc. 061 */ 062public class JavadocTool implements DocumentationTool { 063 064 @Override 065 public String name() { 066 return "javadoc"; 067 } 068 069 @Override 070 public DocumentationTask getTask( 071 Writer out, 072 JavaFileManager fileManager, 073 DiagnosticListener<? super JavaFileObject> diagnosticListener, 074 Class<?> docletClass, 075 Iterable<String> options, 076 Iterable<? extends JavaFileObject> compilationUnits) { 077 Context context = new Context(); 078 return getTask(out, fileManager, diagnosticListener, 079 docletClass, options, compilationUnits, context); 080 } 081 082 public DocumentationTask getTask( 083 Writer out, 084 JavaFileManager fileManager, 085 DiagnosticListener<? super JavaFileObject> diagnosticListener, 086 Class<?> docletClass, 087 Iterable<String> options, 088 Iterable<? extends JavaFileObject> compilationUnits, 089 Context context) { 090 try { 091 ClientCodeWrapper ccw = ClientCodeWrapper.instance(context); 092 093 if (options != null) { 094 for (String option : options) 095 Objects.requireNonNull(option); 096 } 097 098 if (compilationUnits != null) { 099 compilationUnits = ccw.wrapJavaFileObjects(compilationUnits); // implicit 100 // null 101 // check 102 for (JavaFileObject cu : compilationUnits) { 103 if (cu.getKind() != JavaFileObject.Kind.SOURCE) { 104 final String kindMsg 105 = "All compilation units must be of SOURCE kind"; 106 throw new IllegalArgumentException(kindMsg); 107 } 108 } 109 } 110 111 if (diagnosticListener != null) 112 context.put(DiagnosticListener.class, 113 ccw.wrap(diagnosticListener)); 114 115 if (out == null) 116 context.put(Log.errKey, new PrintWriter(System.err, true)); 117 else if (out instanceof PrintWriter pout) 118 context.put(Log.errKey, pout); 119 else 120 context.put(Log.errKey, new PrintWriter(out, true)); 121 122 if (fileManager == null) { 123 fileManager 124 = getStandardFileManager(diagnosticListener, null, null); 125 if (fileManager instanceof BaseFileManager bfm) { 126 bfm.autoClose = true; 127 } 128 } 129 fileManager = ccw.wrap(fileManager); 130 context.put(JavaFileManager.class, fileManager); 131 132 return new JavadocTaskImpl(context, docletClass, options, 133 compilationUnits); 134 } catch (ClientCodeException ex) { 135 throw new RuntimeException(ex.getCause()); 136 } 137 } 138 139 // TODO: used shared static method in JavacFileManager 140 @Override 141 public StandardJavaFileManager getStandardFileManager( 142 DiagnosticListener<? super JavaFileObject> diagnosticListener, 143 Locale locale, 144 Charset charset) { 145 Context context = new Context(); 146 context.put(Locale.class, locale); 147 if (diagnosticListener != null) 148 context.put(DiagnosticListener.class, diagnosticListener); 149 PrintWriter pw = (charset == null) 150 ? new PrintWriter(System.err, true) 151 : new PrintWriter(new OutputStreamWriter(System.err, charset), 152 true); 153 context.put(Log.errKey, pw); 154 return new JavacFileManager(context, true, charset); 155 } 156 157 @Override 158 public int run(InputStream in, OutputStream out, OutputStream err, 159 String... arguments) { 160 PrintWriter err_pw 161 = new PrintWriter(err == null ? System.err : err, true); 162 PrintWriter out_pw = new PrintWriter(out == null ? System.out : out); 163 try { 164 return jdk.javadoc.internal.tool.Main.execute(arguments, 165 err_pw); 166 } finally { 167 err_pw.flush(); 168 out_pw.flush(); 169 } 170 } 171 172 @Override 173 public Set<SourceVersion> getSourceVersions() { 174 return Collections.unmodifiableSet( 175 EnumSet.range(SourceVersion.RELEASE_3, SourceVersion.latest())); 176 } 177 178 @Override 179 public int isSupportedOption(String option) { 180 if (option == null) 181 throw new NullPointerException(); 182 return ToolOptions.isSupportedOption(option); 183 } 184 185}