| 1 | |
|
| 2 | |
|
| 3 | |
|
| 4 | |
|
| 5 | |
|
| 6 | |
|
| 7 | |
|
| 8 | |
|
| 9 | |
|
| 10 | |
|
| 11 | |
|
| 12 | |
|
| 13 | |
|
| 14 | |
|
| 15 | |
|
| 16 | |
|
| 17 | |
|
| 18 | |
|
| 19 | |
|
| 20 | |
|
| 21 | |
|
| 22 | |
package net.sourceforge.cobertura.reporting.html; |
| 23 | |
|
| 24 | |
import java.util.Arrays; |
| 25 | |
import java.util.Collection; |
| 26 | |
import java.util.HashSet; |
| 27 | |
|
| 28 | 12 | public class JavaToHtml |
| 29 | |
{ |
| 30 | |
|
| 31 | |
|
| 32 | 0 | public abstract static class State |
| 33 | |
{ |
| 34 | |
public final static int COMMENT_JAVADOC = 0; |
| 35 | |
public final static int COMMENT_MULTI = 1; |
| 36 | |
public final static int COMMENT_SINGLE = 2; |
| 37 | |
public final static int DEFAULT = 3; |
| 38 | |
public final static int KEYWORD = 4; |
| 39 | |
public final static int IMPORT_NAME = 5; |
| 40 | |
public final static int PACKAGE_NAME = 6; |
| 41 | |
public final static int QUOTE_DOUBLE = 8; |
| 42 | |
public final static int QUOTE_SINGLE = 9; |
| 43 | |
} |
| 44 | |
|
| 45 | |
|
| 46 | |
|
| 47 | |
private static final Collection javaKeywords; |
| 48 | |
private static final Collection javaPrimitiveLiterals; |
| 49 | |
private static final Collection javaPrimitiveTypes; |
| 50 | |
|
| 51 | |
static |
| 52 | |
{ |
| 53 | |
|
| 54 | |
|
| 55 | |
|
| 56 | 5 | final String[] javaKeywordsArray = { "abstract", "assert", "break", |
| 57 | |
"case", "catch", "class", "const", "continue", "default", |
| 58 | |
"do", "else", "extends", "final", "finally", "for", "goto", |
| 59 | |
"if", "interface", "implements", "import", "instanceof", |
| 60 | |
"native", "new", "package", "private", "protected", "public", |
| 61 | |
"return", "static", "strictfp", "super", "switch", |
| 62 | |
"synchronized", "this", "throw", "throws", "transient", |
| 63 | |
"try", "volatile", "while" }; |
| 64 | 5 | final String javaPrimitiveTypesArray[] = { "boolean", "byte", "char", |
| 65 | |
"double", "float", "int", "long", "short", "void" }; |
| 66 | 5 | final String javaPrimitiveLiteralsArray[] = { "false", "null", "true" }; |
| 67 | |
|
| 68 | |
|
| 69 | 5 | javaKeywords = new HashSet(Arrays.asList(javaKeywordsArray)); |
| 70 | 5 | javaPrimitiveTypes = new HashSet(Arrays |
| 71 | |
.asList(javaPrimitiveTypesArray)); |
| 72 | 5 | javaPrimitiveLiterals = new HashSet(Arrays |
| 73 | |
.asList(javaPrimitiveLiteralsArray)); |
| 74 | 5 | } |
| 75 | |
|
| 76 | 12 | private int state = State.DEFAULT; |
| 77 | |
|
| 78 | |
private static String escapeEntity(final char character) |
| 79 | |
{ |
| 80 | 7967 | if (character == '&') |
| 81 | 4 | return "&"; |
| 82 | 7963 | else if (character == '<') |
| 83 | 2 | return "<"; |
| 84 | 7961 | else if (character == '>') |
| 85 | 3 | return ">"; |
| 86 | 7958 | else if (character == '\t') |
| 87 | 331 | return " "; |
| 88 | |
else |
| 89 | 7627 | return new Character(character).toString(); |
| 90 | |
} |
| 91 | |
|
| 92 | |
|
| 93 | |
|
| 94 | |
|
| 95 | |
|
| 96 | |
|
| 97 | |
|
| 98 | |
|
| 99 | |
public String process(final String text) |
| 100 | |
{ |
| 101 | 500 | if (text == null) |
| 102 | 0 | throw new IllegalArgumentException("\"text\" can not be null."); |
| 103 | |
|
| 104 | 500 | StringBuffer ret = new StringBuffer(); |
| 105 | |
|
| 106 | |
|
| 107 | |
|
| 108 | |
int begin, end, nextCR; |
| 109 | 500 | begin = 0; |
| 110 | 500 | end = text.indexOf('\n', begin); |
| 111 | 500 | nextCR = text.indexOf('\r', begin); |
| 112 | 500 | if ((nextCR != -1) && ((end == -1) || (nextCR < end))) |
| 113 | 0 | end = nextCR; |
| 114 | 500 | while (end != -1) |
| 115 | |
{ |
| 116 | 0 | ret.append(processLine(text.substring(begin, end)) + "<br/>"); |
| 117 | |
|
| 118 | 0 | if ((end + 1 < text.length()) |
| 119 | |
&& ((text.charAt(end + 1) == '\n') || (text |
| 120 | |
.charAt(end + 1) == '\r'))) |
| 121 | |
{ |
| 122 | 0 | ret.append(text.substring(end, end + 1)); |
| 123 | 0 | begin = end + 2; |
| 124 | 0 | } |
| 125 | |
else |
| 126 | |
{ |
| 127 | 0 | ret.append(text.charAt(end)); |
| 128 | 0 | begin = end + 1; |
| 129 | |
} |
| 130 | |
|
| 131 | 0 | end = text.indexOf('\n', begin); |
| 132 | 0 | nextCR = text.indexOf('\r', begin); |
| 133 | 0 | if ((nextCR != -1) && ((end == -1) || (nextCR < end))) |
| 134 | 0 | end = nextCR; |
| 135 | |
} |
| 136 | 500 | ret.append(processLine(text.substring(begin))); |
| 137 | |
|
| 138 | 500 | return ret.toString(); |
| 139 | |
} |
| 140 | |
|
| 141 | |
|
| 142 | |
|
| 143 | |
|
| 144 | |
|
| 145 | |
|
| 146 | |
|
| 147 | |
private String processLine(final String line) |
| 148 | |
{ |
| 149 | 500 | if (line == null) |
| 150 | 0 | throw new IllegalArgumentException("\"line\" can not be null."); |
| 151 | 500 | if ((line.indexOf('\n') != -1) || (line.indexOf('\r') != -1)) |
| 152 | 0 | throw new IllegalArgumentException( |
| 153 | |
"\"line\" can not contain newline or carriage return characters."); |
| 154 | |
|
| 155 | 500 | StringBuffer ret = new StringBuffer(); |
| 156 | 500 | int currentIndex = 0; |
| 157 | |
|
| 158 | 2937 | while (currentIndex != line.length()) |
| 159 | |
{ |
| 160 | 2437 | if (state == State.DEFAULT) |
| 161 | |
{ |
| 162 | 1719 | if ((currentIndex + 2 < line.length()) |
| 163 | |
&& line.substring(currentIndex, currentIndex + 3) |
| 164 | |
.equals("/**")) |
| 165 | |
{ |
| 166 | 9 | state = State.COMMENT_JAVADOC; |
| 167 | |
|
| 168 | 9 | } |
| 169 | 1710 | else if ((currentIndex + 1 < line.length()) |
| 170 | |
&& line.substring(currentIndex, currentIndex + 2) |
| 171 | |
.equals("/*")) |
| 172 | |
{ |
| 173 | 7 | state = State.COMMENT_MULTI; |
| 174 | |
|
| 175 | 7 | } |
| 176 | 1703 | else if ((currentIndex + 1 < line.length()) |
| 177 | |
&& (line.substring(currentIndex, currentIndex + 2) |
| 178 | |
.equals("//"))) |
| 179 | |
{ |
| 180 | 8 | state = State.COMMENT_SINGLE; |
| 181 | |
|
| 182 | 8 | } |
| 183 | 1695 | else if (Character.isJavaIdentifierStart(line |
| 184 | |
.charAt(currentIndex))) |
| 185 | |
{ |
| 186 | 478 | state = State.KEYWORD; |
| 187 | |
|
| 188 | 478 | } |
| 189 | 1217 | else if (line.charAt(currentIndex) == '\'') |
| 190 | |
{ |
| 191 | 3 | state = State.QUOTE_SINGLE; |
| 192 | |
|
| 193 | 3 | } |
| 194 | 1214 | else if (line.charAt(currentIndex) == '"') |
| 195 | |
{ |
| 196 | 20 | state = State.QUOTE_DOUBLE; |
| 197 | |
|
| 198 | 20 | } |
| 199 | |
else |
| 200 | |
{ |
| 201 | |
|
| 202 | 1194 | ret.append(escapeEntity(line.charAt(currentIndex++))); |
| 203 | |
} |
| 204 | 1194 | } |
| 205 | |
|
| 206 | 718 | else if ((state == State.COMMENT_MULTI) |
| 207 | |
|| (state == State.COMMENT_JAVADOC)) |
| 208 | |
{ |
| 209 | |
|
| 210 | |
|
| 211 | 188 | ret.append("<span class=\"comment\">"); |
| 212 | |
while ((currentIndex != line.length()) |
| 213 | 6474 | && !((currentIndex + 1 < line.length()) && (line |
| 214 | |
.substring(currentIndex, currentIndex + 2) |
| 215 | |
.equals("*/")))) |
| 216 | |
{ |
| 217 | 6286 | ret.append(escapeEntity(line.charAt(currentIndex++))); |
| 218 | 6286 | } |
| 219 | 188 | if (currentIndex == line.length()) |
| 220 | |
{ |
| 221 | 172 | ret.append("</span>"); |
| 222 | 172 | } |
| 223 | |
else |
| 224 | |
{ |
| 225 | 16 | ret.append("*/</span>"); |
| 226 | 16 | state = State.DEFAULT; |
| 227 | 16 | currentIndex += 2; |
| 228 | |
} |
| 229 | 16 | } |
| 230 | |
|
| 231 | 530 | else if (state == State.COMMENT_SINGLE) |
| 232 | |
{ |
| 233 | |
|
| 234 | |
|
| 235 | 8 | ret.append("<span class=\"comment\">"); |
| 236 | 395 | while (currentIndex != line.length()) |
| 237 | |
{ |
| 238 | 387 | ret.append(escapeEntity(line.charAt(currentIndex++))); |
| 239 | 387 | } |
| 240 | 8 | ret.append("</span>"); |
| 241 | 8 | state = State.DEFAULT; |
| 242 | |
|
| 243 | 8 | } |
| 244 | |
|
| 245 | 522 | else if (state == State.KEYWORD) |
| 246 | |
{ |
| 247 | 478 | StringBuffer tmp = new StringBuffer(); |
| 248 | |
do |
| 249 | |
{ |
| 250 | 2875 | tmp.append(line.charAt(currentIndex++)); |
| 251 | |
} while ((currentIndex != line.length()) |
| 252 | 2875 | && (Character.isJavaIdentifierPart(line |
| 253 | |
.charAt(currentIndex)))); |
| 254 | 478 | if (javaKeywords.contains(tmp.toString())) |
| 255 | 166 | ret.append("<span class=\"keyword\">" + tmp + "</span>"); |
| 256 | 312 | else if (javaPrimitiveLiterals.contains(tmp.toString())) |
| 257 | 13 | ret.append("<span class=\"keyword\">" + tmp + "</span>"); |
| 258 | 299 | else if (javaPrimitiveTypes.contains(tmp.toString())) |
| 259 | 45 | ret.append("<span class=\"keyword\">" + tmp + "</span>"); |
| 260 | |
else |
| 261 | 254 | ret.append(tmp); |
| 262 | 478 | if (tmp.toString().equals("import")) |
| 263 | 9 | state = State.IMPORT_NAME; |
| 264 | 469 | else if (tmp.toString().equals("package")) |
| 265 | 12 | state = State.PACKAGE_NAME; |
| 266 | |
else |
| 267 | 457 | state = State.DEFAULT; |
| 268 | 478 | } |
| 269 | |
|
| 270 | 44 | else if (state == State.IMPORT_NAME) |
| 271 | |
{ |
| 272 | 9 | ret.append(escapeEntity(line.charAt(currentIndex++))); |
| 273 | 9 | state = State.DEFAULT; |
| 274 | 9 | } |
| 275 | |
|
| 276 | 35 | else if (state == State.PACKAGE_NAME) |
| 277 | |
{ |
| 278 | 12 | ret.append(escapeEntity(line.charAt(currentIndex++))); |
| 279 | 12 | state = State.DEFAULT; |
| 280 | 12 | } |
| 281 | |
|
| 282 | 23 | else if (state == State.QUOTE_DOUBLE) |
| 283 | |
{ |
| 284 | |
|
| 285 | |
|
| 286 | 20 | ret.append("<span class=\"string\">"); |
| 287 | |
do |
| 288 | |
{ |
| 289 | 71 | ret.append(escapeEntity(line.charAt(currentIndex++))); |
| 290 | |
} while ((currentIndex != line.length()) |
| 291 | 71 | && (!(line.charAt(currentIndex) == '"') || ((line |
| 292 | |
.charAt(currentIndex - 1) == '\\') && (line |
| 293 | |
.charAt(currentIndex - 2) != '\\')))); |
| 294 | 20 | if (currentIndex == line.length()) |
| 295 | |
{ |
| 296 | 0 | ret.append("</span>"); |
| 297 | 0 | } |
| 298 | |
else |
| 299 | |
{ |
| 300 | 20 | ret.append("\"</span>"); |
| 301 | 20 | state = State.DEFAULT; |
| 302 | 20 | currentIndex++; |
| 303 | |
} |
| 304 | 20 | } |
| 305 | |
|
| 306 | 3 | else if (state == State.QUOTE_SINGLE) |
| 307 | |
{ |
| 308 | |
|
| 309 | |
|
| 310 | 3 | ret.append("<span class=\"string\">"); |
| 311 | |
do |
| 312 | |
{ |
| 313 | 8 | ret.append(escapeEntity(line.charAt(currentIndex++))); |
| 314 | |
} while ((currentIndex != line.length()) |
| 315 | 8 | && (!(line.charAt(currentIndex) == '\'') || ((line |
| 316 | |
.charAt(currentIndex - 1) == '\\') && (line |
| 317 | |
.charAt(currentIndex - 2) != '\\')))); |
| 318 | 3 | if (currentIndex == line.length()) |
| 319 | |
{ |
| 320 | 0 | ret.append("</span>"); |
| 321 | 0 | } |
| 322 | |
else |
| 323 | |
{ |
| 324 | 3 | ret.append("\'</span>"); |
| 325 | 3 | state = State.DEFAULT; |
| 326 | 3 | currentIndex++; |
| 327 | |
} |
| 328 | 3 | } |
| 329 | |
|
| 330 | |
else |
| 331 | |
{ |
| 332 | |
|
| 333 | 0 | ret.append(escapeEntity(line.charAt(currentIndex++))); |
| 334 | |
} |
| 335 | 0 | } |
| 336 | |
|
| 337 | 500 | return ret.toString(); |
| 338 | |
} |
| 339 | |
|
| 340 | |
|
| 341 | |
|
| 342 | |
|
| 343 | |
|
| 344 | |
|
| 345 | |
|
| 346 | |
public void reset() |
| 347 | |
{ |
| 348 | 0 | state = State.DEFAULT; |
| 349 | 0 | } |
| 350 | |
|
| 351 | |
} |