1 /* gnu.classpath.tools.java2xhtml.Java2xhtml
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 /** Java2xhtml.java Version 0.9
39 * Produces an XHTML file from Java source code with syntax highlighting,
40 * includes additional options (line numbering, tab spacing, etc.)
42 * NOTE: Common java naming structure is assumed
43 * Capitalize the first letter that appears in a class or interface name
44 * Use lowercase for the first letter in a method or variable name
45 * Use only uppercase letters when naming constants
47 * @version 0.9, March 2003
48 * @author Shayne Steele
50 package gnu.classpath.tools.java2xhtml;
55 public class Java2xhtml
57 //--- define CSS classes for individual output elements
59 private static final String sourceCodeStyle = "source";
60 private static final String lineNumberStyle = "line-number even";
61 private static final String modulusLineNumberStyle = "line-number odd";
63 private static final String keywordStyle = "keyword";
64 private static final String methodStyle = "method member";
65 private static final String variableStyle = "variable member";
66 private static final String singleLineCommentStyle = "line comment";
67 private static final String traditionalCommentStyle = "c comment";
68 private static final String javadocCommentStyle = "javadoc comment";
69 private static final String javadocTagStyle = "javadoc tag";
70 private static final String importNameStyle = "import header type";
71 private static final String packageNameStyle = "package header type";
72 private static final String primitiveTypeStyle = "primitive type";
73 private static final String nonPrimitiveTypeStyle = "non-primitive type";
74 private static final String constructorStyle = "constructor member";
75 private static final String constantStyle = "constant member";
76 private static final String doubleQuoteStyle = "double quote";
77 private static final String singleQuoteStyle = "single quote";
78 private static final String numericLiteralStyle = "numeric literal";
79 private static final String primitiveLiteralStyle = "primitive literal";
81 private static final String iconStyle = "icon";
85 // parse the command line arguments
86 // give a decent responce for bad input
87 // call the HTMLifier on good input
88 public static void main(String args[])
90 // parse the invokation arguments
91 if (args.length < 1 || args.length > 3) // invoked program incorrectly
93 System.out.println("Java2xhtml Version 0.9 (C) 2005 Free Software Foundation");
94 System.out.println(" Produces an XHTML file of Java source" +
95 " code with syntax highlighting,");
96 System.out.println(" includes additional options " +
97 "(line numbering, tab spacing, etc.)");
98 System.out.println(" This tool is part of GNU Classpath.");
99 System.out.println(" GNU Classpath is free software; you can redistribute it and/or modify");
100 System.out.println(" it under the terms of the GNU General Public License as published by");
101 System.out.println(" the Free Software Foundation; either version 2, or (at your option)");
102 System.out.println(" any later version.");
103 System.out.println(" NOTE: Common java naming structure is " +
105 System.out.println("");
106 System.out.println("USAGE:");
107 System.out.println("java [java options] Java2xhtml " +
108 "source.java [options file] " +
110 System.out.println("");
111 System.out.println(" - java is the name of the Java interpreter");
112 System.out.println(" - [java options] are the optional options " +
113 "of the Java interpreter");
114 System.out.println(" - Java2xhtml is the name of this " +
116 System.out.println(" - source is a file or the directory to the " +
117 "Java source file(s)");
118 System.out.println(" - [options file] is the optional " +
119 "path of a file with");
120 System.out.println(" a structure like this:");
121 System.out.println(" externalStyleSheetName=file_name" +
122 " (default style.css)");
123 System.out.println(" tabSize=integer (default value is 4)");
124 System.out.println(" extraIndentation=integer " +
125 "(default value is 0)");
126 System.out.println(" lineModulus=integer (default value 5)");
127 System.out.println(" isCodeSnippet=boolean" +
129 System.out.println(" isXHTML_1_1=boolean" +
131 System.out.println(" hasInternalStyleSheet=boolean" +
133 System.out.println(" hasExternalStyleSheet=boolean" +
135 System.out.println(" hasTitle=boolean" +
137 System.out.println(" hasLegend=boolean" +
139 System.out.println(" hasAllBoldSourceCode=boolean" +
141 System.out.println(" hasLineNumbers=boolean" +
143 System.out.println(" hasLineModulusDrawnLines=boolean" +
145 System.out.println(" hasLineModulusCodeBlocks=boolean" +
147 System.out.println(" hasFooter=boolean" +
149 System.out.println(" hasFooterIcons=boolean" +
151 System.out.println(" hasFooterDate=boolean" +
153 System.out.println(" NOTE: filename must end with '.prop'");
154 System.out.println(" Default [options file] is " +
156 System.out.println(" - [output file] is name of the XHTML file " +
158 System.out.println(" Default [output file] is source_java.html");
159 System.out.println("");
160 System.out.println("Output: source.java --> [output file]");
161 System.out.println(" Default Output is ");
162 System.out.println(" source.java --> source_java.html");
163 System.out.println("");
164 System.out.println("Examples of calling the program:");
165 System.out.println(" process one file (say Java2xhtml.java):");
166 System.out.println(" java Java2xhtml Java2xhtml.java");
167 System.out.println(" process one directory (say C:\\HOME):");
168 System.out.println(" java Java2xhtml C:\\HOME");
169 System.out.println(" process one directory (say C:\\HOME with a " +
170 "given options file (options.prop)):");
171 System.out.println(" java Java2xhtml C:\\HOME options.prop");
175 // invoked program correctly, now get command line arguments
176 // get the source file name
178 sourceName = args[0];
179 // make sure that the source file exist and if so HTMLify it
180 File sourceFilePath = new File(sourceName);
181 if (sourceFilePath.exists())
183 // good pathname so HTMLify it
184 // get the default html options file name
185 String propertiesFileName = "options.prop";
186 // create a unique default html file name,
187 // bubba.java -> bubba_java.html
188 String htmlFileName = sourceName.replace('.', '_') + ".html";
189 if (args.length == 2 || args.length == 3)
191 if (args[1].endsWith(".prop"))
193 // get the user supplied html options file name
194 propertiesFileName = args[1];
198 // get the user supplied html outputfile name
199 htmlFileName = args[1];
202 if (args.length == 3)
204 if (args[2].endsWith(".prop"))
206 // get the user supplied html options file name
207 propertiesFileName = args[2];
211 // get the user supplied html outputfile name
212 htmlFileName = args[2];
215 new Java2xhtml(propertiesFileName, sourceFilePath,
218 else // source file does not exist, print message and exit normally
220 System.out.println("The source parameter must be an existent" +
221 " file or directory");
222 System.out.println("Run Java2xHtml without parameters for " +
228 // collect various sets of keywords
229 static Collection keywordCollection;
230 static Collection primitiveTypeCollection;
231 static Collection primitiveLiteralCollection;
232 static Collection javadocTagCollection;
234 // all these variables are changeable by a options file
235 int extraIndentation = 0;
238 boolean hasLegend = false;
239 boolean hasLineNumbers = false;
240 boolean hasLineModulusDrawnLines = false;
241 boolean hasLineModulusCodeBlocks = false;
242 boolean hasFooter = false;
243 boolean hasFooterIcons = false;
244 boolean hasFooterDate = true;
245 boolean isCodeSnippet = false;
246 boolean isXHTML_1_1 = true;
247 boolean hasTitle = false;
248 boolean hasAllBoldSourceCode = false;
249 boolean hasInternalStyleSheet = true;
250 boolean hasExternalStyleSheet = true;
251 String externalStyleSheetName = "style.css";
255 // collection type is Hashset for unique elements and fast retieval
256 String keywordArray[] =
258 "abstract", "default", "if", "private",
259 "do", "implements", "protected", "throws",
260 "break", "import", "public", "transient",
261 "else", "instanceof", "return", "try",
262 "case", "extends", "throw", "static",
263 "catch", "final", "interface", "while",
264 "volatile", "finally", "super", "synchronized",
265 "class", "native", "switch", "package",
266 "const", "for", "new", "goto",
267 "continue", "this", "assert", "strictfp"
269 keywordCollection = new HashSet(Arrays.asList(keywordArray));
270 String primitiveTypeArray[] =
272 "boolean", "char", "byte", "short", "int",
273 "long", "float", "double", "void"
275 primitiveTypeCollection =
276 new HashSet(Arrays.asList(primitiveTypeArray));
277 String primitiveLiteralArray[]=
279 "false", "null", "true"
281 primitiveLiteralCollection =
282 new HashSet(Arrays.asList(primitiveLiteralArray));
283 String javadocTagArray[]=
285 "see", "author", "version", "param", "return", "exception",
286 "deprecated", "throws", "link", "since", "serial",
287 "serialField","serialData", "beaninfo"
289 javadocTagCollection = new HashSet(Arrays.asList(javadocTagArray));
296 // create the various keyword collections
297 // parse the html options file
298 Java2xhtml(String propertiesFileName, File sourceFilePath,
301 // get html properties (use defaults if necessary)
302 File propertiesFilePath = new File (propertiesFileName);
303 if (propertiesFilePath.exists())
305 // html properies file exist try parsing it
308 InputStream propertiesFile =
309 new FileInputStream(propertiesFileName);
310 Properties htmlProperties = new Properties();
311 htmlProperties.load(propertiesFile);
312 propertiesFile.close();
313 setProperties(htmlProperties);
315 catch (IOException exception)
317 System.out.println(exception);
320 if (sourceFilePath.isFile())
323 processFile(sourceFilePath, htmlFileName);
325 else if (sourceFilePath.isDirectory())
327 // process a directory
328 File [] sourceFilePathArray = sourceFilePath.listFiles();
329 for (int i = 0; i < sourceFilePathArray.length; i++)
331 if (((sourceFilePathArray[i]).getName()).endsWith(".java"))
333 // process each file that ends in .java
334 // create a unique default html file name,
335 // bubba.java -> bubba_java.html
336 htmlFileName = ((sourceFilePathArray[i]).getName()).replace(
338 processFile(sourceFilePathArray[i], htmlFileName);
344 public void setProperties(Properties htmlProperties)
347 = Boolean.valueOf(htmlProperties.getProperty("hasLegend",
348 "false")).booleanValue();
350 = Integer.parseInt(htmlProperties.getProperty("extraIndentation", "0"));
352 = Integer.parseInt(htmlProperties.getProperty("tabSize", "4"));
354 = Boolean.valueOf(htmlProperties.getProperty("hasLineNumbers",
355 "false")).booleanValue();
357 = Integer.parseInt(htmlProperties.getProperty("lineModulus", "5"));
358 hasLineModulusDrawnLines
359 = Boolean.valueOf(htmlProperties.getProperty("hasLineModulusDrawnLines",
360 "false")).booleanValue();
361 hasLineModulusCodeBlocks
362 = Boolean.valueOf(htmlProperties.getProperty("hasLineModulusCodeBlocks",
363 "false")).booleanValue();
365 = Boolean.valueOf(htmlProperties.getProperty("hasFooter",
366 "false")).booleanValue();
368 = Boolean.valueOf(htmlProperties.getProperty("hasFooterIcons",
369 "false")).booleanValue();
371 = Boolean.valueOf(htmlProperties.getProperty("hasFooterDate",
372 "true")).booleanValue();
374 = Boolean.valueOf(htmlProperties.getProperty("isXHTML_1_1",
375 "true")).booleanValue();
377 = Boolean.valueOf(htmlProperties.getProperty("isCodeSnippet",
378 "false")).booleanValue();
380 = Boolean.valueOf(htmlProperties.getProperty("hasTitle",
381 "false")).booleanValue();
383 = Boolean.valueOf(htmlProperties.getProperty("hasAllBoldSourceCode",
384 "false")).booleanValue();
385 hasInternalStyleSheet
386 = Boolean.valueOf(htmlProperties.getProperty("hasInternalStyleSheet",
387 "true")).booleanValue();
388 hasExternalStyleSheet
389 = Boolean.valueOf(htmlProperties.getProperty("hasExternalStyleSheet",
390 "true")).booleanValue();
391 externalStyleSheetName
392 = htmlProperties.getProperty("externalStyleSheetName", "style.css");
396 // read the file and put it into a stringbuffer
397 void processFile(File sourceFilePath, String htmlFileName)
399 // open the file, copy it to a Stringbuffer , process into an
400 // HTMLified String and convert result into an HTML file
403 BufferedReader sourceReader =
404 new BufferedReader(new FileReader(sourceFilePath));
405 StringBuffer bufferIn = new StringBuffer();
407 char presentChar = 0;
408 // copy file into a Stringbuffer
409 while (readInInt != -1) // -1 value means end of stream/file
411 // put the file into a Stringbuffer
412 readInInt= sourceReader.read();
413 presentChar = ((readInInt >= 0) ? (char) readInInt : 0);
414 bufferIn.append(presentChar);
416 sourceReader.close();
417 BufferedWriter tempBufferedWriter =
418 new BufferedWriter(new FileWriter(htmlFileName));
419 tempBufferedWriter.write(makeHTML(bufferIn,
420 sourceFilePath.getName()));
421 tempBufferedWriter.close();
422 System.out.println(sourceFilePath.getName() + " --> " +
425 catch (IOException exception)
427 System.out.println(exception);
431 // constant 'States' java source code can be in
432 public final static class State
434 public final static State TEXT = new State();
435 public final static State IMPORT_NAME = new State();
436 public final static State PARAM_VARIABLE = new State();
437 public final static State JAVADOC = new State();
438 public final static State PACKAGE_NAME = new State();
439 public final static State DOUBLE_QUOTE = new State();
440 public final static State SINGLE_QUOTE = new State();
441 public final static State TRADITIONAL_COMMENT = new State();
442 public final static State LINE_COMMENT = new State();
451 // Convert java source code StringBufffer into colorized (and tab spaced)
453 // Assumes that Java naming convention is used
454 // Uses a very basic state machine design.
455 public String makeHTML(StringBuffer bufferIn, String sourceFileName)
457 int codeLineNumber = 0;
458 boolean isNewLine = true;
459 boolean isNewBlock = true;
460 int identifierLength = 0;
461 int qualifiedIdentifierLength = 0;
462 int presentIndex = -1;
465 char presentChar = 0;
466 State presentState = State.TEXT;
467 StringBuffer bufferOut = new StringBuffer(8192);
470 bufferOut.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
473 bufferOut.append("<!DOCTYPE html PUBLIC " +
474 "\"-//W3C//DTD XHTML 1.1//EN\"\r\n");
475 bufferOut.append(" \"http://www.w3.org/TR/xhtml11/DTD/" +
476 "xhtml11.dtd\">\r\n");
477 bufferOut.append("<html xmlns=\"http://www.w3.org/1999/xhtml\""+
478 " xml:lang=\"en\">\r\n");
482 bufferOut.append("<!DOCTYPE html PUBLIC " +
483 "\"-//W3C//DTD XHTML 1.0 Strict//EN\"\r\n");
484 bufferOut.append(" \"http://www.w3.org/TR/xhtml1/DTD/" +
485 "xhtml1-strict.dtd\">\r\n");
486 bufferOut.append("<html xmlns=\"http://www.w3.org/1999/xhtml\""+
487 " xml:lang=\"en\" lang=\"en\">\r\n");
489 bufferOut.append(" <head>\r\n");
490 bufferOut.append(" <title>\r\n");
491 bufferOut.append(" " + sourceFileName + "\r\n");
492 bufferOut.append(" </title>\r\n");
493 bufferOut.append(" <meta name=\"generator\"\r\n");
494 bufferOut.append(" content=\"Java2xhtml 0.9\" />\r\n");
495 if (hasInternalStyleSheet)
497 bufferOut.append(" <style type=\"text/css\">\r\n");
498 bufferOut.append(" <!-- /* <![CDATA[ */\r\n");
499 bufferOut.append(" ." + sourceCodeStyle + "\r\n");
500 bufferOut.append(" {\r\n");
501 bufferOut.append(" color: #000000;\r\n");
502 bufferOut.append(" background-color: #FFFFFF;\r\n");
503 if (hasAllBoldSourceCode)
505 bufferOut.append(" font-weight: bold;\r\n");
507 bufferOut.append(" }\r\n");
508 bufferOut.append(" ." + lineNumberStyle + "\r\n");
509 bufferOut.append(" {\r\n");
510 bufferOut.append(" font-weight: normal;\r\n");
511 bufferOut.append(" color: #000000;\r\n");
512 bufferOut.append(" background-color: transparent;\r\n");
513 bufferOut.append(" }\r\n");
516 bufferOut.append(" ." + modulusLineNumberStyle + "\r\n");
517 bufferOut.append(" {\r\n");
518 bufferOut.append(" font-weight: bold;\r\n");
519 bufferOut.append(" color: #000000;\r\n");
520 bufferOut.append(" background-color: ");
521 bufferOut.append("transparent;\r\n");
522 bufferOut.append(" }\r\n");
523 if (hasLineModulusDrawnLines)
525 bufferOut.append(" .modulusLineStyle\r\n");
526 bufferOut.append(" {\r\n");
527 bufferOut.append(" text-decoration: ");
528 bufferOut.append("line-through;\r\n");
529 bufferOut.append(" color: #000000;\r\n");
530 bufferOut.append(" background-color: ");
531 bufferOut.append("transparent;\r\n");
532 bufferOut.append(" }\r\n");
534 if (hasLineModulusCodeBlocks)
536 bufferOut.append(" .modulusBlockPREStyle\r\n");
537 bufferOut.append(" {\r\n");
538 bufferOut.append(" margin: 0em\r\n");
539 bufferOut.append(" }\r\n");
540 bufferOut.append(" .modulusBlockStyle\r\n");
541 bufferOut.append(" {\r\n");
542 bufferOut.append(" color: #000000;\r\n");
543 bufferOut.append(" background-color: ");
544 bufferOut.append("#CCCCCC;\r\n");
545 bufferOut.append(" }\r\n");
548 bufferOut.append(" ." + keywordStyle + "\r\n");
549 bufferOut.append(" {\r\n");
550 bufferOut.append(" color: #9900FF;\r\n");
551 bufferOut.append(" background-color: transparent;\r\n");
552 bufferOut.append(" }\r\n");
553 bufferOut.append(" ." + methodStyle + "\r\n");
554 bufferOut.append(" {\r\n");
555 bufferOut.append(" color: #0000FF;\r\n");
556 bufferOut.append(" background-color: transparent;\r\n");
557 bufferOut.append(" }\r\n");
558 bufferOut.append(" ." + variableStyle + "\r\n");
559 bufferOut.append(" {\r\n");
560 bufferOut.append(" color: #CC9933;\r\n");
561 bufferOut.append(" background-color: transparent;\r\n");
562 bufferOut.append(" }\r\n");
563 bufferOut.append(" ." + singleLineCommentStyle + "\r\n");
564 bufferOut.append(" {\r\n");
565 bufferOut.append(" color: #CC3333;\r\n");
566 bufferOut.append(" background-color: transparent;\r\n");
567 bufferOut.append(" }\r\n");
568 bufferOut.append(" ." + traditionalCommentStyle + "\r\n");
569 bufferOut.append(" {\r\n");
570 bufferOut.append(" color: #FF0000;\r\n");
571 bufferOut.append(" background-color: transparent;\r\n");
572 bufferOut.append(" }\r\n");
573 bufferOut.append(" ." + javadocCommentStyle + "\r\n");
574 bufferOut.append(" {\r\n");
575 bufferOut.append(" color: #CC0033;\r\n");
576 bufferOut.append(" background-color: transparent;\r\n");
577 bufferOut.append(" }\r\n");
578 bufferOut.append(" ." + javadocTagStyle + "\r\n");
579 bufferOut.append(" {\r\n");
580 bufferOut.append(" color: #0099CC;\r\n");
581 bufferOut.append(" background-color: transparent;\r\n");
582 bufferOut.append(" }\r\n");
583 bufferOut.append(" ." + importNameStyle + "\r\n");
584 bufferOut.append(" {\r\n");
585 bufferOut.append(" color: #33CCCC;\r\n");
586 bufferOut.append(" background-color: transparent;\r\n");
587 bufferOut.append(" }\r\n");
588 bufferOut.append(" ." + packageNameStyle + "\r\n");
589 bufferOut.append(" {\r\n");
590 bufferOut.append(" color: #339999;\r\n");
591 bufferOut.append(" background-color: transparent;\r\n");
592 bufferOut.append(" }\r\n");
593 bufferOut.append(" ." + primitiveTypeStyle + "\r\n");
594 bufferOut.append(" {\r\n");
595 bufferOut.append(" color: #009900;\r\n");
596 bufferOut.append(" background-color: transparent;\r\n");
597 bufferOut.append(" }\r\n");
598 bufferOut.append(" ." + nonPrimitiveTypeStyle + "\r\n");
599 bufferOut.append(" {\r\n");
600 bufferOut.append(" color: #009966;\r\n");
601 bufferOut.append(" background-color: transparent;\r\n");
602 bufferOut.append(" }\r\n");
603 bufferOut.append(" ." + constructorStyle + "\r\n");
604 bufferOut.append(" {\r\n");
605 bufferOut.append(" color: #3300CC;\r\n");
606 bufferOut.append(" background-color: transparent;\r\n");
607 bufferOut.append(" }\r\n");
608 bufferOut.append(" ." + constantStyle + "\r\n");
609 bufferOut.append(" {\r\n");
610 bufferOut.append(" color: #666666;\r\n");
611 bufferOut.append(" background-color: transparent;\r\n");
612 bufferOut.append(" }\r\n");
613 bufferOut.append(" ." + doubleQuoteStyle + "\r\n");
614 bufferOut.append(" {\r\n");
615 bufferOut.append(" color: #996633;\r\n");
616 bufferOut.append(" background-color: transparent;\r\n");
617 bufferOut.append(" font-style: italic;\r\n");
618 bufferOut.append(" }\r\n");
619 bufferOut.append(" ." + singleQuoteStyle + "\r\n");
620 bufferOut.append(" {\r\n");
621 bufferOut.append(" color: #663333;\r\n");
622 bufferOut.append(" background-color: transparent;\r\n");
623 bufferOut.append(" font-style: oblique;\r\n");
624 bufferOut.append(" }\r\n");
625 bufferOut.append(" ." + numericLiteralStyle + "\r\n");
626 bufferOut.append(" {\r\n");
627 bufferOut.append(" color: #333300;\r\n");
628 bufferOut.append(" background-color: transparent;\r\n");
629 bufferOut.append(" }\r\n");
630 bufferOut.append(" ." + primitiveLiteralStyle + "\r\n");
631 bufferOut.append(" {\r\n");
632 bufferOut.append(" color: #006600;\r\n");
633 bufferOut.append(" background-color: transparent;\r\n");
634 bufferOut.append(" }\r\n");
637 bufferOut.append(" ." + iconStyle + "\r\n");
638 bufferOut.append(" {\r\n");
639 bufferOut.append(" border-style: none;\r\n");
640 bufferOut.append(" }\r\n");
644 bufferOut.append(" #title\r\n");
645 bufferOut.append(" {\r\n");
646 bufferOut.append(" text-align: center;\r\n");
647 bufferOut.append(" font-size: xx-large;\r\n");
648 bufferOut.append(" }\r\n");
652 bufferOut.append(" #legendTitle\r\n");
653 bufferOut.append(" {\r\n");
654 bufferOut.append(" text-align: center;\r\n");
655 bufferOut.append(" font-size: x-large;\r\n");
656 bufferOut.append(" }\r\n");
657 bufferOut.append(" #legend\r\n");
658 bufferOut.append(" {\r\n");
659 bufferOut.append(" font-family: monospace;\r\n");
660 bufferOut.append(" font-size: large;\r\n");
661 bufferOut.append(" }\r\n");
665 bufferOut.append(" #footer\r\n");
666 bufferOut.append(" {\r\n");
667 bufferOut.append(" font-size: xx-small;\r\n");
668 bufferOut.append(" }\r\n");
670 bufferOut.append(" /* ]]> */ -->\r\n");
671 bufferOut.append(" </style>\r\n");
674 if (hasExternalStyleSheet)
676 bufferOut.append(" <link rel=\"stylesheet\" " +
677 "type=\"text/css\" href=\"" +
678 externalStyleSheetName + "\" />\r\n");
680 bufferOut.append(" </head>\r\n");
681 bufferOut.append(" <body>\r\n");
685 bufferOut.append(" <div id=\"title\">\r\n");
686 bufferOut.append(" " + sourceFileName + "\r\n");
687 bufferOut.append(" </div>\r\n");
688 bufferOut.append(" <hr />\r\n");
692 bufferOut.append(" <div id=\"legendTitle\">\r\n");
693 bufferOut.append(" Legend\r\n");
694 bufferOut.append(" </div>\r\n");
695 bufferOut.append(" <div class=\"" + sourceCodeStyle + "\">\r\n");
696 bufferOut.append(" <div id=\"legend\">\r\n");
697 bufferOut.append(" <span class=\"" + keywordStyle + "\">");
698 bufferOut.append("keyword</span>\r\n");
699 bufferOut.append(" <span class=\"" + methodStyle + "\">");
700 bufferOut.append("method</span>\r\n");
701 bufferOut.append(" <span class=\"" + variableStyle + "\">variable" +
703 bufferOut.append(" <span class=\"" + singleLineCommentStyle + "\">" +
704 "singleLineComment</span>\r\n");
705 bufferOut.append(" <span class=\"" + traditionalCommentStyle + "\">" +
706 "traditionalComment</span>\r\n");
707 bufferOut.append(" <span class=\"" + javadocCommentStyle + "\">" +
708 "javadocComment</span>\r\n");
709 bufferOut.append(" <span class=\"" + javadocTagStyle + "\">javadocTag" +
711 bufferOut.append(" <span class=\"" + importNameStyle + "\">" +
712 "importName</span>\r\n");
713 bufferOut.append(" <span class=\"" + packageNameStyle + "\">" +
714 "packageName</span>\r\n");
715 bufferOut.append(" <span class=\"" + primitiveTypeStyle + "\">" +
716 "primitiveType</span>\r\n");
717 bufferOut.append(" <span class=\"" + nonPrimitiveTypeStyle + "\">" +
718 "nonPrimitiveType</span>\r\n");
719 bufferOut.append(" <span class=\"" + constructorStyle + "\">" +
720 "constructor</span>\r\n");
721 bufferOut.append(" <span class=\"" + constantStyle + "\">" +
722 "constant</span>\r\n");
723 bufferOut.append(" <span class=\"" + doubleQuoteStyle + "\">" +
724 "doubleQuote</span>\r\n");
725 bufferOut.append(" <span class=\"" + singleQuoteStyle + "\">" +
726 "singleQuote</span>\r\n");
727 bufferOut.append(" <span class=\"" + numericLiteralStyle + "\">" +
728 "numericLiteral</span>\r\n");
729 bufferOut.append(" <span class=\"" + primitiveLiteralStyle + "\">" +
730 "primitiveLiteral</span>\r\n");
731 bufferOut.append(" </div>\r\n");
732 bufferOut.append(" </div>\r\n");
733 bufferOut.append(" <hr />\r\n");
735 bufferOut.append(" <div class=\"" + sourceCodeStyle + "\">\r\n");
736 if (hasLineModulusCodeBlocks)
738 bufferOut.append("<pre class=\"modulusBlockPREStyle\">\r\n");
742 bufferOut.append("<pre>\r\n");
744 // process the input Java code Stringbuffer
745 // subtract 2 from the bufferIn.length() to get EOF marker
746 while (presentIndex++ < (bufferIn.length() - 2))
748 for (int i = 0; i < extraIndentation; i++)
750 bufferOut.append(" ");
752 if ((hasLineNumbers || hasLineModulusCodeBlocks) && isNewLine)
754 // add line numbers if desired
755 // line numbers are 1 - 9999 then rotate line numbers
756 codeLineNumber = (++codeLineNumber)%10000;
757 if ((lineModulus > 0) && hasLineModulusCodeBlocks &&
758 (codeLineNumber%lineModulus == 1))
762 if ((State.TRADITIONAL_COMMENT == presentState) ||
763 (State.JAVADOC == presentState))
765 bufferOut.insert((bufferOut.length() -
769 bufferOut.append("</pre>\r\n");
770 bufferOut.append(" <div class=");
771 bufferOut.append("\"modulusBlockStyle\">");
772 bufferOut.append("\r\n<pre class=\"");
773 bufferOut.append("modulusBlockPREStyle\">\r\n");
774 if (State.TRADITIONAL_COMMENT == presentState)
776 bufferOut.append("<span class=" +
777 "\"" + traditionalCommentStyle + "\">");
779 if (State.JAVADOC == presentState)
781 bufferOut.append("<span class=" +
782 "\"" + javadocCommentStyle + "\">");
785 isNewBlock = !isNewBlock;
787 // make straight columns of line numbers
788 if (codeLineNumber < 1000)
790 bufferOut.append(" ");
792 if (codeLineNumber < 100)
794 bufferOut.append(" ");
796 if (codeLineNumber < 10)
798 bufferOut.append(" ");
800 bufferOut.append("<a name=\"line.");
801 bufferOut.append(codeLineNumber);
802 bufferOut.append("\">");
806 if ((lineModulus > 0) && (codeLineNumber%lineModulus == 0))
808 bufferOut.append("<span class=" +
809 "\"" + modulusLineNumberStyle + "\">");
810 bufferOut.append(codeLineNumber);
811 bufferOut.append(": </span>");
812 if (hasLineModulusDrawnLines)
814 // compute spaceLength so a line can be drawn
815 while ((presentIndex != (bufferIn.length() - 1)) &&
816 ((Character.isSpaceChar(
817 bufferIn.charAt(presentIndex))) ||
818 (bufferIn.charAt(presentIndex) == '\t')))
820 // for each tab, insert tabSize spaces
821 if (bufferIn.charAt(presentIndex) == '\t')
823 for (int i = 0; i < tabSize; i++)
825 bufferIn.insert(presentIndex + 1, " ");
830 if (' ' == bufferIn.charAt(presentIndex))
832 // read a space so place a space
833 bufferOut.append(" ");
834 spaceLength += (" ").length();
838 // a white space character was read
839 bufferOut.append(bufferIn.charAt(
845 // check if line is empty
846 // (no printable characters on line)
847 if ((presentIndex == (bufferIn.length() - 1)) ||
848 (Character.isWhitespace(bufferIn.charAt(
856 bufferOut.insert((bufferOut.length() -
857 spaceLength), "<span class=" +
858 "\"modulusLineStyle\">");
859 bufferOut.insert((bufferOut.length() -
860 (" ").length()), "</span>");
867 // line numbers are in lineNumberColor
868 bufferOut.append("<span class=\"" + lineNumberStyle + "\">");
869 bufferOut.append(codeLineNumber);
870 bufferOut.append(":</span> ");
875 bufferOut.append("</a>");
878 presentChar = bufferIn.charAt(presentIndex);
879 if ((Character.isJavaIdentifierPart(presentChar)) ||
880 ((State.IMPORT_NAME == presentState) && (presentChar == '*')))
882 // this is an identifier
883 bufferOut.append(presentChar);
885 continue; // keep adding characters until identifier is done
887 if (identifierLength > 0)
890 qualifiedIdentifierLength =
891 qualifiedIdentifierLength + identifierLength;
892 if (bufferIn.charAt(presentIndex) == '.')
894 // qualified identifier
895 bufferOut.append(presentChar);
896 qualifiedIdentifierLength++;
897 identifierLength = 0;
898 continue; // keep adding characters to qualified identifier
901 bufferOut.substring(bufferOut.length() -
903 if ((State.PARAM_VARIABLE == presentState))
905 // any identifier after a param in a javadoc is assumed to
907 bufferOut.insert(bufferOut.length() -
908 qualifiedIdentifierLength,
909 "<span class=\"" + variableStyle + "\">");
910 bufferOut.append("</span>");
911 presentState = State.JAVADOC;
913 else if (State.JAVADOC == presentState)
916 if ((javadocTagCollection.contains(identifier)) &&
917 (bufferIn.charAt(presentIndex -
918 (identifierLength + 1)) == '@'))
920 // identifier is a javadocTag
921 bufferOut.insert(bufferOut.length() - identifierLength,
922 "<span class=\"" + javadocTagStyle + "\">");
923 bufferOut.append("</span>");
924 if (("param").equals(identifier))
926 // any identifier after a param is assumed to
927 // be a variable, get into a state to do this
928 presentState = State.PARAM_VARIABLE;
932 else if (State.IMPORT_NAME == presentState)
935 bufferOut.insert(bufferOut.length() -
936 qualifiedIdentifierLength,
937 "<span class=\"" + importNameStyle + "\">");
938 bufferOut.append("</span>");
939 presentState = State.TEXT;
941 else if (State.PACKAGE_NAME == presentState)
943 // package identifier
944 bufferOut.insert(bufferOut.length() -
945 qualifiedIdentifierLength,
946 "<span class=\"" + packageNameStyle + "\">");
947 bufferOut.append("</span>");
948 presentState = State.TEXT;
950 else if (State.TEXT == presentState)
952 if (keywordCollection.contains(identifier))
954 // identifier is a keyword
955 bufferOut.insert(bufferOut.length() -
956 qualifiedIdentifierLength,
957 "<span class=\"" + keywordStyle + "\">");
958 bufferOut.append("</span>");
959 if (("import").equals(identifier))
961 // anything after an import in text mode must be
962 // an import name, so enter state to process this
963 presentState = State.IMPORT_NAME;
965 else if (("package").equals(identifier))
967 // anything after an package in text mode must be
968 // an package name, so enter state to process this
969 presentState = State.PACKAGE_NAME;
972 else if (primitiveTypeCollection.contains(identifier))
974 // identifier is a primitive type
975 bufferOut.insert(bufferOut.length() -
976 qualifiedIdentifierLength,
977 "<span class=\"" + primitiveTypeStyle + "\">");
978 bufferOut.append("</span>");
980 else if ((identifier.equals(identifier.toUpperCase())) &&
981 (!(Character.isDigit(identifier.charAt(0)))))
983 // identifier is a constant
984 bufferOut.insert(bufferOut.length() -
985 qualifiedIdentifierLength,
986 "<span class=\"" + constantStyle + "\">");
987 bufferOut.append("</span>");
989 else if (Character.isUpperCase(identifier.charAt(0)))
991 // identifier is a constructor or non-primitive type
993 saveIndex = presentIndex;
994 while (Character.isWhitespace(
995 bufferIn.charAt(saveIndex++)))
999 if (bufferIn.charAt(--saveIndex) == '(')
1000 { // identifier is a constructor
1001 bufferOut.insert(bufferOut.length() -
1002 qualifiedIdentifierLength,
1004 "\"" + constructorStyle + "\">");
1005 bufferOut.append("</span>");
1009 // identifier is a non-primitive type
1010 bufferOut.insert(bufferOut.length() -
1011 qualifiedIdentifierLength,
1013 "\"" + nonPrimitiveTypeStyle + "\">");
1014 bufferOut.append("</span>");
1017 else if (!(Character.isDigit(identifier.charAt(0)) ||
1018 primitiveLiteralCollection.contains(identifier)))
1020 // identifier is a method or a variable
1022 saveIndex = presentIndex;
1023 while (Character.isWhitespace(
1024 bufferIn.charAt(saveIndex++)))
1029 // identifier is a method
1030 if (bufferIn.charAt(saveIndex) == '(')
1032 bufferOut.insert(bufferOut.length() -
1033 qualifiedIdentifierLength,
1034 "<span class=\"" + methodStyle + "\">");
1035 bufferOut.append("</span>");
1037 else if (bufferIn.charAt(saveIndex) == ',')
1039 // comma seperated variables
1040 bufferOut.insert(bufferOut.length() -
1041 qualifiedIdentifierLength,
1042 "<span class=\"" + variableStyle + "\">");
1043 bufferOut.append("</span>");
1048 // take care of cases such as array[index].variable
1049 if (bufferIn.charAt(presentIndex -
1050 (qualifiedIdentifierLength
1053 qualifiedIdentifierLength++;
1055 bufferOut.insert(bufferOut.length() -
1056 qualifiedIdentifierLength,
1057 "<span class=\"" + variableStyle + "\">");
1058 bufferOut.append("</span>");
1063 if (primitiveLiteralCollection.contains(identifier))
1065 // primitiveLiteral (boolean or null)
1066 bufferOut.insert(bufferOut.length() -
1067 identifierLength, "<span class=" +
1068 "\"" + primitiveLiteralStyle + "\">");
1069 bufferOut.append("</span>");
1071 // a numeric literal
1074 if (((presentIndex -
1075 (qualifiedIdentifierLength + 1)) > 0) &&
1076 (bufferIn.charAt(presentIndex -
1077 (qualifiedIdentifierLength + 1)) == '.'))
1079 qualifiedIdentifierLength++;
1081 bufferOut.insert(bufferOut.length() -
1082 qualifiedIdentifierLength,
1084 "\"" + numericLiteralStyle + "\">");
1085 bufferOut.append("</span>");
1089 qualifiedIdentifierLength = 0;
1090 identifierLength = 0;
1092 // process characters NOT in identifiers
1093 switch (presentChar)
1095 case '&': //ampersand
1096 bufferOut.append("&"); // HTMLify character
1098 case '<': // less than sign
1099 bufferOut.append("<"); // HTMLify character
1101 case '>': // greater than sign
1102 bufferOut.append(">"); // HTMLify character
1104 case '\"': // double quote
1105 bufferOut.append("""); // HTMLify character
1106 if (State.TEXT == presentState)
1108 presentState = State.DOUBLE_QUOTE;
1109 bufferOut.insert(bufferOut.length()-(""").length(),
1110 "<span class=\"" + doubleQuoteStyle + "\">");
1112 else if (State.DOUBLE_QUOTE == presentState)
1114 presentState = State.TEXT;
1115 bufferOut.append("</span>");
1118 case '\'': // single quote
1119 bufferOut.append("\'");
1120 if (State.TEXT == presentState)
1122 presentState = State.SINGLE_QUOTE;
1123 bufferOut.insert(bufferOut.length() - ("\'").length(),
1124 "<span class=\"" + singleQuoteStyle + "\">");
1126 else if (State.SINGLE_QUOTE == presentState)
1128 presentState = State.TEXT;
1129 bufferOut.append("</span>");
1132 case '\\': // backslash
1133 bufferOut.append("\\");
1134 if ((State.DOUBLE_QUOTE == presentState) ||
1135 (State.SINGLE_QUOTE == presentState))
1137 // treat as a character escape sequence
1138 bufferOut.append(bufferIn.charAt(++presentIndex));
1142 // replace tabs with tabsize number of spaces
1143 for (int i = 0; i < tabSize; i++)
1145 bufferOut.append(' ');
1149 bufferOut.append("*");
1150 if ((State.TEXT == presentState) &&
1151 (bufferIn.charAt(presentIndex - 1) == '/'))
1153 if (((bufferIn.length() - 1) > presentIndex) &&
1154 (bufferIn.charAt(presentIndex + 1) == '*'))
1156 presentState = State.JAVADOC;
1157 bufferOut.insert(bufferOut.length() -
1158 ("/*").length(), "<span class=" +
1159 "\"" + javadocCommentStyle + "\">");
1163 presentState = State.TRADITIONAL_COMMENT;
1164 bufferOut.insert(bufferOut.length() -
1165 ("/*").length(), "<span class=" +
1166 "\"" + traditionalCommentStyle + "\">");
1170 case '/': // foward slash
1171 bufferOut.append("/");
1172 if (((State.TRADITIONAL_COMMENT == presentState) ||
1173 (State.JAVADOC == presentState)) &&
1174 (bufferIn.charAt(presentIndex - 1) == '*'))
1176 bufferOut.append("</span>");
1177 presentState = State.TEXT;
1179 if ((State.TEXT == presentState) &&
1180 (presentIndex > 0) &&
1181 (bufferIn.charAt(presentIndex - 1) == '/'))
1183 bufferOut.insert(bufferOut.length() - ("//").length(),
1185 "\"" + singleLineCommentStyle + "\">");
1186 presentState = State.LINE_COMMENT;
1189 case '\r': // carriage return
1191 case '\n': // line feed
1192 // all HTML lines end in \r\n
1193 if ((bufferIn.charAt(presentIndex) == '\r') &&
1194 ((bufferIn.length() - 1) > presentIndex) &&
1195 (bufferIn.charAt(presentIndex + 1) == '\n'))
1199 // end single line comments
1200 if (State.LINE_COMMENT == presentState)
1202 bufferOut.append("</span>");
1203 presentState = State.TEXT;
1206 if ((lineModulus > 0) && hasLineModulusCodeBlocks &&
1207 ((codeLineNumber%lineModulus == 0) && !isNewBlock))
1209 // end multi-line spanning states
1210 if ((State.TRADITIONAL_COMMENT == presentState) ||
1211 (State.JAVADOC == presentState))
1213 bufferOut.append("</span>");
1215 bufferOut.append("\r\n");
1216 bufferOut.append("</pre>\r\n");
1217 bufferOut.append(" </div>\r\n");
1218 bufferOut.append("<pre class=\"");
1219 bufferOut.append("modulusBlockPREStyle\">\r\n");
1220 // restart multi-line spanning states
1221 if (State.TRADITIONAL_COMMENT == presentState)
1223 bufferOut.append("<span class=" +
1224 "\"" + traditionalCommentStyle + "\">");
1226 if (State.JAVADOC == presentState)
1228 bufferOut.append("<span class=" +
1229 "\"" + javadocCommentStyle + "\">");
1234 // div automatically starts new line
1235 bufferOut.append("\r\n");
1239 case 0: // nul character
1240 if ((State.LINE_COMMENT == presentState) &&
1241 (presentIndex == (bufferIn.length() - 1)))
1243 bufferOut.append("</span>");
1246 default: // everything else
1247 bufferOut.append(presentChar);
1249 qualifiedIdentifierLength = 0;
1251 if (presentState == State.LINE_COMMENT) {
1252 bufferOut.append("</span>\r\n");
1255 bufferOut.append("</pre>\r\n");
1256 // end block early if no more source code
1257 if ((lineModulus > 0) && hasLineModulusCodeBlocks && !isNewBlock &&
1258 (codeLineNumber%lineModulus != 0))
1260 bufferOut.append(" </div>\r\n");
1262 bufferOut.append(" </div>\r\n"); // end div of sourceCodeStyle
1263 // if code snippet then don't add ending tags of xhtml page
1266 // if footer mode then add a footer
1269 bufferOut.append(" <hr />\r\n");
1270 bufferOut.append(" <div id=\"footer\">\r\n");
1275 bufferOut.append(" <script type=\"text/javaScript\"");
1276 bufferOut.append(">\r\n");
1277 bufferOut.append(" <!-- // <![CDATA[\r\n");
1278 bufferOut.append(" document.write(\"Document last");
1279 bufferOut.append(" modified on \"");
1280 bufferOut.append(" + document.lastModified + ");
1281 bufferOut.append("\"<br />\");\r\n");
1282 bufferOut.append(" // ]]> -->\r\n");
1283 bufferOut.append(" </script>\r\n");
1285 bufferOut.append(" <a href=\"");
1286 bufferOut.append("http://validator.w3.org/check/referer");
1287 bufferOut.append("\">\r\n");
1288 bufferOut.append(" <img class=\"" + iconStyle + "\" src=\"");
1289 bufferOut.append("http://www.w3.org/Icons/");
1292 bufferOut.append("valid-xhtml11\"\r\n");
1293 bufferOut.append(" alt=\"Valid XHTML 1.1!\"");
1297 bufferOut.append("valid-xhtml10\"\r\n");
1298 bufferOut.append(" alt=\"Valid XHTML 1.0!\"");
1300 bufferOut.append(" height=\"31\" ");
1301 bufferOut.append("width=\"88\" />\r\n");
1302 bufferOut.append(" </a>\r\n");
1303 bufferOut.append("  \r\n");
1304 bufferOut.append(" <a href=\"");
1305 bufferOut.append("http://jigsaw.w3.org");
1306 bufferOut.append("/css-validator/check/referer");
1307 bufferOut.append("\">\r\n");
1308 bufferOut.append(" <img class=\"" + iconStyle + "\" src=\"");
1309 bufferOut.append("http://jigsaw.w3.org/");
1310 bufferOut.append("css-validator/images/vcss");
1311 bufferOut.append("\"\r\n");
1312 bufferOut.append(" alt=\"Valid CSS!\"");
1313 bufferOut.append(" height=\"31\" width=\"88\" />\r\n");
1314 bufferOut.append(" </a>\r\n");
1318 bufferOut.append(" This is a valid\r\n");
1319 bufferOut.append(" <a href=\"http://");
1320 bufferOut.append("validator.w3.org/check/referer");
1323 bufferOut.append("\">XHTML 1.1</a>\r\n");
1327 bufferOut.append("\">XHTML 1.0</a>\r\n");
1329 bufferOut.append(" with\r\n");
1330 bufferOut.append(" <a href=\"http://");
1331 bufferOut.append("jigsaw.w3.org");
1332 bufferOut.append("/css-validator/check/referer");
1333 bufferOut.append("\">CSS</a>\r\n");
1334 bufferOut.append(" document \r\n");
1337 bufferOut.append(" <script type=\"text/javaScript\"");
1338 bufferOut.append(">\r\n");
1339 bufferOut.append(" <!-- // <![CDATA[\r\n");
1340 bufferOut.append(" document.write(\"last modified");
1341 bufferOut.append(" on \" + document.lastModified);");
1342 bufferOut.append("\r\n");
1343 bufferOut.append(" // ]]> -->\r\n");
1344 bufferOut.append(" </script>\r\n");
1347 bufferOut.append(" </div>\r\n");
1349 bufferOut.append(" </body>\r\n");
1350 bufferOut.append("</html>\r\n");
1352 return bufferOut.toString();