KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jasper > runtime > JspWriterImpl


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.jasper.runtime;
19
20 import java.io.IOException JavaDoc;
21 import java.io.Writer JavaDoc;
22 import java.security.AccessController JavaDoc;
23 import java.security.PrivilegedAction JavaDoc;
24
25 import javax.servlet.ServletResponse JavaDoc;
26 import javax.servlet.jsp.JspWriter JavaDoc;
27
28 import org.apache.jasper.Constants;
29 import org.apache.jasper.compiler.Localizer;
30 import org.apache.jasper.security.SecurityUtil;
31
32 /**
33  * Write text to a character-output stream, buffering characters so as
34  * to provide for the efficient writing of single characters, arrays,
35  * and strings.
36  *
37  * Provide support for discarding for the output that has been
38  * buffered.
39  *
40  * This needs revisiting when the buffering problems in the JSP spec
41  * are fixed -akv
42  *
43  * @author Anil K. Vijendran
44  */

45 public class JspWriterImpl extends JspWriter JavaDoc {
46     
47     private Writer JavaDoc out;
48     private ServletResponse JavaDoc response;
49     private char cb[];
50     private int nextChar;
51     private boolean flushed = false;
52     private boolean closed = false;
53     
54     public JspWriterImpl() {
55         super( Constants.DEFAULT_BUFFER_SIZE, true );
56     }
57     
58     /**
59      * Create a buffered character-output stream that uses a default-sized
60      * output buffer.
61      *
62      * @param response A Servlet Response
63      */

64     public JspWriterImpl(ServletResponse JavaDoc response) {
65         this(response, Constants.DEFAULT_BUFFER_SIZE, true);
66     }
67     
68     /**
69      * Create a new buffered character-output stream that uses an output
70      * buffer of the given size.
71      *
72      * @param response A Servlet Response
73      * @param sz Output-buffer size, a positive integer
74      *
75      * @exception IllegalArgumentException If sz is <= 0
76      */

77     public JspWriterImpl(ServletResponse JavaDoc response, int sz,
78             boolean autoFlush) {
79         super(sz, autoFlush);
80         if (sz < 0)
81             throw new IllegalArgumentException JavaDoc("Buffer size <= 0");
82         this.response = response;
83         cb = sz == 0 ? null : new char[sz];
84         nextChar = 0;
85     }
86     
87     void init( ServletResponse JavaDoc response, int sz, boolean autoFlush ) {
88         this.response= response;
89         if( sz > 0 && ( cb == null || sz > cb.length ) )
90             cb=new char[sz];
91         nextChar = 0;
92         this.autoFlush=autoFlush;
93         this.bufferSize=sz;
94     }
95     
96     /** Package-level access
97      */

98     void recycle() {
99         flushed = false;
100         closed = false;
101         out = null;
102         nextChar = 0;
103         response = null;
104     }
105     
106     /**
107      * Flush the output buffer to the underlying character stream, without
108      * flushing the stream itself. This method is non-private only so that it
109      * may be invoked by PrintStream.
110      */

111     protected final void flushBuffer() throws IOException JavaDoc {
112         if (bufferSize == 0)
113             return;
114         flushed = true;
115         ensureOpen();
116         if (nextChar == 0)
117             return;
118         initOut();
119         out.write(cb, 0, nextChar);
120         nextChar = 0;
121     }
122     
123     private void initOut() throws IOException JavaDoc {
124         if (out == null) {
125             out = response.getWriter();
126         }
127     }
128     
129     private String JavaDoc getLocalizeMessage(final String JavaDoc message){
130         if (SecurityUtil.isPackageProtectionEnabled()){
131             return (String JavaDoc)AccessController.doPrivileged(new PrivilegedAction JavaDoc(){
132                 public Object JavaDoc run(){
133                     return Localizer.getMessage(message);
134                 }
135             });
136         } else {
137             return Localizer.getMessage(message);
138         }
139     }
140     
141     /**
142      * Discard the output buffer.
143      */

144     public final void clear() throws IOException JavaDoc {
145         if ((bufferSize == 0) && (out != null))
146             // clear() is illegal after any unbuffered output (JSP.5.5)
147
throw new IllegalStateException JavaDoc(
148                     getLocalizeMessage("jsp.error.ise_on_clear"));
149         if (flushed)
150             throw new IOException JavaDoc(
151                     getLocalizeMessage("jsp.error.attempt_to_clear_flushed_buffer"));
152         ensureOpen();
153         nextChar = 0;
154     }
155     
156     public void clearBuffer() throws IOException JavaDoc {
157         if (bufferSize == 0)
158             throw new IllegalStateException JavaDoc(
159                     getLocalizeMessage("jsp.error.ise_on_clear"));
160         ensureOpen();
161         nextChar = 0;
162     }
163     
164     private final void bufferOverflow() throws IOException JavaDoc {
165         throw new IOException JavaDoc(getLocalizeMessage("jsp.error.overflow"));
166     }
167     
168     /**
169      * Flush the stream.
170      *
171      */

172     public void flush() throws IOException JavaDoc {
173         flushBuffer();
174         if (out != null) {
175             out.flush();
176         }
177     }
178     
179     /**
180      * Close the stream.
181      *
182      */

183     public void close() throws IOException JavaDoc {
184         if (response == null || closed)
185             // multiple calls to close is OK
186
return;
187         flush();
188         if (out != null)
189             out.close();
190         out = null;
191         closed = true;
192     }
193     
194     /**
195      * @return the number of bytes unused in the buffer
196      */

197     public int getRemaining() {
198         return bufferSize - nextChar;
199     }
200     
201     /** check to make sure that the stream has not been closed */
202     private void ensureOpen() throws IOException JavaDoc {
203         if (response == null || closed)
204             throw new IOException JavaDoc("Stream closed");
205     }
206     
207     
208     /**
209      * Write a single character.
210      */

211     public void write(int c) throws IOException JavaDoc {
212         ensureOpen();
213         if (bufferSize == 0) {
214             initOut();
215             out.write(c);
216         }
217         else {
218             if (nextChar >= bufferSize)
219                 if (autoFlush)
220                     flushBuffer();
221                 else
222                     bufferOverflow();
223             cb[nextChar++] = (char) c;
224         }
225     }
226     
227     /**
228      * Our own little min method, to avoid loading java.lang.Math if we've run
229      * out of file descriptors and we're trying to print a stack trace.
230      */

231     private int min(int a, int b) {
232         if (a < b) return a;
233         return b;
234     }
235     
236     /**
237      * Write a portion of an array of characters.
238      *
239      * <p> Ordinarily this method stores characters from the given array into
240      * this stream's buffer, flushing the buffer to the underlying stream as
241      * needed. If the requested length is at least as large as the buffer,
242      * however, then this method will flush the buffer and write the characters
243      * directly to the underlying stream. Thus redundant
244      * <code>DiscardableBufferedWriter</code>s will not copy data unnecessarily.
245      *
246      * @param cbuf A character array
247      * @param off Offset from which to start reading characters
248      * @param len Number of characters to write
249      */

250     public void write(char cbuf[], int off, int len)
251     throws IOException JavaDoc
252     {
253         ensureOpen();
254         
255         if (bufferSize == 0) {
256             initOut();
257             out.write(cbuf, off, len);
258             return;
259         }
260         
261         if ((off < 0) || (off > cbuf.length) || (len < 0) ||
262                 ((off + len) > cbuf.length) || ((off + len) < 0)) {
263             throw new IndexOutOfBoundsException JavaDoc();
264         } else if (len == 0) {
265             return;
266         }
267         
268         if (len >= bufferSize) {
269             /* If the request length exceeds the size of the output buffer,
270              flush the buffer and then write the data directly. In this
271              way buffered streams will cascade harmlessly. */

272             if (autoFlush)
273                 flushBuffer();
274             else
275                 bufferOverflow();
276             initOut();
277             out.write(cbuf, off, len);
278             return;
279         }
280         
281         int b = off, t = off + len;
282         while (b < t) {
283             int d = min(bufferSize - nextChar, t - b);
284             System.arraycopy(cbuf, b, cb, nextChar, d);
285             b += d;
286             nextChar += d;
287             if (nextChar >= bufferSize)
288                 if (autoFlush)
289                     flushBuffer();
290                 else
291                     bufferOverflow();
292         }
293         
294     }
295     
296     /**
297      * Write an array of characters. This method cannot be inherited from the
298      * Writer class because it must suppress I/O exceptions.
299      */

300     public void write(char buf[]) throws IOException JavaDoc {
301         write(buf, 0, buf.length);
302     }
303     
304     /**
305      * Write a portion of a String.
306      *
307      * @param s String to be written
308      * @param off Offset from which to start reading characters
309      * @param len Number of characters to be written
310      */

311     public void write(String JavaDoc s, int off, int len) throws IOException JavaDoc {
312         ensureOpen();
313         if (bufferSize == 0) {
314             initOut();
315             out.write(s, off, len);
316             return;
317         }
318         int b = off, t = off + len;
319         while (b < t) {
320             int d = min(bufferSize - nextChar, t - b);
321             s.getChars(b, b + d, cb, nextChar);
322             b += d;
323             nextChar += d;
324             if (nextChar >= bufferSize)
325                 if (autoFlush)
326                     flushBuffer();
327                 else
328                     bufferOverflow();
329         }
330     }
331     
332     /**
333      * Write a string. This method cannot be inherited from the Writer class
334      * because it must suppress I/O exceptions.
335      */

336     public void write(String JavaDoc s) throws IOException JavaDoc {
337         // Simple fix for Bugzilla 35410
338
// Calling the other write function so as to init the buffer anyways
339
if(s == null) {
340             write(s, 0, 0);
341         } else {
342             write(s, 0, s.length());
343         }
344     }
345     
346     
347     static String JavaDoc lineSeparator = System.getProperty("line.separator");
348     
349     /**
350      * Write a line separator. The line separator string is defined by the
351      * system property <tt>line.separator</tt>, and is not necessarily a single
352      * newline ('\n') character.
353      *
354      * @exception IOException If an I/O error occurs
355      */

356     
357     public void newLine() throws IOException JavaDoc {
358         write(lineSeparator);
359     }
360     
361     
362     /* Methods that do not terminate lines */
363     
364     /**
365      * Print a boolean value. The string produced by <code>{@link
366      * java.lang.String#valueOf(boolean)}</code> is translated into bytes
367      * according to the platform's default character encoding, and these bytes
368      * are written in exactly the manner of the <code>{@link
369      * #write(int)}</code> method.
370      *
371      * @param b The <code>boolean</code> to be printed
372      */

373     public void print(boolean b) throws IOException JavaDoc {
374         write(b ? "true" : "false");
375     }
376     
377     /**
378      * Print a character. The character is translated into one or more bytes
379      * according to the platform's default character encoding, and these bytes
380      * are written in exactly the manner of the <code>{@link
381      * #write(int)}</code> method.
382      *
383      * @param c The <code>char</code> to be printed
384      */

385     public void print(char c) throws IOException JavaDoc {
386         write(String.valueOf(c));
387     }
388     
389     /**
390      * Print an integer. The string produced by <code>{@link
391      * java.lang.String#valueOf(int)}</code> is translated into bytes according
392      * to the platform's default character encoding, and these bytes are
393      * written in exactly the manner of the <code>{@link #write(int)}</code>
394      * method.
395      *
396      * @param i The <code>int</code> to be printed
397      */

398     public void print(int i) throws IOException JavaDoc {
399         write(String.valueOf(i));
400     }
401     
402     /**
403      * Print a long integer. The string produced by <code>{@link
404      * java.lang.String#valueOf(long)}</code> is translated into bytes
405      * according to the platform's default character encoding, and these bytes
406      * are written in exactly the manner of the <code>{@link #write(int)}</code>
407      * method.
408      *
409      * @param l The <code>long</code> to be printed
410      */

411     public void print(long l) throws IOException JavaDoc {
412         write(String.valueOf(l));
413     }
414     
415     /**
416      * Print a floating-point number. The string produced by <code>{@link
417      * java.lang.String#valueOf(float)}</code> is translated into bytes
418      * according to the platform's default character encoding, and these bytes
419      * are written in exactly the manner of the <code>{@link #write(int)}</code>
420      * method.
421      *
422      * @param f The <code>float</code> to be printed
423      */

424     public void print(float f) throws IOException JavaDoc {
425         write(String.valueOf(f));
426     }
427     
428     /**
429      * Print a double-precision floating-point number. The string produced by
430      * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
431      * bytes according to the platform's default character encoding, and these
432      * bytes are written in exactly the manner of the <code>{@link
433      * #write(int)}</code> method.
434      *
435      * @param d The <code>double</code> to be printed
436      */

437     public void print(double d) throws IOException JavaDoc {
438         write(String.valueOf(d));
439     }
440     
441     /**
442      * Print an array of characters. The characters are converted into bytes
443      * according to the platform's default character encoding, and these bytes
444      * are written in exactly the manner of the <code>{@link #write(int)}</code>
445      * method.
446      *
447      * @param s The array of chars to be printed
448      *
449      * @throws NullPointerException If <code>s</code> is <code>null</code>
450      */

451     public void print(char s[]) throws IOException JavaDoc {
452         write(s);
453     }
454     
455     /**
456      * Print a string. If the argument is <code>null</code> then the string
457      * <code>"null"</code> is printed. Otherwise, the string's characters are
458      * converted into bytes according to the platform's default character
459      * encoding, and these bytes are written in exactly the manner of the
460      * <code>{@link #write(int)}</code> method.
461      *
462      * @param s The <code>String</code> to be printed
463      */

464     public void print(String JavaDoc s) throws IOException JavaDoc {
465         if (s == null) {
466             s = "null";
467         }
468         write(s);
469     }
470     
471     /**
472      * Print an object. The string produced by the <code>{@link
473      * java.lang.String#valueOf(Object)}</code> method is translated into bytes
474      * according to the platform's default character encoding, and these bytes
475      * are written in exactly the manner of the <code>{@link #write(int)}</code>
476      * method.
477      *
478      * @param obj The <code>Object</code> to be printed
479      */

480     public void print(Object JavaDoc obj) throws IOException JavaDoc {
481         write(String.valueOf(obj));
482     }
483     
484     /* Methods that do terminate lines */
485     
486     /**
487      * Terminate the current line by writing the line separator string. The
488      * line separator string is defined by the system property
489      * <code>line.separator</code>, and is not necessarily a single newline
490      * character (<code>'\n'</code>).
491      *
492      * Need to change this from PrintWriter because the default
493      * println() writes to the sink directly instead of through the
494      * write method...
495      */

496     public void println() throws IOException JavaDoc {
497         newLine();
498     }
499     
500     /**
501      * Print a boolean value and then terminate the line. This method behaves
502      * as though it invokes <code>{@link #print(boolean)}</code> and then
503      * <code>{@link #println()}</code>.
504      */

505     public void println(boolean x) throws IOException JavaDoc {
506         print(x);
507         println();
508     }
509     
510     /**
511      * Print a character and then terminate the line. This method behaves as
512      * though it invokes <code>{@link #print(char)}</code> and then <code>{@link
513      * #println()}</code>.
514      */

515     public void println(char x) throws IOException JavaDoc {
516         print(x);
517         println();
518     }
519     
520     /**
521      * Print an integer and then terminate the line. This method behaves as
522      * though it invokes <code>{@link #print(int)}</code> and then <code>{@link
523      * #println()}</code>.
524      */

525     public void println(int x) throws IOException JavaDoc {
526         print(x);
527         println();
528     }
529     
530     /**
531      * Print a long integer and then terminate the line. This method behaves
532      * as though it invokes <code>{@link #print(long)}</code> and then
533      * <code>{@link #println()}</code>.
534      */

535     public void println(long x) throws IOException JavaDoc {
536         print(x);
537         println();
538     }
539     
540     /**
541      * Print a floating-point number and then terminate the line. This method
542      * behaves as though it invokes <code>{@link #print(float)}</code> and then
543      * <code>{@link #println()}</code>.
544      */

545     public void println(float x) throws IOException JavaDoc {
546         print(x);
547         println();
548     }
549     
550     /**
551      * Print a double-precision floating-point number and then terminate the
552      * line. This method behaves as though it invokes <code>{@link
553      * #print(double)}</code> and then <code>{@link #println()}</code>.
554      */

555     public void println(double x) throws IOException JavaDoc {
556         print(x);
557         println();
558     }
559     
560     /**
561      * Print an array of characters and then terminate the line. This method
562      * behaves as though it invokes <code>{@link #print(char[])}</code> and then
563      * <code>{@link #println()}</code>.
564      */

565     public void println(char x[]) throws IOException JavaDoc {
566         print(x);
567         println();
568     }
569     
570     /**
571      * Print a String and then terminate the line. This method behaves as
572      * though it invokes <code>{@link #print(String)}</code> and then
573      * <code>{@link #println()}</code>.
574      */

575     public void println(String JavaDoc x) throws IOException JavaDoc {
576         print(x);
577         println();
578     }
579     
580     /**
581      * Print an Object and then terminate the line. This method behaves as
582      * though it invokes <code>{@link #print(Object)}</code> and then
583      * <code>{@link #println()}</code>.
584      */

585     public void println(Object JavaDoc x) throws IOException JavaDoc {
586         print(x);
587         println();
588     }
589     
590 }
591
Popular Tags