FileDocCategorySizeDatePackage
CodeViewer.javaAPI DocExample15633Wed Aug 08 15:13:52 BST 2001None

CodeViewer

public class CodeViewer extends Object
A class that syntax highlights Java code by turning it into html.
version
1.0 October 1999
author
Bill Lynch, Matt Tucker, CoolServlets.com

A CodeViewer object is created and then keeps state as lines are passed in. Each line passed in as java text, is returned as syntax highlighted html text.

Users of the class can set how the java code will be highlighted with setter methods.

Only valid java lines should be passed in since the object maintains state and may not handle illegal code gracefully.

The actual system is implemented as a series of filters that deal with specific portions of the java code. The filters are as follows:

htmlFilter
|__
multiLineCommentFilter
|___
inlineCommentFilter
|___
stringFilter
|__
keywordFilter

Fields Summary
private static HashMap
reservedWords
private boolean
inMultiLineComment
private String
backgroundColor
private String
commentStart
private String
commentEnd
private String
stringStart
private String
stringEnd
private String
reservedWordStart
private String
reservedWordEnd
Constructors Summary
public CodeViewer()


     
        loadHash();
    
    
Methods Summary
public java.lang.StringgetCommentEnd()

        return commentEnd;
    
public java.lang.StringgetCommentStart()

        return commentStart;
    
public java.lang.StringgetReservedWordEnd()

        return reservedWordEnd;
    
public java.lang.StringgetReservedWordStart()

        return reservedWordStart;
    
public java.lang.StringgetStringEnd()

        return stringEnd;
    
public java.lang.StringgetStringStart()

        return stringStart;
    
private java.lang.StringhtmlFilter(java.lang.String line)

        if( line == null || line.equals("") ) {
            return "";
        }

        // replace ampersands with HTML escape sequence for ampersand;
        line = replace(line, "&", "&");

        // replace the \\ with HTML escape sequences. fixes a problem when
        // backslashes preceed quotes.
        line = replace(line, "\\\\", "\\" );

        // replace \" sequences with HTML escape sequences;
        line = replace(line, "" + (char)92 + (char)34, "\"");

        // replace less-than signs which might be confused
        // by HTML as tag angle-brackets;
        line = replace(line, "<", "<");
        // replace greater-than signs which might be confused
        // by HTML as tag angle-brackets;
        line = replace(line, ">", ">");
        
        return multiLineCommentFilter(line);
    
private java.lang.StringinlineCommentFilter(java.lang.String line)

        if (line == null || line.equals("")) {
            return "";
        }
        StringBuffer buf = new StringBuffer();
        int index;
        if ((index = line.indexOf("//")) > -1 && !isInsideString(line,index)) {
            buf.append(stringFilter(line.substring(0,index)));
            buf.append(commentStart);
            buf.append(line.substring(index));
            buf.append(commentEnd);
        }
        else {
            buf.append(stringFilter(line));
        }
        return buf.toString();
    
private booleanisInsideString(java.lang.String line, int position)

        if (line.indexOf("\"") < 0) {
            return false;
        }
        int index;
        String left = line.substring(0,position);
        String right = line.substring(position);
        int leftCount = 0;
        int rightCount = 0;
        while ((index = left.indexOf("\"")) > -1) {
            leftCount ++;
            left = left.substring(index+1); 
        }
        while ((index = right.indexOf("\"")) > -1) {
            rightCount ++;
            right = right.substring(index+1); 
        }
        if (rightCount % 2 != 0 && leftCount % 2 != 0) {
            return true;
        }
        else {
            return false;
        }        
    
private java.lang.StringkeywordFilter(java.lang.String line)

        if( line == null || line.equals("") ) {
            return "";
        }
        StringBuffer buf = new StringBuffer();
        HashMap usedReservedWords = new HashMap(); // >= Java2 only (not thread-safe)
        //Hashtable usedReservedWords = new Hashtable(); // < Java2 (thread-safe)
        int i=0, startAt=0;
        char ch;
        StringBuffer temp = new StringBuffer();
        while( i < line.length() ) {
            temp.setLength(0);
            ch = line.charAt(i);
            startAt = i;
            // 65-90, uppercase letters
            // 97-122, lowercase letters
            while( i<line.length() && ( ( ch >= 65 && ch <= 90 )
                    || ( ch >= 97 && ch <= 122 ) ) ) {
                temp.append(ch);
                i++;
                if( i < line.length() ) {
                    ch = line.charAt(i);
                }
            }
            String tempString = temp.toString();
            if( reservedWords.containsKey(tempString) && !usedReservedWords.containsKey(tempString)) {
                usedReservedWords.put(tempString,tempString);
                line = replace( line, tempString, (reservedWordStart+tempString+reservedWordEnd) );
                i += (reservedWordStart.length() + reservedWordEnd.length());
            }
            else {
                i++;
            }            
        }
        buf.append(line);
        return buf.toString();
    
