2009/05/20 - Apache Shale has been retired.
For more information, please explore the Attic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shale.remoting.faces;
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>Basic implementation of <code>javax.faces.context.ResponseWriter</code>
27 * for use when a content type other than <code>text/html</code> is desired
28 * (such as <code>text/xml</code>).</p>
29 */
30 public class BasicResponseWriter extends ResponseWriter {
31
32
33
34
35
36 /***
37 * <p>Create a new instance configured with the specified properties.</p>
38 *
39 * @param writer <code>Writer</code> to be wrapped
40 * @param contentType Content type of this response
41 * @param characterEncoding Character encoding of thie response
42 **/
43 public BasicResponseWriter(Writer writer, String contentType, String characterEncoding) {
44 this.writer = writer;
45 this.contentType = contentType;
46 this.characterEncoding = characterEncoding;
47 }
48
49
50
51
52
53 /***
54 * <p>The character encoding of the response we are creating.</p>
55 */
56 private String characterEncoding = null;
57
58
59 /***
60 * <p>The content type of the response we are creating.</p>
61 */
62 private String contentType = "text/html";
63
64
65 /***
66 * <p>Flag indicating that an element has been started.</p>
67 */
68 private boolean open = false;
69
70
71 /***
72 * <p>The <code>Writer</code> we are wrapping.</p>
73 */
74 private Writer writer = null;
75
76
77
78
79
80
81
82
83
84 /*** {@inheritDoc} */
85 public ResponseWriter cloneWithWriter(Writer writer) {
86 return new BasicResponseWriter(writer, contentType, characterEncoding);
87 }
88
89
90 /*** {@inheritDoc} */
91 public void endDocument() throws IOException {
92 finish();
93 writer.flush();
94 }
95
96
97 /*** {@inheritDoc} */
98 public void endElement(String name) throws IOException {
99 if (open) {
100 writer.write("/");
101 finish();
102 } else {
103 writer.write("</");
104 writer.write(name);
105 writer.write(">");
106 }
107 }
108
109
110 /*** {@inheritDoc} */
111 public String getCharacterEncoding() {
112 return this.characterEncoding;
113 }
114
115
116 /*** {@inheritDoc} */
117 public String getContentType() {
118 return this.contentType;
119 }
120
121
122 /*** {@inheritDoc} */
123 public void flush() throws IOException {
124 finish();
125 }
126
127
128 /*** {@inheritDoc} */
129 public void startDocument() throws IOException {
130
131 }
132
133
134 /*** {@inheritDoc} */
135 public void startElement(String name, UIComponent component) throws IOException {
136 if (name == null) {
137 throw new NullPointerException();
138 }
139 finish();
140 writer.write('<');
141 writer.write(name);
142 open = true;
143 }
144
145
146 /*** {@inheritDoc} */
147 public void writeAttribute(String name, Object value, String property) throws IOException {
148 if ((name == null) || (value == null)) {
149 throw new NullPointerException();
150 }
151 if (!open) {
152 throw new IllegalStateException();
153 }
154 writer.write(" ");
155 writer.write(name);
156 writer.write("=\"");
157 if (value instanceof String) {
158 string((String) value);
159 } else {
160 string(value.toString());
161 }
162 writer.write("\"");
163 }
164
165
166 /*** {@inheritDoc} */
167 public void writeComment(Object comment) throws IOException {
168 if (comment == null) {
169 throw new NullPointerException();
170 }
171 finish();
172 writer.write("<!-- ");
173 if (comment instanceof String) {
174 writer.write((String) comment);
175 } else {
176 writer.write(comment.toString());
177 }
178 writer.write(" -->");
179 }
180
181
182 /*** {@inheritDoc} */
183 public void writeText(Object text, String property) throws IOException {
184 if (text == null) {
185 throw new NullPointerException();
186 }
187 finish();
188 if (text instanceof String) {
189 string((String) text);
190 } else {
191 string(text.toString());
192 }
193 }
194
195
196 /*** {@inheritDoc} */
197 public void writeText(char[] text, int off, int len) throws IOException {
198 if (text == null) {
199 throw new NullPointerException();
200 }
201 if ((off < 0) || (off > text.length) || (len < 0) || (len > text.length)) {
202 throw new IndexOutOfBoundsException();
203 }
204 finish();
205 string(text, off, len);
206 }
207
208
209 /*** {@inheritDoc} */
210 public void writeURIAttribute(String name, Object value, String property) throws IOException {
211 if ((name == null) || (value == null)) {
212 throw new NullPointerException();
213 }
214 if (!open) {
215 throw new IllegalStateException();
216 }
217 writer.write(" ");
218 writer.write(name);
219 writer.write("=\"");
220 if (value instanceof String) {
221 string((String) value);
222 } else {
223 string(value.toString());
224 }
225 writer.write("\"");
226 }
227
228
229
230
231
232 /*** {@inheritDoc} */
233 public void close() throws IOException {
234 finish();
235 writer.close();
236 }
237
238
239 /*** {@inheritDoc} */
240 public void write(char[] cbuf, int off, int len) throws IOException {
241 finish();
242 writer.write(cbuf, off, len);
243 }
244
245
246
247
248
249 /***
250 * <p>Write the specified character, filtering if necessary.</p>
251 *
252 * @param ch Character to be written
253 *
254 * @exception IOException if an input/output error occurs
255 */
256 private void character(char ch) throws IOException {
257
258 if (ch <= 0xff) {
259
260
261 if (ch == 0x22) {
262 writer.write(""");
263 } else if (ch == 0x26) {
264 writer.write("&");
265 } else if (ch == 0x27) {
266 writer.write("'");
267 } else if (ch == 0x3C) {
268 writer.write("<");
269 } else if (ch == 0X3E) {
270 writer.write(">");
271 } else {
272 writer.write(ch);
273 }
274 } else {
275 if (substitution()) {
276 numeric(writer, ch);
277 } else {
278 writer.write(ch);
279 }
280 }
281
282 }
283
284
285 /***
286 * <p>Close any element that is currently open.</p>
287 *
288 * @exception IOException if an input/output error occurs
289 */
290 private void finish() throws IOException {
291
292 if (open) {
293 writer.write(">");
294 open = false;
295 }
296
297 }
298
299
300 /***
301 * <p>Write a numeric character reference for specified character
302 * to the specfied writer.</p>
303 *
304 * @param writer Writer we are writing to
305 * @param ch Character to be translated and appended
306 *
307 * @exception IOException if an input/output error occurs
308 */
309 private void numeric(Writer writer, char ch) throws IOException {
310
311 writer.write("&#");
312 writer.write(String.valueOf((int) ch));
313 writer.write(";");
314
315 }
316
317
318 /***
319 * <p>Write the specified characters (after performing suitable
320 * replacement of characters by corresponding entities).</p>
321 *
322 * @param text Character array containing text to be written
323 * @param off Starting offset (zero relative)
324 * @param len Number of characters to be written
325 *
326 * @exception IOException if an input/output error occurs
327 */
328 private void string(char[] text, int off, int len) throws IOException {
329
330
331 for (int i = off; i < (off + len); i++) {
332 character(text[i]);
333 }
334
335 }
336
337
338 /***
339 * <p>Write the specified string (after performing suitable
340 * replacement of characters by corresponding entities).</p>
341 *
342 * @param s String to be filtered and written
343 *
344 * @exception IOException if an input/output error occurs
345 */
346 private void string(String s) throws IOException {
347
348 for (int i = 0; i < s.length(); i++) {
349 character(s.charAt(i));
350 }
351
352 }
353
354
355 /***
356 * <p>Return true if entity substitution should be performed on double
357 * byte character values.</p>
358 */
359 private boolean substitution() {
360
361 return !("UTF-8".equals(characterEncoding) || "UTF-16".equals(characterEncoding));
362
363 }
364
365
366 }