| /* |
| * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| */ |
| |
| package com.sun.tools.doclets.internal.toolkit.util; |
| |
| import com.sun.tools.doclets.internal.toolkit.*; |
| import com.sun.javadoc.*; |
| import java.io.*; |
| import java.util.*; |
| |
| /** |
| * Converts Java Source Code to HTML. |
| * |
| * This code is not part of an API. |
| * It is implementation that is subject to change. |
| * Do not use it as an API |
| * |
| * @author Jamie Ho |
| * @since 1.4 |
| */ |
| public class SourceToHTMLConverter { |
| |
| /** |
| * The background color. |
| */ |
| protected static final String BGCOLOR = "white"; |
| |
| /** |
| * The line number color. |
| */ |
| protected static final String LINE_NO_COLOR = "green"; |
| |
| /** |
| * The number of trailing blank lines at the end of the page. |
| * This is inserted so that anchors at the bottom of small pages |
| * can be reached. |
| */ |
| protected static final int NUM_BLANK_LINES = 60; |
| |
| |
| /** |
| * Source is converted to HTML using static methods below. |
| */ |
| private SourceToHTMLConverter() {} |
| |
| /** |
| * Convert the Classes in the given RootDoc to an HTML. |
| * @param configuration the configuration. |
| * @param rd the RootDoc to convert. |
| * @param outputdir the name of the directory to output to. |
| */ |
| public static void convertRoot(Configuration configuration, RootDoc rd, String outputdir) { |
| if (rd == null || outputdir == null) { |
| return; |
| } |
| PackageDoc[] pds = rd.specifiedPackages(); |
| for (int i = 0; i < pds.length; i++) { |
| convertPackage(configuration, pds[i], outputdir); |
| } |
| ClassDoc[] cds = rd.specifiedClasses(); |
| for (int i = 0; i < cds.length; i++) { |
| convertClass(configuration, cds[i], |
| getPackageOutputDir(outputdir, cds[i].containingPackage())); |
| } |
| } |
| |
| /** |
| * Convert the Classes in the given Package to an HTML. |
| * @param configuration the configuration. |
| * @param pd the Package to convert. |
| * @param outputdir the name of the directory to output to. |
| */ |
| public static void convertPackage(Configuration configuration, PackageDoc pd, String outputdir) { |
| if (pd == null || outputdir == null) { |
| return; |
| } |
| String classOutputdir = getPackageOutputDir(outputdir, pd); |
| ClassDoc[] cds = pd.allClasses(); |
| for (int i = 0; i < cds.length; i++) { |
| convertClass(configuration, cds[i], classOutputdir); |
| } |
| } |
| |
| /** |
| * Return the directory write output to for the given package. |
| * @param outputDir the directory to output to. |
| * @param pd the Package to generate output for. |
| */ |
| private static String getPackageOutputDir(String outputDir, PackageDoc pd) { |
| return outputDir + File.separator + |
| DirectoryManager.getDirectoryPath(pd) + File.separator; |
| } |
| |
| /** |
| * Convert the given Class to an HTML. |
| * @param configuration the configuration. |
| * @param cd the class to convert. |
| * @param outputdir the name of the directory to output to. |
| */ |
| public static void convertClass(Configuration configuration, ClassDoc cd, String outputdir) { |
| if (cd == null || outputdir == null) { |
| return; |
| } |
| File file; |
| SourcePosition sp = cd.position(); |
| if (sp == null || (file = sp.file()) == null) { |
| return; |
| } |
| try { |
| int lineno = 1; |
| String line; |
| StringBuffer output = new StringBuffer(); |
| LineNumberReader reader = new LineNumberReader(new FileReader(file)); |
| try { |
| while ((line = reader.readLine()) != null) { |
| output.append(formatLine(line, configuration.sourcetab, lineno)); |
| lineno++; |
| } |
| } finally { |
| reader.close(); |
| } |
| output = addLineNumbers(output.toString()); |
| output.insert(0, getHeader()); |
| output.append(getFooter()); |
| writeToFile(output.toString(), outputdir, cd.name(), configuration); |
| } catch (Exception e){ |
| e.printStackTrace(); |
| } |
| } |
| |
| /** |
| * Write the output to the file. |
| * @param output the string to output. |
| * @param outputDir the directory to output to. |
| * @param className the name of the class that I am converting to HTML. |
| * @param configuration the Doclet configuration to pass notices to. |
| */ |
| private static void writeToFile(String output, String outputDir, String className, Configuration configuration) throws IOException { |
| File dir = new File(outputDir); |
| dir.mkdirs(); |
| File newFile = new File(dir, className + ".html"); |
| configuration.message.notice("doclet.Generating_0", newFile.getPath()); |
| FileOutputStream fout = new FileOutputStream(newFile); |
| BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fout)); |
| bw.write(output); |
| bw.close(); |
| fout.close(); |
| } |
| |
| /** |
| * Given a <code>String</code>, add line numbers. |
| * @param s the text to add line numbers to. |
| * |
| * @return the string buffer with the line numbering for each line. |
| */ |
| private static StringBuffer addLineNumbers(String s) { |
| StringBuffer sb = new StringBuffer(); |
| StringTokenizer st = new StringTokenizer(s, "\n", true); |
| int lineno = 1; |
| String current; |
| while(st.hasMoreTokens()){ |
| current = st.nextToken(); |
| sb.append(current.equals("\n") ? |
| getHTMLLineNo(lineno) + current : |
| getHTMLLineNo(lineno) + current + st.nextToken()); |
| lineno++; |
| } |
| return sb; |
| } |
| |
| /** |
| * Get the header. |
| * @return the header to the output file |
| */ |
| protected static String getHeader() { |
| StringBuffer result = new StringBuffer("<HTML>" + DocletConstants.NL); |
| result.append("<BODY BGCOLOR=\""+ BGCOLOR + "\">" + DocletConstants.NL); |
| result.append("<PRE>" + DocletConstants.NL); |
| return result.toString(); |
| } |
| |
| /** |
| * Get the footer |
| * @return the footer to the output file |
| */ |
| protected static String getFooter() { |
| StringBuffer footer = new StringBuffer(); |
| for (int i = 0; i < NUM_BLANK_LINES; i++) { |
| footer.append(DocletConstants.NL); |
| } |
| footer.append("</PRE>" + DocletConstants.NL + "</BODY>" + |
| DocletConstants.NL + "</HTML>" + DocletConstants.NL); |
| return footer.toString(); |
| } |
| |
| /** |
| * Get the HTML for the lines. |
| * @param lineno The line number |
| * @return the HTML code for the line |
| */ |
| protected static String getHTMLLineNo(int lineno) { |
| StringBuffer result = new StringBuffer("<FONT color=\"" + LINE_NO_COLOR |
| + "\">"); |
| if (lineno < 10) { |
| result.append("00" + ((new Integer(lineno)).toString())); |
| } else if (lineno < 100) { |
| result.append("0" + ((new Integer(lineno)).toString())); |
| } else { |
| result.append((new Integer(lineno)).toString()); |
| } |
| result.append("</FONT> "); |
| return result.toString(); |
| } |
| |
| /** |
| * Format a given line of source. <br> |
| * Note: In the future, we will add special colors for constructs in the |
| * language. |
| * @param line the string to format. |
| * @param tabLength the number of spaces for each tab. |
| * @param currentLineNo the current number. |
| */ |
| protected static String formatLine(String line, int tabLength, int currentLineNo) { |
| if (line == null) { |
| return null; |
| } |
| StringBuffer lineBuffer = new StringBuffer(Util.escapeHtmlChars(line)); |
| //Insert an anchor for the line |
| lineBuffer.append("<a name=\"line." + Integer.toString(currentLineNo) + "\"></a>"); |
| lineBuffer.append(DocletConstants.NL); |
| Util.replaceTabs(tabLength, lineBuffer); |
| return lineBuffer.toString(); |
| } |
| |
| /** |
| * Given an array of <code>Doc</code>s, add to the given <code>HashMap</code> the |
| * line numbers and anchors that should be inserted in the output at those lines. |
| * @param docs the array of <code>Doc</code>s to add anchors for. |
| * @param hash the <code>HashMap</code> to add to. |
| */ |
| protected static void addToHash(Doc[] docs, HashMap<Integer,String> hash) { |
| if(docs == null) { |
| return; |
| } |
| for(int i = 0; i < docs.length; i++) { |
| hash.put(docs[i].position().line(), getAnchor(docs[i])); |
| } |
| } |
| |
| /** |
| * Given a <code>Doc</code>, return an anchor for it. |
| * @param d the <code>Doc</code> to check. |
| * @return an anchor of the form <a name="my_name"></a> |
| */ |
| protected static String getAnchor(Doc d) { |
| return " <a name=\"" + getAnchorName(d) + "\"></a>"; |
| } |
| |
| /** |
| * Given a <code>Doc</code>, return an anchor name for it. |
| * @param d the <code>Doc</code> to check. |
| * @return the name of the anchor. |
| */ |
| public static String getAnchorName(Doc d) { |
| return "line." + d.position().line(); |
| } |
| } |