JToH.java

HTML Generated on 10 Apr 2000 by JToH
    1  package com.showmejava.jtoh;
    2  
    3  //////////////////////////////////////////////////////////////////////////////
    4  // Copyright (c) 2000, Eric M. Burke (ericb@showmejava.com)
    5  // All rights reserved.
    6  // Redistribution and use in source and binary forms, with or without 
    7  // modification, are permitted provided that the following conditions are met:
    8  //
    9  // - Redistributions of source code must retain the above copyright notice,
   10  //   this list of conditions and the following disclaimer.
   11  // 
   12  // - Redistributions in binary form must reproduce the above copyright notice,
   13  //   this list of conditions and the following disclaimer in the documentation
   14  //   and/or other materials provided with the distribution.
   15  // 
   16  // - Neither name of the ShowMeJava.com nor the names of its contributors may 
   17  //   be used to endorse or promote products derived from this software without
   18  //   specific prior written permission. 
   19  // 
   20  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
   21  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   22  // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   23  // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
   24  // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  // POSSIBILITY OF SUCH DAMAGE. 
   31  /////////////////////////////////////////////////////////////////////////////
   32  
   33  import java.io.*;
   34  import java.text.SimpleDateFormat;
   35  import java.util.Date;
   36  
   37  /**
   38   * Convert Java source code into HTML.
   39   *
   40   * @author Eric M. Burke
   41   * @version $Id: JToH.java,v 1.3 2000/04/11 03:11:00 ericb Exp $
   42   */
   43  public class JToH implements Serializable {
   44      private static final int BUF_SIZE = 2000;
   45  
   46      // initialize to non-null values for JavaBeans support
   47      private String title = "";
   48      private String header = "";
   49      private String footer = "";
   50      private String styleSheetName = "jtoh.css";
   51      private boolean useLineNumbers = false;
   52              
   53      /**
   54       * Entry point when running as a standalone application.
   55       */
   56      public static void main(String[] args) throws IOException {
   57          if (args.length < 1) {
   58              System.err.println("usage: java com.showmejava.jtoh.JToH "
   59                      + "javafile [htmlfile]");
   60              System.exit(1);
   61          }
   62          String javafile = null;
   63          String htmlfile = null;
   64          javafile = args[0];
   65          if (args.length > 1) {
   66              htmlfile = args[1];
   67          }
   68          
   69          BufferedReader in = new BufferedReader(new FileReader(javafile));
   70          PrintWriter out = null;
   71          if (htmlfile == null) {
   72              out = new PrintWriter(new OutputStreamWriter(System.out));
   73          } else {
   74              out = new PrintWriter(new BufferedWriter(
   75                      new FileWriter(htmlfile)));
   76          }
   77          JToH translator = new JToH();
   78  
   79          // create a header
   80          SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy");
   81          StringBuffer header = new StringBuffer();
   82          header.append("<h2>").append(javafile).append("</h2>\n");
   83          header.append("<b><i>HTML Generated on ");
   84          header.append(sdf.format(new Date()));
   85          header.append(" by <a href='http://www.showmejava.com/jtoh/'>");
   86          header.append("JToH</a></i></b>\n");
   87          header.append("<hr>\n");
   88  
   89          translator.setTitle(javafile);
   90          translator.setUseLineNumbers(true);
   91          translator.setHeader(header.toString());
   92          translator.translateHTML(in, out);
   93      }
   94  
   95      /**
   96       * @param useLineNumbers if true, include line numbers in the output.
   97       */
   98      public void setUseLineNumbers(boolean useLineNumbers) {
   99          this.useLineNumbers = useLineNumbers;
  100      }
  101  
  102      /**
  103       * @return true if line numbering is enabled.
  104       */
  105      public boolean getUseLineNumbers() {
  106          return useLineNumbers;
  107      }
  108  
  109      /**
  110       * @param title the title for the generated HTML web page.
  111       */
  112      public void setTitle(String title) {
  113          this.title = title;
  114      }
  115  
  116      /**
  117       * @return the title for the generated HTML web page.
  118       */
  119      public String getTitle() {
  120          return title;
  121      }
  122  
  123      /**
  124       * @param styleSheetName alternate name for the cascading style sheet.
  125       * The default value is jtoh.css.
  126       */
  127      public void setStyleSheetName(String styleSheetName) {
  128          this.styleSheetName = styleSheetName;
  129      }
  130  
  131      /**
  132       * @return the name of the cascading style sheet.
  133       */
  134      public String getStyleSheetName() {
  135          return styleSheetName;
  136      }
  137  
  138      /**
  139       * @param optional HTML to insert just before the generated code.
  140       */
  141      public void setHeader(String header) {
  142          this.header = header;
  143      }
  144  
  145      /**
  146       * @return HTML to insert just before the generated code.
  147       */
  148      public String getHeader() {
  149          return header;
  150      }
  151  
  152      /**
  153       * @param footer optional HTML to insert just after the generated code.
  154       */
  155      public void setFooter(String footer) {
  156          this.footer = footer;
  157      }
  158  
  159      /**
  160       * @return HTML to insert just after the generated code.
  161       */
  162      public String getFooter() {
  163          return footer;
  164      }
  165  
  166  
  167      /**
  168       * Perform Java to HTML conversion.
  169       *
  170       * @param in the Java source code.
  171       * @param out the destination for the HTML.  If null, simply send output
  172       *            to System.out.
  173       * @exception IOException if a file cannot be read from or written to.
  174       */
  175      public void translateHTML(BufferedReader in, PrintWriter out) 
  176              throws IOException {
  177          if (out == null) {
  178              out = new PrintWriter(new OutputStreamWriter(System.out));
  179          }
  180  
  181          out.println("<html>");
  182          out.println("<head>");
  183          out.println("<meta name=\"GENERATOR\" content=\"JToH\">");
  184          out.print("<title>");
  185          out.print(title);
  186          out.println("</title>");
  187          out.print("<link href=\"");
  188          out.print(styleSheetName);
  189          out.println("\" rel=\"stylesheet\" type=\"text/css\">");
  190          out.println("</head>");
  191          out.println("<body>");
  192  
  193          out.println(header);
  194          translateBody(in, out);
  195          out.println(footer);
  196          
  197          out.println("</body>");
  198          out.println("</html>");
  199          out.close();
  200      }
  201  
  202  
  203      /**
  204       * Translate just the source code portion.  You can optionally call this
  205       * method if you just want the preformatted source code, without all
  206       * of the other HTML tags.  This is useful if you wish to embed source
  207       * code into another web page that some Servlet is generating.
  208       *
  209       * @param in the input source containing Java code.
  210       * @param out the destination for HTML.
  211       * @exception IOException if I/O fails.
  212       */
  213      public void translateBody(BufferedReader in, PrintWriter out)
  214              throws IOException {
  215          out.print("<pre>");
  216          translate(in, out);
  217          out.println("</pre>");
  218      }
  219      
  220      
  221      // do the actual source code analysis and conversion
  222      private void translate(BufferedReader in, PrintWriter out) 
  223              throws IOException {
  224  
  225          // The destination initializes to out.  If line numbers are enabled,
  226          // then first write to an alternate destination.
  227          PrintWriter dest = out;
  228          CharArrayWriter cawOut =null;
  229          if (useLineNumbers) {
  230              cawOut = new CharArrayWriter();
  231              dest = new PrintWriter(cawOut);
  232          }
  233  
  234          // read the input document into an array of characters
  235          CharArrayWriter cawIn = new CharArrayWriter();
  236          char[] cbufIn = new char[BUF_SIZE];
  237          int numCharsRead = in.read(cbufIn, 0, cbufIn.length);
  238          while (numCharsRead > -1) {
  239              cawIn.write(cbufIn, 0, numCharsRead);
  240              numCharsRead = in.read(cbufIn, 0, cbufIn.length);
  241          }
  242          in.close();
  243          char[] characters = cawIn.toCharArray();
  244          
  245          WhitespaceState whitespaceState = new WhitespaceState(characters);
  246          
  247          State[] states = new State[] {
  248              new SingleLineCommentState(characters),
  249              new MultiLineCommentState(characters),
  250              new QuoteState(characters),
  251              new AposState(characters),
  252              new KeywordState(characters)
  253          };
  254  
  255          int curPos = 0;
  256          while (curPos < characters.length) {
  257              State curState = null;
  258              for (int i=0; i<states.length; i++) {
  259                  if (states[i].isStartPos(curPos)) {
  260                      curState = states[i];
  261                      curState.setStartPos(curPos);
  262                      break;
  263                  }
  264              }
  265  
  266              // if none of the states match, use WhitespaceState
  267              if (curState == null) {
  268                  curState = whitespaceState;
  269                  curState.setStartPos(curPos);
  270              }
  271              
  272              curState.write(dest);
  273              curPos = curState.getEndPos();
  274          }
  275  
  276          // append line numbers if enabled
  277          if (useLineNumbers) {
  278              // five characters of padding supports files with up to 
  279              // 99999 lines of code.
  280              char[] padding = "     ".toCharArray();
  281  
  282              BufferedReader br = new BufferedReader(new StringReader(
  283                     cawOut.toString())); 
  284              int curLineNumber = 1;
  285              String curLine = br.readLine();
  286              while (curLine != null) {
  287                  char[] curLineNumberAsChars = 
  288                          Integer.toString(curLineNumber).toCharArray();
  289  
  290                  // this will first happen on files containing more than
  291                  // 99999 lines of code, which is unlikely but conceivable.
  292                  if (curLineNumberAsChars.length > padding.length) {
  293                      padding = ((new String(padding)) + " ").toCharArray();
  294                  }
  295  
  296                  System.arraycopy(curLineNumberAsChars, 0, padding,
  297                          padding.length-curLineNumberAsChars.length,
  298                          curLineNumberAsChars.length);
  299  
  300                  out.println("<font class=\"lineNum\">" + new String(padding) 
  301                          + " </font> " + curLine);
  302                  curLineNumber++;
  303                  curLine = br.readLine();
  304              }
  305          }
  306      }
  307  }