2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shale.test.mock;
19  
20  import java.io.IOException;
21  import java.io.Writer;
22  import javax.faces.component.UIComponent;
23  import javax.faces.context.ResponseWriter;
24  
25  /***
26   * <p>Mock implementation of <code>javax.faces.context.ResponseWriter</code>.</p>
27   */
28  public class MockResponseWriter extends ResponseWriter {
29  
30  
31      // ------------------------------------------------------------ Constructors
32  
33  
34      /***
35       * <p>Construct an instance wrapping the specified writer.</p>
36       *
37       * @param writer Writer we are wrapping
38       * @param contentType Content type to be created
39       * @param characterEncoding Character encoding of this response
40       */
41      public MockResponseWriter(Writer writer, String contentType, String characterEncoding) {
42          this.writer = writer;
43          this.contentType = contentType;
44          this.characterEncoding = characterEncoding;
45      }
46  
47  
48      // ------------------------------------------------------ Instance Variables
49  
50  
51      private String characterEncoding = null;
52      private String contentType = "text/html";
53      private boolean open = false; // Is an element currently open?
54      private Writer writer = null;
55  
56  
57      // ----------------------------------------------------- Mock Object Methods
58  
59  
60      /***
61       * <p>Return the <code>Writer</code> that we are wrapping.</p>
62       */
63      public Writer getWriter() {
64          return this.writer;
65      }
66  
67  
68      // -------------------------------------------------- ResponseWriter Methods
69  
70  
71      /*** {@inheritDoc} */
72      public ResponseWriter cloneWithWriter(Writer writer) {
73          return new MockResponseWriter(writer, contentType, characterEncoding);
74      }
75  
76  
77      /*** {@inheritDoc} */
78      public void endDocument() throws IOException {
79          finish();
80          writer.flush();
81      }
82  
83  
84      /*** {@inheritDoc} */
85      public void endElement(String name) throws IOException {
86          if (open) {
87              writer.write("/");
88              finish();
89          } else {
90              writer.write("</");
91              writer.write(name);
92              writer.write(">");
93          }
94      }
95  
96  
97      /*** {@inheritDoc} */
98      public String getCharacterEncoding() {
99          return this.characterEncoding;
100     }
101 
102 
103     /*** {@inheritDoc} */
104     public String getContentType() {
105         return this.contentType;
106     }
107 
108 
109     /*** {@inheritDoc} */
110     public void flush() throws IOException {
111         finish();
112     }
113 
114 
115     /*** {@inheritDoc} */
116     public void startDocument() throws IOException {
117         // Do nothing
118     }
119 
120 
121     /*** {@inheritDoc} */
122     public void startElement(String name, UIComponent component) throws IOException {
123         if (name == null) {
124             throw new NullPointerException();
125         }
126         finish();
127         writer.write('<');
128         writer.write(name);
129         open = true;
130     }
131 
132 
133     /*** {@inheritDoc} */
134     public void writeAttribute(String name, Object value, String property) throws IOException {
135         if ((name == null) || (value == null)) {
136             throw new NullPointerException();
137         }
138         if (!open) {
139             throw new IllegalStateException();
140         }
141         writer.write(" ");
142         writer.write(name);
143         writer.write("=\"");
144         if (value instanceof String) {
145             string((String) value);
146         } else {
147             string(value.toString());
148         }
149         writer.write("\"");
150     }
151 
152 
153     /*** {@inheritDoc} */
154     public void writeComment(Object comment) throws IOException {
155         if (comment == null) {
156             throw new NullPointerException();
157         }
158         finish();
159         writer.write("<!-- ");
160         if (comment instanceof String) {
161             writer.write((String) comment);
162         } else {
163             writer.write(comment.toString());
164         }
165         writer.write(" -->");
166     }
167 
168 
169     /*** {@inheritDoc} */
170     public void writeText(Object text, String property) throws IOException {
171         if (text == null) {
172             throw new NullPointerException();
173         }
174         finish();
175         if (text instanceof String) {
176             string((String) text);
177         } else {
178             string(text.toString());
179         }
180     }
181 
182 
183     /*** {@inheritDoc} */
184     public void writeText(char[] text, int off, int len) throws IOException {
185         if (text == null) {
186             throw new NullPointerException();
187         }
188         if ((off < 0) || (off > text.length) || (len < 0) || (len > text.length)) {
189             throw new IndexOutOfBoundsException();
190         }
191         finish();
192         string(text, off, len);
193     }
194 
195 
196     /*** {@inheritDoc} */
197     public void writeURIAttribute(String name, Object value, String property) throws IOException {
198         if ((name == null) || (value == null)) {
199             throw new NullPointerException();
200         }
201         if (!open) {
202             throw new IllegalStateException();
203         }
204         writer.write(" ");
205         writer.write(name);
206         writer.write("=\"");
207         if (value instanceof String) {
208             string((String) value);
209         } else {
210             string(value.toString());
211         }
212         writer.write("\"");
213     }
214 
215 
216     // ---------------------------------------------------------- Writer Methods
217 
218 
219     /*** {@inheritDoc} */
220     public void close() throws IOException {
221         finish();
222         writer.close();
223     }
224 
225 
226     /*** {@inheritDoc} */
227     public void write(char[] cbuf, int off, int len) throws IOException {
228         finish();
229         writer.write(cbuf, off, len);
230     }
231 
232 
233     // --------------------------------------------------------- Support Methods
234 
235 
236     /***
237      * <p>Write the specified character, filtering if necessary.</p>
238      *
239      * @param ch Character to be written
240      *
241      * @exception IOException if an input/output error occurs
242      */
243     private void character(char ch) throws IOException {
244 
245         if (ch <= 0xff) {
246             // In single byte characters, replace only the five
247             // characters for which well-known entities exist in XML
248             if (ch == 0x22) {
249                 writer.write("&quot;");
250             } else if (ch == 0x26) {
251                 writer.write("&amp;");
252             } else if (ch == 0x27) {
253                 writer.write("&apos;");
254             } else if (ch == 0x3C) {
255                 writer.write("&lt;");
256             } else if (ch == 0X3E) {
257                 writer.write("&gt;");
258             } else {
259                 writer.write(ch);
260             }
261         } else {
262             if (substitution()) {
263                 numeric(writer, ch);
264             } else {
265                 writer.write(ch);
266             }
267         }
268 
269     }
270 
271 
272     /***
273      * <p>Close any element that is currently open.</p>
274      *
275      * @exception IOException if an input/output error occurs
276      */
277     private void finish() throws IOException {
278 
279         if (open) {
280             writer.write(">");
281             open = false;
282         }
283 
284     }
285 
286 
287     /***
288      * <p>Write a numeric character reference for specified character
289      * to the specfied writer.</p>
290      *
291      * @param writer Writer we are writing to
292      * @param ch Character to be translated and appended
293      *
294      * @exception IOException if an input/output error occurs
295      */
296     private void numeric(Writer writer, char ch) throws IOException {
297 
298         writer.write("&#");
299         writer.write(String.valueOf(ch));
300         writer.write(";");
301 
302     }
303 
304 
305     /***
306      * <p>Write the specified characters (after performing suitable
307      * replacement of characters by corresponding entities).</p>
308      *
309      * @param text Character array containing text to be written
310      * @param off Starting offset (zero relative)
311      * @param len Number of characters to be written
312      *
313      * @exception IOException if an input/output error occurs
314      */
315     private void string(char[] text, int off, int len) throws IOException {
316 
317         // Process the specified characters
318         for (int i = off; i < (off + len); i++) {
319             character(text[i]);
320         }
321 
322     }
323 
324 
325     /***
326      * <p>Write the specified string (after performing suitable
327      * replacement of characters by corresponding entities).</p>
328      *
329      * @param s String to be filtered and written
330      *
331      * @exception IOException if an input/output error occurs
332      */
333     private void string(String s) throws IOException {
334 
335         for (int i = 0; i < s.length(); i++) {
336             character(s.charAt(i));
337         }
338 
339     }
340 
341 
342     /***
343      * <p>Return true if entity substitution should be performed on double
344      * byte character values.</p>
345      */
346     private boolean substitution() {
347 
348         return !("UTF-8".equals(characterEncoding) || "UTF-16".equals(characterEncoding));
349 
350     }
351 
352 
353 }