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.webapp;
21  
22  import org.apache.myfaces.tobago.config.TobagoConfig;
23  import org.apache.myfaces.tobago.renderkit.css.Classes;
24  import org.apache.myfaces.tobago.renderkit.css.Style;
25  import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
26  import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
27  import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
28  import org.apache.myfaces.tobago.renderkit.html.StyleClasses;
29  
30  import javax.faces.component.UIComponent;
31  import javax.faces.context.FacesContext;
32  import javax.faces.context.ResponseWriter;
33  import java.io.IOException;
34  import java.io.Writer;
35  
36  /**
37   * This provides an alternative ResponseWriter interfaces, which allows optimizations.
38   * E. g. some attributes needed to to be escaped.
39   * <p/>
40   */
41  public abstract class TobagoResponseWriter extends ResponseWriter {
42  
43    // same as in ResponseWriter
44  
45    @Override
46    public abstract void startElement(String name, UIComponent component) throws IOException;
47  
48    /**
49     * @deprecated Use {@link #startElement(String, UIComponent) startElement(name, null)} instead.
50     */
51    @Deprecated
52    public void startElement(String name) throws IOException {
53      startElement(name, null);
54    }
55  
56    @Override
57    public abstract void endElement(String name) throws IOException;
58      
59    public abstract void write(String string) throws IOException;
60  
61    @Override
62    public abstract void writeComment(Object comment) throws IOException;
63  
64    @Override
65    public abstract ResponseWriter cloneWithWriter(Writer writer);
66  
67    /**
68     * @deprecated Should not directly called via this interface. There is be a special method which might be better.
69     */
70    @Deprecated
71    public abstract void writeAttribute(String name, Object value, final String property) throws IOException;
72  
73    /**
74     * @deprecated Should not directly called via this interface. There is be a special method which might be better.
75     */
76    @Deprecated
77    public abstract void writeText(Object text, String property) throws IOException;
78  
79    @Override
80    public abstract void flush() throws IOException;
81  
82    // others (not from ResponseWriter)
83  
84    /**
85     * Writes a string attribute. The renderer may set escape=false to switch of escaping of the string,
86     * if it is not necessary.
87     */
88    public abstract void writeAttribute(String name, String string, boolean escape) throws IOException;
89  
90    /**
91     * Writes a boolean attribute. The value will not escaped.
92     */
93    public void writeAttribute(String name, boolean on) throws IOException {
94      if (on) {
95        writeAttribute(name, name, false);
96      }
97    }
98  
99    /**
100    * Writes a integer attribute. The value will not escaped.
101    */
102   public void writeAttribute(String name, int number) throws IOException {
103     writeAttribute(name, Integer.toString(number), false);
104   }
105 
106   /**
107    * Writes a propery as attribute. The value will be escaped.
108    */
109   public void writeAttributeFromComponent(String name, String property) throws IOException {
110     writeAttribute(name, null, property);
111   }
112 
113   /**
114    * Write the id attribute. The value will not escaped.
115    */
116   public void writeIdAttribute(String id) throws IOException {
117     writeAttribute(HtmlAttributes.ID, id, false);
118   }
119 
120   /**
121    * Write the name attribute. The value will not escaped.
122    */
123   public void writeNameAttribute(String name) throws IOException {
124     writeAttribute(HtmlAttributes.NAME, name, false);
125   }
126 
127   /**
128    * Write the class attribute. The value will not escaped.
129    * @deprecated since Tobago 1.5.0
130    */
131   @Deprecated
132   public void writeClassAttribute(String cssClass) throws IOException {
133     writeAttribute(HtmlAttributes.CLASS, cssClass, false);
134   }
135 
136   /**
137    * Write the class attribute. The value will not escaped.
138    * @deprecated since Tobago 1.5.0
139    */
140   @Deprecated
141   public void writeClassAttribute(StyleClasses styleClasses) throws IOException {
142     writeAttribute(HtmlAttributes.CLASS, styleClasses.toString(), false);
143   }
144 
145   /**
146    * Write the class attribute. The value will not escaped.
147    * <br/>
148    * <b>Note:</b> For backward compatibility the value of the Attribute
149    * <code>{@link org.apache.myfaces.tobago.component.Attributes#STYLE_CLASS}</code>
150    * will be inserted additionally. This function will be removed in later releases.
151    * @param classes The abstract representation of the css class string, normally created by the renderer.
152    */
153   public void writeClassAttribute(Classes classes) throws IOException {
154     String styleClasses = getStyleClasses();
155     String stringValue = classes.getStringValue();
156     if (styleClasses != null) {
157       stringValue += " " + styleClasses;
158     }
159     writeAttribute(HtmlAttributes.CLASS, stringValue, false);
160   }
161 
162   @Deprecated
163   public abstract String getStyleClasses();
164 
165   /**
166    * Write the class attribute. The value will not escaped.
167    * @deprecated since Tobago 1.5.0
168    */
169   @Deprecated
170   public abstract void writeClassAttribute() throws IOException;
171 
172 /*
173   private long self = 0;
174   private long gson = 0;
175 
176   private synchronized void time(long s, long g) {
177     self += s;
178     gson += g;
179   }
180 
181   private static final Logger LOG = LoggerFactory.getLogger(TobagoResponseWriter.class);
182 
183   public static final Gson GSON = new Gson();
184 
185 */
186   /**
187    * Write the style attribute. The value will not escaped.
188    */
189   public void writeStyleAttribute(Style style) throws IOException {
190     if (style != null) {
191       if (TobagoConfig.getInstance(FacesContext.getCurrentInstance()).getContentSecurityPolicy().size() > 0) {
192 
193 //        final long a = System.nanoTime();
194 
195         final String json = style.encodeJson();
196 
197 /*
198         final long b = System.nanoTime();
199 
200         final String json2 = GSON.toJson(style);
201 
202         final long c = System.nanoTime();
203 
204         time(b-a, c-b);
205 
206         LOG.error("self: " + json);
207         LOG.error("gson: " + json2);
208         LOG.error("self: " + self + " gson: " + gson);
209 
210 */
211         if (json.length() > 2) { // empty "{}" needs not to be written
212           writeAttribute(DataAttributes.STYLE, json, true);
213         }
214       } else {
215 
216         final String value = style.encode();
217         if (value.length() > 0) {
218           writeAttribute(HtmlAttributes.STYLE, value, style.needsToBeEscaped());
219         }
220       }
221     }
222   }
223 
224   /**
225    * Write the style attribute. The value will not escaped.
226    * @deprecated since 1.5.0, use writeStyleAttribute(Style) instead.
227    */
228   @Deprecated
229   public void writeStyleAttribute(String style) throws IOException {
230     writeAttribute(HtmlAttributes.STYLE, style, false);
231   }
232 
233   public void writeJavascript(String script) throws IOException {
234     startJavascript();
235     write(script);
236     endJavascript();
237   }
238 
239   public void endJavascript() throws IOException {
240 //    write("\n// -->\n"); // todo: for XHMTL we may need
241     endElement(HtmlElements.SCRIPT);
242   }
243 
244   public void startJavascript() throws IOException {
245     startElement(HtmlElements.SCRIPT, null);
246     writeAttribute(HtmlAttributes.TYPE, "text/javascript", false);
247     flush(); // is needed in some cases, e. g. TOBAGO-1094
248 //    write("\n<!--\n");
249   }
250 
251   /**
252    * Write text content. The text will be escaped.
253    */
254   public void writeText(String text) throws IOException {
255     writeText(text, null);
256   }
257 
258   /**
259    * Writes a property as text. The text will be escaped.
260    */
261   public void writeTextFromComponent(String property) throws IOException {
262     writeText(null, property);
263   }
264 
265   public String getContentTypeWithCharSet() {
266     String contentType = getContentType();
267     if (contentType == null) {
268       contentType = "text/html";
269     }
270     String characterEncoding = getCharacterEncoding();
271     if (characterEncoding == null) {
272       characterEncoding = "UTF-8";
273     }
274 
275     StringBuilder builder = new StringBuilder(contentType);
276     builder.append(";charset=");
277     builder.append(characterEncoding);
278     return builder.toString();
279 
280   }
281 }