View Javadoc

1   /*
2    * $Id: PrettyPrintWriter.java 651946 2008-04-27 13:41:38Z apetrelli $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.struts2.interceptor.debugging;
23  
24  import java.io.PrintWriter;
25  import java.io.Writer;
26  import java.util.Stack;
27  
28  public class PrettyPrintWriter {
29  
30      private final PrintWriter writer;
31      private final Stack<String> elementStack = new Stack<String>();
32      private final char[] lineIndenter;
33  
34      private boolean tagInProgress;
35      private int depth;
36      private boolean readyForNewLine;
37      private boolean tagIsEmpty;
38      private String newLine;
39      private boolean escape = true;
40  
41      private static final char[] NULL = "&#x0;".toCharArray();
42      private static final char[] AMP = "&amp;".toCharArray();
43      private static final char[] LT = "&lt;".toCharArray();
44      private static final char[] GT = "&gt;".toCharArray();
45      private static final char[] SLASH_R = "&#x0D;".toCharArray();
46      private static final char[] QUOT = "&quot;".toCharArray();
47      private static final char[] APOS = "&apos;".toCharArray();
48      private static final char[] CLOSE = "</".toCharArray();
49  
50      public PrettyPrintWriter(Writer writer, char[] lineIndenter, String newLine) {
51          this.writer = new PrintWriter(writer);
52          this.lineIndenter = lineIndenter;
53          this.newLine = newLine;
54      }
55  
56      public PrettyPrintWriter(Writer writer, char[] lineIndenter) {
57          this(writer, lineIndenter, "\n");
58      }
59  
60      public PrettyPrintWriter(Writer writer, String lineIndenter, String newLine) {
61          this(writer, lineIndenter.toCharArray(), newLine);
62      }
63  
64      public PrettyPrintWriter(Writer writer, String lineIndenter) {
65          this(writer, lineIndenter.toCharArray());
66      }
67  
68      public PrettyPrintWriter(Writer writer) {
69          this(writer, new char[]{' ', ' '});
70      }
71  
72      public void startNode(String name) {
73          tagIsEmpty = false;
74          finishTag();
75          writer.write('<');
76          writer.write(name);
77          elementStack.push(name);
78          tagInProgress = true;
79          depth++;
80          readyForNewLine = true;
81          tagIsEmpty = true;
82      }
83  
84      public void setValue(String text) {
85          readyForNewLine = false;
86          tagIsEmpty = false;
87          finishTag();
88  
89          writeText(writer, text);
90      }
91  
92      public void addAttribute(String key, String value) {
93          writer.write(' ');
94          writer.write(key);
95          writer.write('=');
96          writer.write('\"');
97          writeAttributeValue(writer, value);
98          writer.write('\"');
99      }
100 
101     protected void writeAttributeValue(PrintWriter writer, String text) {
102         writeText(text);
103     }
104 
105     protected void writeText(PrintWriter writer, String text) {
106         writeText(text);
107     }
108 
109     private void writeText(String text) {
110         int length = text.length();
111         for (int i = 0; i < length; i++) {
112             char c = text.charAt(i);
113             switch (c) {
114                 case '\0':
115                     this.writer.write(NULL);
116                     break;
117                 case '&':
118                     this.writer.write(AMP);
119                     break;
120                 case '<':
121                     this.writer.write(LT);
122                     break;
123                 case '>':
124                     this.writer.write(GT);
125                     break;
126                 case '"':
127                     this.writer.write(QUOT);
128                     break;
129                 case '\'':
130                     //for some reason IE just doesn't like this when we use it from ObjectToHtmlWriter
131                     //it works on FF and Opera
132                     if (escape)
133                         this.writer.write(APOS);
134                     else
135                         this.writer.write(c);
136                     break;
137                 case '\r':
138                     this.writer.write(SLASH_R);
139                     break;
140                 default:
141                     this.writer.write(c);
142             }
143         }
144     }
145 
146     public void endNode() {
147         depth--;
148         if (tagIsEmpty) {
149             writer.write('/');
150             readyForNewLine = false;
151             finishTag();
152             elementStack.pop();
153         } else {
154             finishTag();
155             writer.write(CLOSE);
156             writer.write((String)elementStack.pop());
157             writer.write('>');
158         }
159         readyForNewLine = true;
160         if (depth == 0 ) {
161             writer.flush();
162         }
163     }
164 
165     private void finishTag() {
166         if (tagInProgress) {
167             writer.write('>');
168         }
169         tagInProgress = false;
170         if (readyForNewLine) {
171             endOfLine();
172         }
173         readyForNewLine = false;
174         tagIsEmpty = false;
175     }
176 
177     protected void endOfLine() {
178         writer.write(newLine);
179         for (int i = 0; i < depth; i++) {
180             writer.write(lineIndenter);
181         }
182     }
183 
184     public void flush() {
185         writer.flush();
186     }
187 
188     public void close() {
189         writer.close();
190     }
191 
192     public boolean isEscape() {
193         return escape;
194     }
195 
196     public void setEscape(boolean escape) {
197         this.escape = escape;
198     }
199 }