private static voidloadHash()

        reservedWords.put( "abstract", "abstract" );
        reservedWords.put( "do", "do" );
        reservedWords.put( "inner", "inner" );
        reservedWords.put( "public", "public" );
        reservedWords.put( "var", "var" );
        reservedWords.put( "boolean", "boolean" );
        reservedWords.put( "continue", "continue" );
        reservedWords.put( "int", "int" );
        reservedWords.put( "return", "return" );
        reservedWords.put( "void", "void" );
        reservedWords.put( "break", "break" );
        reservedWords.put( "else", "else" );
        reservedWords.put( "interface", "interface" );
        reservedWords.put( "short", "short" );
        reservedWords.put( "volatile", "volatile" );
        reservedWords.put( "byvalue", "byvalue" );
        reservedWords.put( "extends", "extends" );
        reservedWords.put( "long", "long" );
        reservedWords.put( "static", "static" );
        reservedWords.put( "while", "while" );
        reservedWords.put( "case", "case" );
        reservedWords.put( "final", "final" );
        reservedWords.put( "naive", "naive" );
        reservedWords.put( "super", "super" );
        reservedWords.put( "transient", "transient" );
        reservedWords.put( "cast", "cast" );
        reservedWords.put( "float", "float" );
        reservedWords.put( "new", "new" );
        reservedWords.put( "rest", "rest" );
        reservedWords.put( "catch", "catch" );
        reservedWords.put( "for", "for" );
        reservedWords.put( "null", "null" );
        reservedWords.put( "synchronized", "synchronized" );
        reservedWords.put( "char", "char" );
        reservedWords.put( "finally", "finally" );
        reservedWords.put( "operator", "operator" );
        reservedWords.put( "this", "this" );
        reservedWords.put( "class", "class" );
        reservedWords.put( "generic", "generic" );
        reservedWords.put( "outer", "outer" );
        reservedWords.put( "switch", "switch" );
        reservedWords.put( "const", "const" );
        reservedWords.put( "goto", "goto" );
        reservedWords.put( "package", "package" );
        reservedWords.put( "throw", "throw" );
        reservedWords.put( "double", "double" );
        reservedWords.put( "if", "if" );
        reservedWords.put( "private", "private" );
        reservedWords.put( "true", "true" );
        reservedWords.put( "default", "default" );
        reservedWords.put( "import", "import" );
        reservedWords.put( "protected", "protected" );
        reservedWords.put( "try", "try" );
    
private java.lang.StringmultiLineCommentFilter(java.lang.String line)

        if (line == null || line.equals("")) {
            return "";
        }
        StringBuffer buf = new StringBuffer();
        int index;
        //First, check for the end of a multi-line comment.
        if (inMultiLineComment && (index = line.indexOf("*/")) > -1 && !isInsideString(line,index)) {
            inMultiLineComment = false;               
            buf.append(line.substring(0,index));
            buf.append("*/").append(commentEnd);
            if (line.length() > index+2) {
                buf.append(inlineCommentFilter(line.substring(index+2)));
            }
            return buf.toString();
        }
        //If there was no end detected and we're currently in a multi-line
        //comment, we don't want to do anymore work, so return line.
        else if (inMultiLineComment) {
            return line;
        }
        //We're not currently in a comment, so check to see if the start
        //of a multi-line comment is in this line.
        else if ((index = line.indexOf("/*")) > -1 && !isInsideString(line,index)) {
            inMultiLineComment = true;
            //Return result of other filters + everything after the start
            //of the multiline comment. We need to pass the through the
            //to the multiLineComment filter again in case the comment ends
            //on the same line.
            buf.append(inlineCommentFilter(line.substring(0,index)));
            buf.append(commentStart).append("/*");
            buf.append(multiLineCommentFilter(line.substring(index+2)));
            return buf.toString();
        }
        //Otherwise, no useful multi-line comment information was found so
        //pass the line down to the next filter for processesing.
        else {
            return inlineCommentFilter(line);
        }
    
private java.lang.Stringreplace(java.lang.String line, java.lang.String oldString, java.lang.String newString)

        int i=0;
        while( ( i=line.indexOf( oldString, i ) ) >= 0 ) {
            line = (new StringBuffer().append(line.substring(0,i)).append(newString).append(line.substring(i+oldString.length()))).toString();
            i += newString.length();
        }
        return line;
    
public voidsetCommentEnd(java.lang.String commentEnd)

        this.commentEnd = commentEnd;
    
public voidsetCommentStart(java.lang.String commentStart)

        this.commentStart = commentStart;
    
public voidsetReservedWordEnd(java.lang.String reservedWordEnd)

        this.reservedWordEnd = reservedWordEnd;
    
public voidsetReservedWordStart(java.lang.String reservedWordStart)

        this.reservedWordStart = reservedWordStart;
    
public voidsetStringEnd(java.lang.String stringEnd)

        this.stringEnd = stringEnd;
    
public voidsetStringStart(java.lang.String stringStart)

        this.stringStart = stringStart;
    
private java.lang.StringstringFilter(java.lang.String line)

        if (line == null || line.equals("")) {
            return "";
        }
        StringBuffer buf = new StringBuffer();
        if (line.indexOf("\"") <= -1) {
            return keywordFilter(line);
        }
        int start = 0;
        int startStringIndex = -1;
        int endStringIndex = -1;
        int tempIndex;
        //Keep moving through String characters until we want to stop...
        while ((tempIndex = line.indexOf("\"")) > -1) {
            //We found the beginning of a string
            if (startStringIndex == -1) {
                startStringIndex = 0;
                buf.append( stringFilter(line.substring(start,tempIndex)) );
                buf.append(stringStart).append("\"");
                line = line.substring(tempIndex+1);
            }
            //Must be at the end
            else {
                startStringIndex = -1;
                endStringIndex = tempIndex;
                buf.append(line.substring(0,endStringIndex+1));
                buf.append(stringEnd);
                line = line.substring(endStringIndex+1);
            }
        }

        buf.append( keywordFilter(line) );

        return buf.toString();
    
public java.lang.StringsyntaxHighlight(java.lang.String line)
Passes off each line to the first filter.

param
line The line of Java code to be highlighted.

       return htmlFilter(line);