View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.internal.webapp;
21  
22  import org.apache.myfaces.tobago.internal.util.StringUtils;
23  import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
24  import org.apache.myfaces.tobago.renderkit.html.HtmlTypes;
25  import org.apache.myfaces.tobago.renderkit.html.MarkupLanguageAttributes;
26  import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  
30  import javax.faces.component.UIComponent;
31  import javax.faces.context.ResponseWriter;
32  import java.io.IOException;
33  import java.io.Writer;
34  import java.util.EmptyStackException;
35  import java.util.Stack;
36  
37  public class DebugResponseWriterWrapper extends TobagoResponseWriter {
38  
39    private Stack<Object> stack = new Stack<Object>();
40  
41    private static final Logger LOG = LoggerFactory.getLogger(DebugResponseWriterWrapper.class);
42  
43    private final TobagoResponseWriter responseWriter;
44  
45    public DebugResponseWriterWrapper(final TobagoResponseWriter responseWriter) {
46      this.responseWriter = responseWriter;
47    }
48  
49    @Override
50    public void write(final String string) throws IOException {
51      responseWriter.write(string);
52    }
53  
54    @Override
55    public void writeComment(final Object comment) throws IOException {
56      String commentStr = comment.toString();
57      if (commentStr.indexOf("--") > 0) {
58        LOG.error("Comment must not contain the sequence '--', comment = '" + comment + "'.",
59            new IllegalArgumentException());
60  
61        commentStr = StringUtils.replace(commentStr, "--", "++");
62      }
63      responseWriter.writeComment(commentStr);
64    }
65  
66    @Override
67    public ResponseWriter cloneWithWriter(final Writer writer) {
68      return new DebugResponseWriterWrapper((TobagoResponseWriter) responseWriter.cloneWithWriter(writer));
69    }
70  
71    @Override
72    @Deprecated
73    public void writeAttribute(final String name, final Object value, final String property) throws IOException {
74      responseWriter.writeAttribute(name, value, property);
75    }
76  
77    @Override
78    @Deprecated
79    public void writeText(final Object text, final String property) throws IOException {
80      responseWriter.writeText(text, property);
81    }
82  
83    @Override
84    public void flush() throws IOException {
85      responseWriter.flush();
86    }
87  
88    @Override
89    public void writeAttribute(final MarkupLanguageAttributes name, final String value, final boolean escape)
90        throws IOException {
91      responseWriter.writeAttribute(name, value, escape);
92    }
93  
94    @Override
95    public void writeAttribute(final MarkupLanguageAttributes name, final HtmlTypes types) throws IOException {
96      responseWriter.writeAttribute(name, types);
97    }
98  
99    @Override
100   public void writeURIAttribute(MarkupLanguageAttributes name, String string) throws IOException {
101     responseWriter.writeURIAttribute(name, string);
102   }
103 
104   @Override
105   public String getContentType() {
106     return responseWriter.getContentType();
107   }
108 
109   @Override
110   public String getCharacterEncoding() {
111     return responseWriter.getCharacterEncoding();
112   }
113 
114   @Override
115   public void startDocument() throws IOException {
116     responseWriter.startDocument();
117   }
118 
119   @Override
120   public void endDocument() throws IOException {
121     responseWriter.endDocument();
122   }
123 
124   /**
125    * @deprecated Should not be used, because it conflicts with CSP.
126    */
127   @Deprecated
128   @Override
129   public void writeJavascript(final String script) throws IOException {
130     responseWriter.writeJavascript(script);
131   }
132 
133   /**
134    * @deprecated Should not be used, because it conflicts with CSP.
135    */
136   @Deprecated
137   @Override
138   public void endJavascript() throws IOException {
139     responseWriter.endJavascript();
140   }
141 
142   /**
143    * @deprecated Should not be used, because it conflicts with CSP.
144    */
145   @Deprecated
146   @Override
147   public void startJavascript() throws IOException {
148     responseWriter.startJavascript();
149   }
150 
151   @Override
152   public void writeURIAttribute(final String name, final Object value, final String property) throws IOException {
153     responseWriter.writeURIAttribute(name, value, property);
154   }
155 
156   @Override
157   public void writeText(final char[] text, final int off, final int len) throws IOException {
158     responseWriter.writeText(text, off, len);
159   }
160 
161   @Override
162   public void write(final char[] chars, final int i, final int i1) throws IOException {
163     responseWriter.write(chars, i, i1);
164   }
165 
166   @Override
167   public void close() throws IOException {
168     responseWriter.close();
169   }
170 
171   @Override
172   public void startElement(final String name, final UIComponent currentComponent) throws IOException {
173     if (LOG.isDebugEnabled()) {
174       LOG.debug("start element: '" + name + "'");
175     }
176     stack.push(name);
177     responseWriter.startElement(name, currentComponent);
178   }
179 
180   @Override
181   public void startElement(final HtmlElements name) throws IOException {
182     if (LOG.isDebugEnabled()) {
183       LOG.debug("start element: '" + name + "'");
184     }
185     stack.push(name);
186     responseWriter.startElement(name);
187   }
188 
189   @Override
190   public void endElement(final String name) throws IOException {
191     if (LOG.isDebugEnabled()) {
192       LOG.debug("end element: '" + name + "'");
193     }
194     Object top;
195     try {
196       top = stack.pop();
197     } catch (final EmptyStackException e) {
198       LOG.error("Failed to close element \"" + name + "\"!", e);
199       top = "*** failure ***";
200     }
201 
202     if (!top.equals(name)) {
203       LOG.error("Element end with name='" + name + "' doesn't match with top element on the stack='" + top + "'.",
204           new IllegalArgumentException());
205     }
206     responseWriter.endElement(name);
207   }
208 
209   @Override
210   public void endElement(final HtmlElements name) throws IOException {
211     if (LOG.isDebugEnabled()) {
212       LOG.debug("end element: '" + name + "'");
213     }
214     Object top;
215     try {
216       top = stack.pop();
217     } catch (final EmptyStackException e) {
218       LOG.error("Failed to close element \"" + name + "\"!", e);
219       top = "*** failure ***";
220     }
221 
222     if (!top.equals(name)) {
223       LOG.error("Element end with name='" + name + "' doesn't match with top element on the stack='" + top + "'.",
224           new IllegalArgumentException());
225     }
226     responseWriter.endElement(name);
227   }
228 }