2
package org.crosswire.util;
10
* Bill Lynch & Matt Tucker
11
* CoolServlets.com, July 1999
13
* Any errors or suggested improvements to this servlet can be reported
14
* as instructed on Coolservlets.com. We hope you enjoy
15
* this program... your comments will encourage further development!
17
* Copyright (C) 1999 Bill Lynch & Matt Tucker
19
* This program is free software; you can redistribute it and/or modify
20
* it under the terms of the GNU General Public License as published by
21
* the Free Software Foundation; either version 2 of the License, or
22
* (at your option) any later version.
24
* This program is distributed in the hope that it will be useful,
25
* but WITHOUT ANY WARRANTY; without even the implied warranty of
26
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
* GNU General Public License for more details.
29
* You should have received a copy of the GNU General Public License
30
* along with this program; if not, write to the Free Software
31
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34
* Syntax highlights java by turning it into html.
36
* A codeviewer object is created and then keeps state as lines are passed
37
* in. Each line passed in as java test, is returned as syntax highlighted
40
* Users of the class can set how the java code will be highlighted with setter
43
* Only valid java lines should be passed in since the object maintains state
44
* and may not handle illegal code gracefully.
46
* The actual system is implemented as a series of filters that deal with
47
* specific portions of the java code. The filters are as follows:
51
* multiLineCommentFilter
59
public class CodeColorizer implements Serializable
62
* Set up a CodeColorizer
64
public CodeColorizer()
70
* Now different method of seeing if at end of input stream,
71
* closes inputs stream at end.
73
public String syntaxHighlight(String line)
75
return htmlFilter(line);
78
public void setCommentStart(String commentStart)
80
this.commentStart = commentStart;
83
public void setCommentEnd(String commentEnd)
85
this.commentEnd = commentEnd;
88
public void setStringStart(String stringStart)
90
this.stringStart = stringStart;
93
public void setStringEnd(String stringEnd)
95
this.stringEnd = stringEnd;
98
public void setReservedWordStart(String reservedWordStart)
100
this.reservedWordStart = reservedWordStart;
103
public void setReservedWordEnd(String reservedWordEnd)
105
this.reservedWordEnd = reservedWordEnd;
108
public String getCommentStart()
113
public String getCommentEnd()
118
public String getStringStart()
123
public String getStringEnd()
128
public String getReservedWordStart()
130
return reservedWordStart;
133
public String getReservedWordEnd()
135
return reservedWordEnd;
139
* Filter html tags into more benign text.
141
private String htmlFilter(String line)
143
StringBuffer buf = new StringBuffer();
144
if (line == null || line.equals(""))
147
line = replace(line,"&","&");
148
line = replace(line,"<","<");
149
line = replace(line,">",">");
150
line = replace(line, "\\\\", "//");
151
line = replace(line, "\\\"", "\\"");
152
line = replace(line, "'\"'", "'"'");
154
return multiLineCommentFilter(line);
158
* Filter out multiLine comments. State is kept with a private boolean
161
private String multiLineCommentFilter(String line)
163
if (line == null || line.equals(""))
166
StringBuffer buf = new StringBuffer();
169
// First, check for the end of a multi-line comment.
170
if (inMultiLineComment &&
171
(index = line.indexOf("*/")) > -1 &&
172
!isInsideString(line,index))
174
inMultiLineComment = false;
176
buf.append(line.substring(0,index));
177
buf.append("*/").append(commentEnd);
178
if (line.length() > index+2)
179
buf.append(inlineCommentFilter(line.substring(index+2)));
181
return buf.toString();
183
else if (inMultiLineComment)
185
// If there was no end detected and we're currently in a multi-line
186
// comment, we don't want to do anymore work, so return line.
190
else if ((index = line.indexOf("/*")) > -1 &&
191
!isInsideString(line,index))
193
// We're not currently in a comment, so check to see if the start
194
// of a multi-line comment is in this line.
195
inMultiLineComment = true;
197
// Return result of other filters + everything after the start
198
// of the multiline comment. We need to pass the through the
199
// to the multiLineComment filter again in case the comment ends
201
buf.append(inlineCommentFilter(line.substring(0,index)));
202
buf.append(commentStart).append("/*");
203
buf.append(multiLineCommentFilter(line.substring(index+2)));
205
return buf.toString();
209
// Otherwise, no useful multi-line comment information was found so
210
// pass the line down to the next filter for processesing.
212
return inlineCommentFilter(line);
217
* Filter inline comments from a line and formats them properly.
218
* One problem we'll have to solve here: comments contained in a string
219
* should be ignored... this is also true of the multiline comments. So,
220
* we could either ignore the problem, or implement a function called
221
* something like isInsideString(line, index) where index points to
222
* some point in the line that we need to check... started doing this
225
private String inlineCommentFilter(String line)
227
if (line == null || line.equals(""))
230
StringBuffer buf = new StringBuffer();
233
if ((index = line.indexOf("//")) > -1 &&
234
!isInsideString(line,index))
236
buf.append(stringFilter(line.substring(0,index)));
237
buf.append(commentStart);
238
buf.append(line.substring(index));
239
buf.append(commentEnd);
243
buf.append(stringFilter(line));
246
return buf.toString();
250
* Filters strings from a line of text and formats them properly.
252
private String stringFilter(String line)
254
if (line == null || line.equals(""))
257
if (line.indexOf("\"") <= -1)
258
return keywordFilter(line);
260
StringBuffer buf = new StringBuffer();
262
int startStringIndex = -1;
263
int endStringIndex = -1;
266
// Keep moving through String characters until we want to stop...
267
while ((tempIndex = line.indexOf("\"")) > -1)
269
// We found the beginning of a string
270
if (startStringIndex == -1)
272
startStringIndex = 0;
273
buf.append(stringFilter(line.substring(start,tempIndex)));
274
buf.append(stringStart).append("\"");
275
line = line.substring(tempIndex+1);
280
startStringIndex = -1;
281
endStringIndex = tempIndex;
282
buf.append(line.substring(0,endStringIndex+1));
283
buf.append(stringEnd);
284
line = line.substring(endStringIndex+1);
288
buf.append( keywordFilter(line));
290
return buf.toString();
294
* Filters keywords from a line of text and formats them properly.
296
private String keywordFilter(String line)
298
if (line == null || line.equals(""))
301
StringBuffer buf = new StringBuffer();
303
//HashMap usedReservedWords = new HashMap();
304
Hashtable usedReservedWords = new Hashtable();
309
StringBuffer temp = new StringBuffer();
311
while (i < line.length())
317
while (i<line.length() &&
318
((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122)))
323
if (i < line.length())
327
String tempString = temp.toString();
328
if (reservedWords.containsKey(tempString) && !usedReservedWords.containsKey(tempString))
330
usedReservedWords.put(tempString,tempString);
331
line = replace (line, tempString, (reservedWordStart+tempString+reservedWordEnd));
332
i += (reservedWordStart.length() + reservedWordEnd.length());
340
return buf.toString();
345
* I made it use a stringBuffer... hope it still works :)
347
private String replace(String line, String oldString, String newString)
351
while ((i = line.indexOf(oldString, i)) >= 0)
353
line = (new StringBuffer().append(line.substring(0,i)).append(newString).append(line.substring(i+oldString.length()))).toString();
354
i += newString.length();
361
* Checks to see if some position in a line is between String start and
362
* ending characters. Not yet used in code or fully working :)
364
private boolean isInsideString(String line, int position)
366
if (line.indexOf("\"") < 0)
370
String left = line.substring(0,position);
371
String right = line.substring(position);
375
while ((index = left.indexOf("\"")) > -1)
378
left = left.substring(index+1);
381
while ((index = right.indexOf("\"")) > -1)
384
right = right.substring(index+1);
387
if (rightCount % 2 != 0 && leftCount % 2 != 0)
393
private void loadHash()
395
reservedWords.put("abstract", "abstract");
396
reservedWords.put("do", "do");
397
reservedWords.put("inner", "inner");
398
reservedWords.put("public", "public");
399
reservedWords.put("var", "var");
400
reservedWords.put("boolean", "boolean");
401
reservedWords.put("continue", "continue");
402
reservedWords.put("int", "int");
403
reservedWords.put("return", "return");
404
reservedWords.put( "void", "void");
405
reservedWords.put("break", "break");
406
reservedWords.put("else", "else");
407
reservedWords.put("interface", "interface");
408
reservedWords.put("short", "short");
409
reservedWords.put("volatile", "volatile");
410
reservedWords.put("byvalue", "byvalue");
411
reservedWords.put("extends", "extends");
412
reservedWords.put("long", "long");
413
reservedWords.put("static", "static");
414
reservedWords.put("while", "while");
415
reservedWords.put("case", "case");
416
reservedWords.put("final", "final");
417
reservedWords.put("naive", "naive");
418
reservedWords.put("super", "super");
419
reservedWords.put("transient", "transient");
420
reservedWords.put("cast", "cast");
421
reservedWords.put("float", "float");
422
reservedWords.put("new", "new");
423
reservedWords.put("rest", "rest");
424
reservedWords.put("catch", "catch");
425
reservedWords.put("for", "for");
426
reservedWords.put("null", "null");
427
reservedWords.put("synchronized", "synchronized");
428
reservedWords.put("char", "char");
429
reservedWords.put("finally", "finally");
430
reservedWords.put("operator", "operator");
431
reservedWords.put("this", "this");
432
reservedWords.put("class", "class");
433
reservedWords.put("generic", "generic");
434
reservedWords.put("outer", "outer");
435
reservedWords.put("switch", "switch");
436
reservedWords.put("const", "const");
437
reservedWords.put("goto", "goto");
438
reservedWords.put("package", "package");
439
reservedWords.put("throw", "throw");
440
reservedWords.put("double", "double");
441
reservedWords.put("if", "if");
442
reservedWords.put("private", "private");
443
reservedWords.put("true", "true");
444
reservedWords.put("default", "default");
445
reservedWords.put("import", "import");
446
reservedWords.put("protected", "protected");
447
reservedWords.put("try", "try");
450
void writeObject(ObjectOutputStream oos) throws IOException
452
oos.defaultWriteObject();
455
void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException
457
ois.defaultReadObject();
460
private BufferedReader in;
461
private StringBuffer out;
462
//private HashMap reservedWords = new HashMap();
463
private Hashtable reservedWords = new Hashtable();
464
private boolean inMultiLineComment = false;
465
private String backgroundColor = "#ffffff";
466
private String commentStart = "<font color='#009900'>";
467
private String commentEnd = "</font>";
468
private String stringStart = "<font color='#0000aa'>";
469
private String stringEnd = "</font>";
470
private String reservedWordStart = "<b>";
471
private String reservedWordEnd = "</b>";