1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 package org.w3c.tidy.servlet.reports;
56
57 import java.io.IOException;
58 import java.io.InputStream;
59 import java.io.LineNumberReader;
60 import java.io.InputStreamReader;
61 import java.io.Writer;
62 import java.io.StringReader;
63 import java.util.Vector;
64 import java.util.Iterator;
65 import java.util.HashMap;
66
67 import javax.servlet.http.HttpSession;
68
69 import org.apache.commons.logging.Log;
70 import org.apache.commons.logging.LogFactory;
71
72 import org.w3c.tidy.TidyMessage;
73 import org.w3c.tidy.servlet.ResponseRecord;
74 import org.w3c.tidy.servlet.ResponseRecordRepository;
75 import org.w3c.tidy.servlet.properties.JTidyServletProperties;
76 import org.w3c.tidy.servlet.util.HTMLEncode;
77
78
79 /***
80 * Report code used by ReportTag and TidyServlet
81 * @author Vlad Skarzhevskyy <a href="mailto:skarzhevskyy@gmail.com">skarzhevskyy@gmail.com </a>
82 * @version $Revision: 1.10 $ ($Author: vlads $)
83 */
84 public class Report
85 {
86
87 /***
88 * Properties
89 */
90 private boolean completePage = true;
91
92 private boolean view;
93
94 private boolean printSource;
95
96 private boolean wrapSource = true;
97
98 private boolean printHtmlResult = false;
99
100 private int wrapLen = 0;
101
102 /***
103 * output report as xhtml
104 */
105 private boolean xhtml;
106
107 private static final String RESOURCE_JAVASCRIPT = "JTidyServletReport.js";
108
109 private static final String RESOURCE_STYLESHEET = "JTidyServletReport.css";
110
111 /***
112 * Logger.
113 */
114 private Log log = LogFactory.getLog(Report.class);
115
116 /***
117 * Internal variables for convenience
118 */
119 StringBuffer out;
120
121 ResponseRecordRepository responseRecordRepository;
122
123 public Report(ResponseRecordRepository responseRecordRepository)
124 {
125 this.out = new StringBuffer(1024);
126 this.responseRecordRepository = responseRecordRepository;
127 init();
128 }
129
130 public Report(HttpSession httpSession)
131 {
132 this.out = new StringBuffer(1024);
133 this.responseRecordRepository = JTidyServletProperties.getInstance().getRepositoryInstance(httpSession);
134 init();
135 }
136
137 private void init()
138 {
139 JTidyServletProperties properties = JTidyServletProperties.getInstance();
140 this.xhtml = properties.getBooleanProperty(JTidyServletProperties.PROPERTY_BOOLEAN_XHTML, true);
141 }
142
143 public void print(Writer writer, String key) throws IOException
144 {
145 format(key);
146 writer.write(this.out.toString());
147 }
148
149 void td(String str1, String str2)
150 {
151 td(str1);
152 td(str2);
153 }
154
155 void td(String str)
156 {
157 this.out.append("<td>").append(str).append("</td>\n");
158 }
159
160 void tr()
161 {
162 this.out.append("</tr><tr>\n");
163 }
164
165 void identSpace(int ln)
166 {
167 if (ln < 10)
168 {
169 this.out.append(" ");
170 }
171 else if (ln < 100)
172 {
173 this.out.append(" ");
174 }
175 else if (ln < 1000)
176 {
177 this.out.append(" ");
178 }
179 }
180
181 void format(String keyString) throws IOException
182 {
183
184 ResponseRecord record = null;
185
186 if (this.responseRecordRepository == null)
187 {
188 log.info("No ResponseRecordRepository");
189 }
190 else
191 {
192 Object key = this.responseRecordRepository.getResponseID(keyString);
193 record = this.responseRecordRepository.getRecord(key);
194 }
195
196 if (record == null)
197 {
198 this.out.append("No data for ").append(keyString);
199 return;
200 }
201
202 if (this.view)
203 {
204 formatView(record);
205 }
206 else
207 {
208 formatReport(record);
209 }
210 }
211
212 void formatView(ResponseRecord record)
213 {
214 if (printHtmlResult)
215 {
216 this.out.append(record.getHtmlOutput());
217 }
218 else
219 {
220 this.out.append(record.getHtmlInput());
221 }
222 }
223
224 void printScript()
225 {
226 appendResource(RESOURCE_JAVASCRIPT);
227 }
228
229 void printStylesheet()
230 {
231 this.out.append("<style type=\"text/css\">\n");
232 appendResource(RESOURCE_STYLESHEET);
233 this.out.append("</style>\n");
234 }
235
236 void appendResource(String resourceName)
237 {
238 InputStream in = this.getClass().getClassLoader().getResourceAsStream(resourceName);
239 if (in == null)
240 {
241 log.warn("resource not found:" + resourceName);
242 return;
243 }
244
245 LineNumberReader lnr = new LineNumberReader(new InputStreamReader(in));
246 String strSource;
247 try
248 {
249 while ((strSource = lnr.readLine()) != null)
250 {
251 this.out.append(strSource).append("\n");
252 }
253 lnr.close();
254 }
255 catch (IOException e)
256 {
257 log.error("Error Reading resource " + resourceName, e);
258 }
259 }
260
261 void formatReport(ResponseRecord record) throws IOException
262 {
263 if (completePage)
264 {
265 if (this.xhtml)
266 {
267 out.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"");
268 out.append(" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n");
269 }
270 else
271 {
272 out.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"");
273 out.append(" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
274 }
275 out.append("<html><head><title>JTidy Messages</title>");
276 printStylesheet();
277 out.append("</head><body>\n");
278 }
279
280 printScript();
281
282 out.append("<table id=\"JTidyMessagesTable\" summary=\"\"><tr>");
283 out.append("<td colspan=\"4\">JTidy Messages for request:" + record.getRequestID());
284 out.append(" processed in " + record.getParsTime() + " milliseconds</td>");
285 tr();
286 out.append("<td colspan=\"4\">Validation Errors " + record.getParseErrors() + "</td>\n");
287 tr();
288 out.append("<td colspan=\"4\">Validation Warnings " + record.getParseWarnings() + "</td>\n");
289
290 HashMap map = new HashMap();
291
292
293 Vector source = new Vector();
294 LineNumberReader lnr = new LineNumberReader(new StringReader(record.getHtmlInput()));
295 String strSource;
296 while ((strSource = lnr.readLine()) != null)
297 {
298
299 source.add(strSource);
300 }
301
302 for (Iterator i = record.getMessages().iterator(); i.hasNext();)
303 {
304 TidyMessage message = (TidyMessage) i.next();
305 tr();
306 Integer ln = new Integer(message.getLine());
307
308 StringBuffer lineStr = new StringBuffer(300);
309 lineStr.append("Line ");
310 if (printSource)
311 {
312 lineStr.append("<a href=\"#line").append(ln).append("\" ");
313 lineStr.append(" onclick=\"jTidyReportHighlight('").append(ln).append("')\" ");
314 lineStr.append(">").append(ln).append("</a>");
315 }
316 else
317 {
318 lineStr.append(ln);
319 }
320
321 if (map.get(ln) == null)
322 {
323
324 lineStr.append("<a name=\"errline").append(ln).append("\"></a>");
325 }
326 lineStr.append(", ");
327
328 td(lineStr.toString());
329
330 td("column " + message.getColumn());
331 td(message.getLevel().toString() + ":");
332
333 StringBuffer messageStr = new StringBuffer(300);
334
335 messageStr.append("<a title=\"");
336 messageStr.append(HTMLEncode.encode((String) source.get(message.getLine() - 1)));
337 messageStr.append("\">");
338
339 messageStr.append(HTMLEncode.encode(message.getMessage()));
340
341 messageStr.append("</a>");
342
343 td(messageStr.toString());
344
345 map.put(ln, message);
346 }
347
348 out.append("</tr>\n");
349 out.append("</table>\n");
350
351 if (printSource)
352 {
353 out.append("<div>");
354 if (this.xhtml)
355 {
356 out.append("<br/>");
357 }
358 else
359 {
360 out.append("<br>");
361 }
362 out.append("Below is the source used for this validation:");
363
364 out.append("<pre>");
365 out.append("<a name=\"JTidyOriginalSource\"></a>");
366
367 int ln = 0;
368 for (int lnIdx = 0; lnIdx < source.size(); lnIdx++)
369 {
370 ln = lnIdx + 1;
371 String str = (String) source.get(lnIdx);
372 TidyMessage message = (TidyMessage) map.get(new Integer(ln));
373
374 out.append("<span id=\"srcline").append(ln).append("\"");
375
376 if (message != null)
377 {
378
379
380 out.append("class = \"JTidyReportSrcLineError\" ");
381 }
382 out.append(">");
383
384 identSpace(ln);
385
386 out.append("<a name=\"line");
387 out.append(ln);
388 out.append("\"></a><strong>");
389
390 if (message == null)
391 {
392 out.append(ln);
393 }
394 else
395 {
396
397 out.append("<a href=\"#errline" + ln + "\">");
398 out.append(ln);
399 out.append("</a>");
400 }
401
402 out.append("</strong>");
403
404 if ((this.wrapSource) || (this.wrapLen != 0))
405 {
406 int useWrapLen = this.wrapLen;
407 if (useWrapLen == 0)
408 {
409 useWrapLen = 100;
410 }
411 str = wrap(str, useWrapLen);
412 }
413
414 if (message != null)
415 {
416
417 out.append("<a title=\"");
418 out.append(message.getLevel().toString() + " :");
419 out.append(HTMLEncode.encode(message.getMessage()));
420 out.append("\">");
421 }
422
423 if (str.length() > 0)
424 {
425 out.append("<code class=\"html\"> ");
426 out.append(HTMLEncode.encode(str));
427 out.append("</code>");
428 }
429
430 if (message != null)
431 {
432 out.append("</a>");
433 }
434 out.append("</span>");
435 out.append("\n");
436 }
437
438
439 out.append("<a name=\"line");
440 out.append((ln + 1));
441 out.append("\"></a>");
442 out.append("EOF");
443 out.append("</pre>");
444 out.append("</div>");
445 }
446
447 if (printHtmlResult)
448 {
449 out.append("<div>");
450 if (this.xhtml) {
451 out.append("<br/>");
452 } else {
453 out.append("<br>");
454 }
455 out.append("Below is the generated html code:");
456
457 LineNumberReader lnrr = new LineNumberReader(new StringReader(record.getHtmlOutput()));
458
459 out.append("<pre>");
460 out.append("<a name=\"JTidyHtmlResult\"></a>");
461
462 String str;
463 int ln = 0;
464 while ((str = lnrr.readLine()) != null)
465 {
466 ln = lnrr.getLineNumber();
467
468 identSpace(ln);
469 out.append("<a name=\"resultLine");
470 out.append(ln);
471 out.append("\"></a><strong>");
472 out.append(ln);
473 out.append("</strong>");
474
475 if ((this.wrapSource) || (this.wrapLen != 0))
476 {
477 int useWrapLen = this.wrapLen;
478 if (useWrapLen == 0)
479 {
480 useWrapLen = 100;
481 }
482 str = wrap(str, useWrapLen);
483 }
484
485
486 if (str.length() > 0)
487 {
488 out.append("<code> ");
489 out.append(HTMLEncode.encode(str));
490 out.append("</code>");
491 }
492
493 out.append("\n");
494 }
495 out.append("<a name=\"resultLine");
496 out.append((ln + 1));
497 out.append("\"></a>");
498 out.append("EOF");
499 out.append("</pre>");
500 out.append("</div>");
501 }
502
503 if (completePage)
504 {
505 out.append("</body></html>");
506 }
507 }
508
509 /***
510 * Simple line Wrapper by End of Tag.
511 * @param str
512 * @param wrapLen
513 * @return Wraped line
514 */
515 private String wrap(String str, int wrapLen)
516 {
517 final String identLine = " ";
518 int strLen = str.length();
519 StringBuffer buffer = new StringBuffer(strLen + strLen / wrapLen + 3);
520
521 char[] charAry = str.toCharArray();
522 int idx = 0;
523 int lineLen = 0;
524 boolean inString = false;
525 while (idx < charAry.length)
526 {
527 char c = charAry[idx];
528 idx++;
529 lineLen++;
530 buffer.append(c);
531 if ((lineLen >= wrapLen) && (c == '>'))
532 {
533 buffer.append('\n').append(identLine);
534 lineLen = 0;
535 }
536
537 if (c == '\"')
538 {
539 if (inString && (lineLen >= (wrapLen + 10)))
540 {
541 buffer.append('\n').append(identLine);
542 lineLen = 0;
543 }
544 inString = !inString;
545 }
546 }
547
548 return buffer.toString();
549 }
550
551 /***
552 * @param completePage The completePage to set.
553 */
554 public void setCompletePage(boolean completePage)
555 {
556 this.completePage = completePage;
557 }
558
559 /***
560 * @param view The view to set.
561 */
562 public void setView(boolean view)
563 {
564 this.view = view;
565 }
566
567 /***
568 * @param printSource The printSource to set.
569 */
570 public void setPrintSource(boolean printSource)
571 {
572 this.printSource = printSource;
573 }
574
575 /***
576 * @param wrapSource The wrapSource to set.
577 */
578 public void setWrapSource(boolean wrapSource)
579 {
580 this.wrapSource = wrapSource;
581 }
582
583 /***
584 * @param printHtmlResult The printHtmlResult to set.
585 */
586 public void setPrintHtmlResult(boolean printHtmlResult)
587 {
588 this.printHtmlResult = printHtmlResult;
589 }
590
591 /***
592 * @param wrapLen The wrapLen to set.
593 */
594 public void setWrapLen(int wrapLen)
595 {
596 this.wrapLen = wrapLen;
597 }
598 }