1 package org.apache.maven.jcoveragereport;
2
3 /**
4 * CodeViewer.java
5 *
6 * Bill Lynch & Matt Tucker
7 * CoolServlets.com, October 1999
8 *
9 * Please visit CoolServlets.com for high quality, open source Java servlets.
10 *
11 * Copyright (C) 1999 CoolServlets.com
12 *
13 * Any errors or suggested improvements to this class can be reported
14 * as instructed on Coolservlets.com. We hope you enjoy
15 * this program... your comments will encourage further development!
16 *
17 * This software is distributed under the terms of The BSD License.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are met:
21 * * Redistributions of source code must retain the above copyright notice,
22 * this list of conditions and the following disclaimer.
23 * * Redistributions in binary form must reproduce the above copyright notice,
24 * this list of conditions and the following disclaimer in the documentation
25 * and/or other materials provided with the distribution.
26 * Neither name of CoolServlets.com nor the names of its contributors may be
27 * used to endorse or promote products derived from this software without
28 * specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY COOLSERVLETS.COM AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 * DISCLAIMED. IN NO EVENT SHALL COOLSERVLETS.COM OR CONTRIBUTORS BE LIABLE FOR
34 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
36 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 import java.util.HashMap;
43
44 public class JavaToHtml
45 {
46 private static HashMap reservedWords = new HashMap();
47 private static boolean inMultiLineComment = false;
48 private static String commentStart = "<span class=\"comment\">";
49 private static String commentEnd = "</span>";
50 private static String stringStart = "<span class=\"string\">";
51 private static String stringEnd = "</span>";
52 private static String reservedWordStart = "<span class=\"keyword\">";
53 private static String reservedWordEnd = "</span>";
54
55 static
56 {
57 loadHash();
58 }
59
60 /**
61 * Passes off each line to the first filter.
62 * @param line The line of Java code to be highlighted.
63 * @return Highlighted line.
64 */
65 public static String syntaxHighlight( String line )
66 {
67 return htmlFilter(line);
68 }
69
70
71
72
73 private static String htmlFilter(String line)
74 {
75 if (line == null || line.equals(""))
76 {
77 return "";
78 }
79
80
81 line = replace(line, "&", "&");
82
83
84
85 line = replace(line, "\\\\", "\\" );
86
87
88 line = replace(line, "" + (char) 92 + (char) 34, "\"");
89
90
91
92 line = replace(line, "<", "<");
93
94
95 line = replace(line, ">", ">");
96
97 return multiLineCommentFilter(line);
98 }
99
100
101
102
103
104 private static String multiLineCommentFilter(String line)
105 {
106 if (line == null || line.equals(""))
107 {
108 return "";
109 }
110 StringBuffer buf = new StringBuffer();
111 int index;
112
113 if (inMultiLineComment && (index = line.indexOf("*/")) > -1 && !isInsideString(line, index))
114 {
115 inMultiLineComment = false;
116 buf.append(commentStart);
117 buf.append(line.substring(0, index));
118 buf.append("*/").append(commentEnd);
119 if (line.length() > index + 2)
120 {
121 buf.append(inlineCommentFilter(line.substring(index + 2)));
122 }
123 return buf.toString();
124 }
125
126
127 else if (inMultiLineComment)
128 {
129 buf.append(commentStart);
130 buf.append(line);
131 buf.append(commentEnd);
132 return buf.toString();
133 }
134
135
136 else if ((index = line.indexOf("/*")) > -1 && !isInsideString(line, index))
137 {
138 inMultiLineComment = true;
139
140
141
142
143 buf.append(inlineCommentFilter(line.substring(0, index)));
144 buf.append(commentStart).append("/*");
145 buf.append(multiLineCommentFilter(line.substring(index + 2)));
146 buf.append(commentEnd);
147 return buf.toString();
148 }
149
150
151 else
152 {
153 return inlineCommentFilter(line);
154 }
155 }
156
157
158
159
160 private static String inlineCommentFilter(String line)
161 {
162 if (line == null || line.equals(""))
163 {
164 return "";
165 }
166 StringBuffer buf = new StringBuffer();
167 int index;
168 if ((index = line.indexOf("//")) > -1 && !isInsideString(line, index))
169 {
170 buf.append(stringFilter(line.substring(0, index)));
171 buf.append(commentStart);
172 buf.append(line.substring(index));
173 buf.append(commentEnd);
174 }
175 else
176 {
177 buf.append(stringFilter(line));
178 }
179 return buf.toString();
180 }
181
182
183
184
185 private static String stringFilter(String line)
186 {
187 if (line == null || line.equals(""))
188 {
189 return "";
190 }
191 StringBuffer buf = new StringBuffer();
192 if (line.indexOf("\"") <= -1)
193 {
194 return keywordFilter(line);
195 }
196 int start = 0;
197 int startStringIndex = -1;
198 int endStringIndex = -1;
199 int tempIndex;
200
201 while ((tempIndex = line.indexOf("\"")) > -1)
202 {
203
204 if (startStringIndex == -1)
205 {
206 startStringIndex = 0;
207 buf.append(stringFilter(line.substring(start, tempIndex)));
208 buf.append(stringStart).append("\"");
209 line = line.substring(tempIndex + 1);
210 }
211
212 else
213 {
214 startStringIndex = -1;
215 endStringIndex = tempIndex;
216 buf.append(line.substring(0, endStringIndex + 1));
217 buf.append(stringEnd);
218 line = line.substring(endStringIndex + 1);
219 }
220 }
221
222 buf.append(keywordFilter(line));
223
224 return buf.toString();
225 }
226
227
228
229
230 private static String keywordFilter( String line )
231 {
232 if (line == null || line.equals(""))
233 {
234 return "";
235 }
236 StringBuffer buf = new StringBuffer();
237 HashMap usedReservedWords = new HashMap();
238
239 int i = 0, startAt = 0;
240 char ch;
241 StringBuffer temp = new StringBuffer();
242 while (i < line.length())
243 {
244 temp.setLength(0);
245 ch = line.charAt(i);
246 startAt = i;
247
248
249 while (i < line.length() && ((ch >= 65 && ch <= 90 )
250 || (ch >= 97 && ch <= 122)))
251 {
252 temp.append(ch);
253 i++;
254 if (i < line.length())
255 {
256 ch = line.charAt(i);
257 }
258 }
259 String tempString = temp.toString();
260 if (reservedWords.containsKey(tempString) && !usedReservedWords.containsKey(tempString))
261 {
262 usedReservedWords.put(tempString, tempString);
263 line = replace(line, tempString, (reservedWordStart + tempString + reservedWordEnd), startAt);
264 i += (reservedWordStart.length() + reservedWordEnd.length());
265 }
266 else
267 {
268 i++;
269 }
270 }
271 buf.append(line);
272 return buf.toString();
273 }
274
275
276
277
278
279 private static String replace( String line, String oldString, String newString )
280 {
281 return replace(line, oldString, newString, 0);
282 }
283
284
285
286
287
288 private static String replace( String line, String oldString, String newString, int startAt )
289 {
290 int i = startAt;
291 while ((i = line.indexOf(oldString, i)) >= 0)
292 {
293 line = (new StringBuffer().append(line.substring(0, i))
294 .append(newString)
295 .append(line.substring(i + oldString.length()))).toString();
296 i += newString.length();
297 }
298 return line;
299 }
300
301
302
303
304
305 private static boolean isInsideString(String line, int position)
306 {
307 if (line.indexOf("\"") < 0)
308 {
309 return false;
310 }
311 int index;
312 String left = line.substring(0, position);
313 String right = line.substring(position);
314 int leftCount = 0;
315 int rightCount = 0;
316 while ((index = left.indexOf("\"")) > -1)
317 {
318 leftCount++;
319 left = left.substring(index + 1);
320 }
321 while ((index = right.indexOf("\"")) > -1)
322 {
323 rightCount++;
324 right = right.substring(index + 1);
325 }
326 if (rightCount % 2 != 0 && leftCount % 2 != 0)
327 {
328 return true;
329 }
330 else
331 {
332 return false;
333 }
334 }
335
336
337
338
339 private static void loadHash()
340 {
341 reservedWords.put( "abstract", "abstract" );
342 reservedWords.put( "do", "do" );
343 reservedWords.put( "inner", "inner" );
344 reservedWords.put( "public", "public" );
345 reservedWords.put( "var", "var" );
346 reservedWords.put( "boolean", "boolean" );
347 reservedWords.put( "continue", "continue" );
348 reservedWords.put( "int", "int" );
349 reservedWords.put( "return", "return" );
350 reservedWords.put( "void", "void" );
351 reservedWords.put( "break", "break" );
352 reservedWords.put( "else", "else" );
353 reservedWords.put( "interface", "interface" );
354 reservedWords.put( "short", "short" );
355 reservedWords.put( "volatile", "volatile" );
356 reservedWords.put( "byvalue", "byvalue" );
357 reservedWords.put( "extends", "extends" );
358 reservedWords.put( "long", "long" );
359 reservedWords.put( "static", "static" );
360 reservedWords.put( "while", "while" );
361 reservedWords.put( "case", "case" );
362 reservedWords.put( "final", "final" );
363 reservedWords.put( "native", "native" );
364 reservedWords.put( "super", "super" );
365 reservedWords.put( "transient", "transient" );
366 reservedWords.put( "cast", "cast" );
367 reservedWords.put( "float", "float" );
368 reservedWords.put( "new", "new" );
369 reservedWords.put( "rest", "rest" );
370 reservedWords.put( "catch", "catch" );
371 reservedWords.put( "for", "for" );
372 reservedWords.put( "null", "null" );
373 reservedWords.put( "synchronized", "synchronized" );
374 reservedWords.put( "char", "char" );
375 reservedWords.put( "finally", "finally" );
376 reservedWords.put( "operator", "operator" );
377 reservedWords.put( "this", "this" );
378 reservedWords.put( "class", "class" );
379 reservedWords.put( "generic", "generic" );
380 reservedWords.put( "outer", "outer" );
381 reservedWords.put( "switch", "switch" );
382 reservedWords.put( "const", "const" );
383 reservedWords.put( "goto", "goto" );
384 reservedWords.put( "package", "package" );
385 reservedWords.put( "throw", "throw" );
386 reservedWords.put( "double", "double" );
387 reservedWords.put( "if", "if" );
388 reservedWords.put( "private", "private" );
389 reservedWords.put( "true", "true" );
390 reservedWords.put( "default", "default" );
391 reservedWords.put( "import", "import" );
392 reservedWords.put( "protected", "protected" );
393 reservedWords.put( "try", "try" );
394 }
395 }