1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package net.sourceforge.servletspy.writer;
22
23 import java.io.BufferedReader;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.io.PrintWriter;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.Map;
31
32 import net.sourceforge.servletspy.INodeWriter;
33 import net.sourceforge.servletspy.Node;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37
38 /***
39 * @author arno schumacher
40 */
41 public final class HtmlNodeWriter implements INodeWriter {
42 private static class EscapeMap {
43 private static final long serialVersionUID = 3035978367106983288L;
44
45 private final Map impl = new HashMap();
46
47 EscapeMap() {
48 super();
49 impl.put(new Long(10), "<br />\n");
50 impl.put(new Long(13), "");
51 impl.put(new Long(34), """);
52 impl.put(new Long(38), "&");
53 impl.put(new Long(60), "<");
54 impl.put(new Long(62), ">");
55 }
56
57 public final String map(final char c) {
58 String s = (String) impl.get(new Long(c));
59 return s == null ? String.valueOf(c) : s;
60 }
61 };
62
63 private static final EscapeMap ESCAPE_MAP = new EscapeMap();
64
65 private static final Log LOGGER = LogFactory.getLog(HtmlNodeWriter.class);
66
67 private static void comment(final PrintWriter out, final int id,
68 final Node node, final boolean isBegin) {
69 out.println();
70 out.print("<!-- ");
71 out.print(isBegin ? " b e g i n : " : " e n d : ");
72 out.print(getPath(node));
73 out.print(" - ");
74 out.print(id);
75 out.println(" -->");
76 }
77
78 private static String getPath(final Node node) {
79 if (node == null) {
80 throw new NullPointerException();
81 } else {
82 return node.getParent() == null ? node.getName() : (getPath(node
83 .getParent())
84 + "/" + node.getName());
85 }
86 }
87
88 private static String quoteCharacters(final String stringToQuote) {
89 final StringBuffer stringBuffer = new StringBuffer(stringToQuote
90 .length() * 2);
91 final char[] stringToQuoteAsCharArray = new char[stringToQuote.length()];
92 stringToQuote.getChars(0, stringToQuote.length(),
93 stringToQuoteAsCharArray, 0);
94 for (int j = 0; j < stringToQuoteAsCharArray.length; j++) {
95 stringBuffer.append(ESCAPE_MAP.map(stringToQuoteAsCharArray[j]));
96 }
97 return stringBuffer.toString();
98 }
99
100 private final PrintWriter printWriter;
101
102 private final String resourceName = this.getClass().getName().replace('.',
103 '/')
104 + ".htmlstatic";
105
106 /***
107 * Constructor.
108 *
109 * @param pPrintWriter
110 * The writer.
111 */
112 public HtmlNodeWriter(final PrintWriter pPrintWriter) {
113 printWriter = pPrintWriter;
114 }
115
116 private String generateDebugHint(final Node node) {
117 String answer = "";
118 if (LOGGER.isDebugEnabled()) {
119 answer = quoteCharacters(" // "
120 + String.valueOf(node.getDebugHint()));
121 }
122 return answer;
123 }
124
125 private String generateHeaderString(final Node node, final String id) {
126 final StringBuffer sb = new StringBuffer();
127 sb.append("<div class=\"spyHeader\">");
128 if (node.hasChildNodes()) {
129 sb.append("<a href=\"javascript:changeVisualizationMode('");
130 sb.append(id);
131 sb.append("')\">");
132 }
133 sb.append(quoteCharacters(node.getName()));
134 if (node.hasChildNodes()) {
135 sb.append("</a>");
136 }
137 sb.append("<span class=\"spyHeaderValue\">");
138 sb.append(quoteCharacters(node.getValue()));
139 sb.append(generateDebugHint(node));
140 sb.append("</span>");
141 sb.append("</div>");
142 return sb.toString();
143 }
144
145 private void writeHtmlStatic(final PrintWriter writer) throws IOException {
146 LOGGER.debug("Writing static part...");
147 boolean succeeded = false;
148 try {
149 final InputStream ios = Thread.currentThread()
150 .getContextClassLoader().getResourceAsStream(resourceName);
151 if (ios == null) {
152 throw new IOException("Resource '" + resourceName
153 + "' could not be found.");
154 }
155 final BufferedReader in = new BufferedReader(new InputStreamReader(
156 ios));
157 String s = in.readLine();
158 while (s != null) {
159 writer.println(s);
160 s = in.readLine();
161 }
162 in.close();
163 succeeded = true;
164 } finally {
165 LOGGER.debug(succeeded ? "..succeeded." : "...failed.");
166 }
167 }
168
169
170
171
172
173
174
175 public void writeNode(final Node rootNode) throws IOException {
176 final long startRandom = System.currentTimeMillis() % 100000;
177 writeHtmlStatic(printWriter);
178 writeNode(printWriter, rootNode, 0, startRandom);
179 }
180
181 private int writeNode(final PrintWriter out, final Node node, int counter,
182 final long random) {
183 final int fixedCounter = ++counter;
184 final String id = fixedCounter + "R" + String.valueOf(random);
185 final String header = generateHeaderString(node, id);
186
187 comment(out, fixedCounter, node, true);
188
189 if (node.hasChildNodes()) {
190
191 out.print("<div class=\"spyBox\" style=\"display:");
192 out.print("block");
193 out.print("\" id=\"");
194 out.print(id);
195 out.print("C\">");
196 out.print(header);
197 out.println("</div>");
198 }
199
200
201 out.print("<div class=\"spyBox\" ");
202 if (node.hasChildNodes()) {
203 out.print("style=\"display:");
204 out.print("none");
205 out.print("\" id=\"");
206 out.print(id);
207 out.print("E\"");
208 }
209 out.print(">");
210
211 out.print(header);
212
213
214 counter += 1 - (node.getNumberOfChild() % 2);
215 for (Iterator enumNodeChilds = node.childNodes(); enumNodeChilds
216 .hasNext();) {
217 final Node nodeChild = (Node) enumNodeChilds.next();
218
219 counter++;
220
221 if (nodeChild.hasChildNodes()) {
222 out.print("<div class=\"spyKeyBox");
223 out.print(counter % 2);
224 out.print("\">\n ");
225 final int counterSave = counter;
226 counter = writeNode(out, nodeChild, ++counter, random);
227 if ((counterSave % 2) != (counter % 2)) {
228 counter++;
229 }
230 out.println("</div>");
231 } else {
232 out.print("<div class=\"spyKeyValue");
233 out.print(counter % 2);
234 out.print("\">\n ");
235 out.print(quoteCharacters(nodeChild.getName()));
236
237 if (nodeChild.getValue() != null
238 && nodeChild.getValue().toString().length() > 0) {
239 out.print("<span class=\"spyValue\">");
240 out.print(quoteCharacters(nodeChild.getValue().toString()));
241
242 out.print(generateDebugHint(nodeChild));
243 out.print("</span>");
244 if (nodeChild.hasReference()) {
245 out.print(" - ");
246 out.print("<span class=\"spyValueReference\">");
247 out.print(nodeChild.getReference().getName());
248 out.print("</span>");
249 }
250 }
251 out.print("</div>");
252 }
253 }
254
255 if (node.hasChildNodes()) {
256 out.print("</div>");
257 }
258
259 comment(out, fixedCounter, node, false);
260
261 return counter;
262 }
263 }