KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icesoft > faces > webapp > parser > BodyContentImpl


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 1999 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if
20  * any, must include the following acknowlegement:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowlegement may appear in the software itself,
24  * if and wherever such third-party acknowlegements normally appear.
25  *
26  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
27  * Foundation" must not be used to endorse or promote products derived
28  * from this software without prior written permission. For written
29  * permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache"
32  * nor may "Apache" appear in their names without prior written
33  * permission of the Apache Group.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation. For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  */

55
56
57 package com.icesoft.faces.webapp.parser;
58
59 import com.icesoft.jasper.Constants;
60
61 import javax.servlet.jsp.JspWriter JavaDoc;
62 import javax.servlet.jsp.tagext.BodyContent JavaDoc;
63 import java.io.CharArrayReader JavaDoc;
64 import java.io.IOException JavaDoc;
65 import java.io.Reader JavaDoc;
66 import java.io.Writer JavaDoc;
67
68 /**
69  * Write text to a character-output stream, buffering characters so as to
70  * provide for the efficient writing of single characters, arrays, and strings.
71  * <p/>
72  * Provide support for discarding for the output that has been buffered.
73  *
74  * @author Rajiv Mordani
75  * @author Jan Luehe
76  */

77 public class BodyContentImpl extends BodyContent JavaDoc {
78
79     private static final String JavaDoc LINE_SEPARATOR = System.getProperty(
80             "line.separator");
81
82     private char[] cb;
83     private int nextChar;
84     private boolean closed;
85
86     // Enclosed writer to which any output is written
87
private Writer JavaDoc writer;
88
89     // See comment in setWriter()
90
private int bufferSizeSave;
91
92     /**
93      * Constructor.
94      */

95     public BodyContentImpl(JspWriter JavaDoc enclosingWriter) {
96         super(enclosingWriter);
97         bufferSize = Constants.DEFAULT_TAG_BUFFER_SIZE;
98         cb = new char[bufferSize];
99         nextChar = 0;
100         closed = false;
101     }
102
103     /**
104      * Write a single character.
105      */

106     public void write(int c) throws IOException JavaDoc {
107         if (writer != null) {
108             writer.write(c);
109         } else {
110             ensureOpen();
111             if (nextChar >= bufferSize) {
112                 reAllocBuff(1);
113             }
114             cb[nextChar++] = (char) c;
115         }
116     }
117
118     /**
119      * Write a portion of an array of characters.
120      * <p/>
121      * <p> Ordinarily this method stores characters from the given array into
122      * this stream's buffer, flushing the buffer to the underlying stream as
123      * needed. If the requested length is at least as large as the buffer,
124      * however, then this method will flush the buffer and write the characters
125      * directly to the underlying stream. Thus redundant
126      * <code>DiscardableBufferedWriter</code>s will not copy data
127      * unnecessarily.
128      *
129      * @param cbuf A character array
130      * @param off Offset from which to start reading characters
131      * @param len Number of characters to write
132      */

133     public void write(char[] cbuf, int off, int len) throws IOException JavaDoc {
134         if (writer != null) {
135             writer.write(cbuf, off, len);
136         } else {
137             ensureOpen();
138
139             if ((off < 0) || (off > cbuf.length) || (len < 0) ||
140                 ((off + len) > cbuf.length) || ((off + len) < 0)) {
141                 throw new IndexOutOfBoundsException JavaDoc();
142             } else if (len == 0) {
143                 return;
144             }
145
146             if (len >= bufferSize - nextChar)
147                 reAllocBuff(len);
148
149             System.arraycopy(cbuf, off, cb, nextChar, len);
150             nextChar += len;
151         }
152     }
153
154     /**
155      * Write an array of characters. This method cannot be inherited from the
156      * Writer class because it must suppress I/O exceptions.
157      */

158     public void write(char[] buf) throws IOException JavaDoc {
159         if (writer != null) {
160             writer.write(buf);
161         } else {
162             write(buf, 0, buf.length);
163         }
164     }
165
166     /**
167      * Write a portion of a String.
168      *
169      * @param s String to be written
170      * @param off Offset from which to start reading characters
171      * @param len Number of characters to be written
172      */

173     public void write(String JavaDoc s, int off, int len) throws IOException JavaDoc {
174         if (writer != null) {
175             writer.write(s, off, len);
176         } else {
177             ensureOpen();
178             if (len >= bufferSize - nextChar)
179                 reAllocBuff(len);
180
181             s.getChars(off, off + len, cb, nextChar);
182             nextChar += len;
183         }
184     }
185
186     /**
187      * Write a string. This method cannot be inherited from the Writer class
188      * because it must suppress I/O exceptions.
189      */

190     public void write(String JavaDoc s) throws IOException JavaDoc {
191         if (writer != null) {
192             writer.write(s);
193         } else {
194             write(s, 0, s.length());
195         }
196     }
197
198     /**
199      * Write a line separator. The line separator string is defined by the
200      * system property <tt>line.separator</tt>, and is not necessarily a single
201      * newline ('\n') character.
202      *
203      * @throws IOException If an I/O error occurs
204      */

205     public void newLine() throws IOException JavaDoc {
206         if (writer != null) {
207             writer.write(LINE_SEPARATOR);
208         } else {
209             write(LINE_SEPARATOR);
210         }
211     }
212
213     /**
214      * Print a boolean value. The string produced by <code>{@link
215      * java.lang.String#valueOf(boolean)}</code> is translated into bytes
216      * according to the platform's default character encoding, and these bytes
217      * are written in exactly the manner of the <code>{@link #write(int)}</code>
218      * method.
219      *
220      * @param b The <code>boolean</code> to be printed
221      * @throws IOException
222      */

223     public void print(boolean b) throws IOException JavaDoc {
224         if (writer != null) {
225             writer.write(b ? "true" : "false");
226         } else {
227             write(b ? "true" : "false");
228         }
229     }
230
231     /**
232      * Print a character. The character is translated into one or more bytes
233      * according to the platform's default character encoding, and these bytes
234      * are written in exactly the manner of the <code>{@link #write(int)}</code>
235      * method.
236      *
237      * @param c The <code>char</code> to be printed
238      * @throws IOException
239      */

240     public void print(char c) throws IOException JavaDoc {
241         if (writer != null) {
242             writer.write(String.valueOf(c));
243         } else {
244             write(String.valueOf(c));
245         }
246     }
247
248     /**
249      * Print an integer. The string produced by <code>{@link
250      * java.lang.String#valueOf(int)}</code> is translated into bytes according
251      * to the platform's default character encoding, and these bytes are written
252      * in exactly the manner of the <code>{@link #write(int)}</code> method.
253      *
254      * @param i The <code>int</code> to be printed
255      * @throws IOException
256      */

257     public void print(int i) throws IOException JavaDoc {
258         if (writer != null) {
259             writer.write(String.valueOf(i));
260         } else {
261             write(String.valueOf(i));
262         }
263     }
264
265     /**
266      * Print a long integer. The string produced by <code>{@link
267      * java.lang.String#valueOf(long)}</code> is translated into bytes according
268      * to the platform's default character encoding, and these bytes are written
269      * in exactly the manner of the <code>{@link #write(int)}</code> method.
270      *
271      * @param l The <code>long</code> to be printed
272      * @throws IOException
273      */

274     public void print(long l) throws IOException JavaDoc {
275         if (writer != null) {
276             writer.write(String.valueOf(l));
277         } else {
278             write(String.valueOf(l));
279         }
280     }
281
282     /**
283      * Print a floating-point number. The string produced by <code>{@link
284      * java.lang.String#valueOf(float)}</code> is translated into bytes
285      * according to the platform's default character encoding, and these bytes
286      * are written in exactly the manner of the <code>{@link #write(int)}</code>
287      * method.
288      *
289      * @param f The <code>float</code> to be printed
290      * @throws IOException
291      */

292     public void print(float f) throws IOException JavaDoc {
293         if (writer != null) {
294             writer.write(String.valueOf(f));
295         } else {
296             write(String.valueOf(f));
297         }
298     }
299
300     /**
301      * Print a double-precision floating-point number. The string produced by
302      * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
303      * bytes according to the platform's default character encoding, and these
304      * bytes are written in exactly the manner of the <code>{@link
305      * #write(int)}</code> method.
306      *
307      * @param d The <code>double</code> to be printed
308      * @throws IOException
309      */

310     public void print(double d) throws IOException JavaDoc {
311         if (writer != null) {
312             writer.write(String.valueOf(d));
313         } else {
314             write(String.valueOf(d));
315         }
316     }
317
318     /**
319      * Print an array of characters. The characters are converted into bytes
320      * according to the platform's default character encoding, and these bytes
321      * are written in exactly the manner of the <code>{@link #write(int)}</code>
322      * method.
323      *
324      * @param s The array of chars to be printed
325      * @throws NullPointerException If <code>s</code> is <code>null</code>
326      * @throws IOException
327      */

328     public void print(char[] s) throws IOException JavaDoc {
329         if (writer != null) {
330             writer.write(s);
331         } else {
332             write(s);
333         }
334     }
335
336     /**
337      * Print a string. If the argument is <code>null</code> then the string
338      * <code>"null"</code> is printed. Otherwise, the string's characters are
339      * converted into bytes according to the platform's default character
340      * encoding, and these bytes are written in exactly the manner of the
341      * <code>{@link #write(int)}</code> method.
342      *
343      * @param s The <code>String</code> to be printed
344      * @throws IOException
345      */

346     public void print(String JavaDoc s) throws IOException JavaDoc {
347         if (s == null) s = "null";
348         if (writer != null) {
349             writer.write(s);
350         } else {
351             write(s);
352         }
353     }
354
355     /**
356      * Print an object. The string produced by the <code>{@link
357      * java.lang.String#valueOf(Object)}</code> method is translated into bytes
358      * according to the platform's default character encoding, and these bytes
359      * are written in exactly the manner of the <code>{@link #write(int)}</code>
360      * method.
361      *
362      * @param obj The <code>Object</code> to be printed
363      * @throws IOException
364      */

365     public void print(Object JavaDoc obj) throws IOException JavaDoc {
366         if (writer != null) {
367             writer.write(String.valueOf(obj));
368         } else {
369             write(String.valueOf(obj));
370         }
371     }
372
373     /**
374      * Terminate the current line by writing the line separator string. The
375      * line separator string is defined by the system property
376      * <code>line.separator</code>, and is not necessarily a single newline
377      * character (<code>'\n'</code>).
378      *
379      * @throws IOException
380      */

381     public void println() throws IOException JavaDoc {
382         newLine();
383     }
384
385     /**
386      * Print a boolean value and then terminate the line. This method behaves
387      * as though it invokes <code>{@link #print(boolean)}</code> and then
388      * <code>{@link #println()}</code>.
389      *
390      * @throws IOException
391      */

392     public void println(boolean x) throws IOException JavaDoc {
393         print(x);
394         println();
395     }
396
397     /**
398      * Print a character and then terminate the line. This method behaves as
399      * though it invokes <code>{@link #print(char)}</code> and then <code>{@link
400      * #println()}</code>.
401      *
402      * @throws IOException
403      */

404     public void println(char x) throws IOException JavaDoc {
405         print(x);
406         println();
407     }
408
409     /**
410      * Print an integer and then terminate the line. This method behaves as
411      * though it invokes <code>{@link #print(int)}</code> and then <code>{@link
412      * #println()}</code>.
413      *
414      * @throws IOException
415      */

416     public void println(int x) throws IOException JavaDoc {
417         print(x);
418         println();
419     }
420
421     /**
422      * Print a long integer and then terminate the line. This method behaves as
423      * though it invokes <code>{@link #print(long)}</code> and then <code>{@link
424      * #println()}</code>.
425      *
426      * @throws IOException
427      */

428     public void println(long x) throws IOException JavaDoc {
429         print(x);
430         println();
431     }
432
433     /**
434      * Print a floating-point number and then terminate the line. This method
435      * behaves as though it invokes <code>{@link #print(float)}</code> and then
436      * <code>{@link #println()}</code>.
437      *
438      * @throws IOException
439      */

440     public void println(float x) throws IOException JavaDoc {
441         print(x);
442         println();
443     }
444
445     /**
446      * Print a double-precision floating-point number and then terminate the
447      * line. This method behaves as though it invokes <code>{@link
448      * #print(double)}</code> and then <code>{@link #println()}</code>.
449      *
450      * @throws IOException
451      */

452     public void println(double x) throws IOException JavaDoc {
453         print(x);
454         println();
455     }
456
457     /**
458      * Print an array of characters and then terminate the line. This method
459      * behaves as though it invokes <code>{@link #print(char[])}</code> and then
460      * <code>{@link #println()}</code>.
461      *
462      * @throws IOException
463      */

464     public void println(char x[]) throws IOException JavaDoc {
465         print(x);
466         println();
467     }
468
469     /**
470      * Print a String and then terminate the line. This method behaves as
471      * though it invokes <code>{@link #print(String)}</code> and then
472      * <code>{@link #println()}</code>.
473      *
474      * @throws IOException
475      */

476     public void println(String JavaDoc x) throws IOException JavaDoc {
477         print(x);
478         println();
479     }
480
481     /**
482      * Print an Object and then terminate the line. This method behaves as
483      * though it invokes <code>{@link #print(Object)}</code> and then
484      * <code>{@link #println()}</code>.
485      *
486      * @throws IOException
487      */

488     public void println(Object JavaDoc x) throws IOException JavaDoc {
489         print(x);
490         println();
491     }
492
493     /**
494      * Clear the contents of the buffer. If the buffer has been already been
495      * flushed then the clear operation shall throw an IOException to signal the
496      * fact that some data has already been irrevocably written to the client
497      * response stream.
498      *
499      * @throws IOException If an I/O error occurs
500      */

501     public void clear() throws IOException JavaDoc {
502         if (writer != null) {
503             throw new IOException JavaDoc();
504         } else {
505             nextChar = 0;
506         }
507     }
508
509     /**
510      * Clears the current contents of the buffer. Unlike clear(), this mehtod
511      * will not throw an IOException if the buffer has already been flushed. It
512      * merely clears the current content of the buffer and returns.
513      *
514      * @throws IOException If an I/O error occurs
515      */

516     public void clearBuffer() throws IOException JavaDoc {
517         if (writer == null) {
518             this.clear();
519         }
520     }
521
522     /**
523      * Close the stream, flushing it first. Once a stream has been closed,
524      * further write() or flush() invocations will cause an IOException to be
525      * thrown. Closing a previously-closed stream, however, has no effect.
526      *
527      * @throws IOException If an I/O error occurs
528      */

529     public void close() throws IOException JavaDoc {
530         if (writer != null) {
531             writer.close();
532         } else {
533             cb = null;
534             closed = true;
535         }
536     }
537
538     /**
539      * @return the number of bytes unused in the buffer
540      */

541     public int getRemaining() {
542         return (writer == null) ? bufferSize - nextChar : 0;
543     }
544
545     /**
546      * Return the value of this BodyJspWriter as a Reader. Note: this is after
547      * evaluation!! There are no scriptlets, etc in this stream.
548      *
549      * @return the value of this BodyJspWriter as a Reader
550      */

551     public Reader JavaDoc getReader() {
552         return (writer == null) ? new CharArrayReader JavaDoc(cb, 0, nextChar) : null;
553     }
554
555     /**
556      * Return the value of the BodyJspWriter as a String. Note: this is after
557      * evaluation!! There are no scriptlets, etc in this stream.
558      *
559      * @return the value of the BodyJspWriter as a String
560      */

561     public String JavaDoc getString() {
562         return (writer == null) ? new String JavaDoc(cb, 0, nextChar) : null;
563     }
564
565     /**
566      * Write the contents of this BodyJspWriter into a Writer. Subclasses are
567      * likely to do interesting things with the implementation so some things
568      * are extra efficient.
569      *
570      * @param out The writer into which to place the contents of this body
571      * evaluation
572      */

573     public void writeOut(Writer JavaDoc out) throws IOException JavaDoc {
574         if (writer == null) {
575             out.write(cb, 0, nextChar);
576             // Flush not called as the writer passed could be a BodyContent and
577
// it doesn't allow to flush.
578
}
579     }
580
581     /**
582      * Sets the writer to which all output is written.
583      */

584     void setWriter(Writer JavaDoc writer) {
585         this.writer = writer;
586         if (writer != null) {
587             // According to the spec, the JspWriter returned by
588
// JspContext.pushBody(java.io.Writer writer) must behave as
589
// though it were unbuffered. This means that its getBufferSize()
590
// must always return 0. The implementation of
591
// JspWriter.getBufferSize() returns the value of JspWriter's
592
// 'bufferSize' field, which is inherited by this class.
593
// Therefore, we simply save the current 'bufferSize' (so we can
594
// later restore it should this BodyContentImpl ever be reused by
595
// a call to PageContext.pushBody()) before setting it to 0.
596
if (bufferSize != 0) {
597                 bufferSizeSave = bufferSize;
598                 bufferSize = 0;
599             }
600         } else {
601             bufferSize = bufferSizeSave;
602             clearBody();
603         }
604     }
605
606     private void ensureOpen() throws IOException JavaDoc {
607         if (closed) throw new IOException JavaDoc("Stream closed");
608     }
609
610     /**
611      * Reallocates buffer since the spec requires it to be unbounded.
612      */

613     private void reAllocBuff(int len) {
614
615         if (bufferSize + len <= cb.length) {
616             bufferSize = cb.length;
617             return;
618         }
619
620         if (len < cb.length) {
621             len = cb.length;
622         }
623
624         bufferSize = cb.length + len;
625         char[] tmp = new char[bufferSize];
626
627         System.arraycopy(cb, 0, tmp, 0, cb.length);
628         cb = tmp;
629         tmp = null;
630
631     }
632
633
634 }
635
Popular Tags