KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > velocity > io > VelocityWriter


1 package org.apache.velocity.io;
2
3 /*
4  * Copyright 2000-2001,2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * 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, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import java.io.IOException JavaDoc;
20 import java.io.Writer JavaDoc;
21
22 /**
23  * Implementation of a fast Writer. It was originally taken from JspWriter
24  * and modified to have less syncronization going on.
25  *
26  * @author <a HREF="mailto:jvanzyl@apache.org">Jason van Zyl</a>
27  * @author <a HREF="mailto:jon@latchkey.com">Jon S. Stevens</a>
28  * @author Anil K. Vijendran
29  * @version $Id: VelocityWriter.java,v 1.8.4.1 2004/03/03 23:22:54 geirm Exp $
30  */

31 public final class VelocityWriter extends Writer JavaDoc
32 {
33     /**
34      * constant indicating that the Writer is not buffering output
35      */

36     public static final int NO_BUFFER = 0;
37
38     /**
39      * constant indicating that the Writer is buffered and is using the
40      * implementation default buffer size
41      */

42     public static final int DEFAULT_BUFFER = -1;
43
44     /**
45      * constant indicating that the Writer is buffered and is unbounded;
46      * this is used in BodyContent
47      */

48     public static final int UNBOUNDED_BUFFER = -2;
49
50     protected int bufferSize;
51     protected boolean autoFlush;
52
53     private Writer JavaDoc writer;
54     
55     private char cb[];
56     private int nextChar;
57
58     private static int defaultCharBufferSize = 8 * 1024;
59
60     private boolean flushed = false;
61
62     /**
63      * Create a buffered character-output stream that uses a default-sized
64      * output buffer.
65      *
66      * @param response A Servlet Response
67      */

68     public VelocityWriter(Writer JavaDoc writer)
69     {
70         this(writer, defaultCharBufferSize, true);
71     }
72
73     /**
74      * private constructor.
75      */

76     private VelocityWriter(int bufferSize, boolean autoFlush)
77     {
78         this.bufferSize = bufferSize;
79         this.autoFlush = autoFlush;
80     }
81
82     /**
83      * This method returns the size of the buffer used by the JspWriter.
84      *
85      * @return the size of the buffer in bytes, or 0 is unbuffered.
86      */

87     public int getBufferSize() { return bufferSize; }
88
89     /**
90      * This method indicates whether the JspWriter is autoFlushing.
91      *
92      * @return if this JspWriter is auto flushing or throwing IOExceptions on
93      * buffer overflow conditions
94      */

95     public boolean isAutoFlush() { return autoFlush; }
96
97     /**
98      * Create a new buffered character-output stream that uses an output
99      * buffer of the given size.
100      *
101      * @param response A Servlet Response
102      * @param sz Output-buffer size, a positive integer
103      *
104      * @exception IllegalArgumentException If sz is <= 0
105      */

106     public VelocityWriter(Writer JavaDoc writer, int sz, boolean autoFlush)
107     {
108         this(sz, autoFlush);
109         if (sz < 0)
110             throw new IllegalArgumentException JavaDoc("Buffer size <= 0");
111         this.writer = writer;
112         cb = sz == 0 ? null : new char[sz];
113         nextChar = 0;
114     }
115
116     private final void init( Writer JavaDoc writer, int sz, boolean autoFlush )
117     {
118         this.writer= writer;
119         if( sz > 0 && ( cb == null || sz > cb.length ) )
120             cb=new char[sz];
121         nextChar = 0;
122         this.autoFlush=autoFlush;
123         this.bufferSize=sz;
124     }
125
126     /**
127      * Flush the output buffer to the underlying character stream, without
128      * flushing the stream itself. This method is non-private only so that it
129      * may be invoked by PrintStream.
130      */

131     private final void flushBuffer() throws IOException JavaDoc
132     {
133         if (bufferSize == 0)
134             return;
135         flushed = true;
136         if (nextChar == 0)
137             return;
138         writer.write(cb, 0, nextChar);
139         nextChar = 0;
140     }
141
142     /**
143      * Discard the output buffer.
144      */

145     public final void clear()
146     {
147         nextChar = 0;
148     }
149
150     private final void bufferOverflow() throws IOException JavaDoc
151     {
152         throw new IOException JavaDoc("overflow");
153     }
154
155     /**
156      * Flush the stream.
157      *
158      */

159     public final void flush() throws IOException JavaDoc
160     {
161         flushBuffer();
162         if (writer != null)
163         {
164             writer.flush();
165         }
166     }
167
168     /**
169      * Close the stream.
170      *
171      */

172     public final void close() throws IOException JavaDoc {
173         if (writer == null)
174             return;
175         flush();
176     }
177
178     /**
179      * @return the number of bytes unused in the buffer
180      */

181     public final int getRemaining()
182     {
183         return bufferSize - nextChar;
184     }
185
186     /**
187      * Write a single character.
188      *
189      */

190     public final void write(int c) throws IOException JavaDoc
191     {
192         if (bufferSize == 0)
193         {
194             writer.write(c);
195         }
196         else
197         {
198             if (nextChar >= bufferSize)
199                 if (autoFlush)
200                     flushBuffer();
201                 else
202                     bufferOverflow();
203             cb[nextChar++] = (char) c;
204         }
205     }
206
207     /**
208      * Our own little min method, to avoid loading
209      * <code>java.lang.Math</code> if we've run out of file
210      * descriptors and we're trying to print a stack trace.
211      */

212     private final int min(int a, int b)
213     {
214         return (a < b ? a : b);
215     }
216
217     /**
218      * Write a portion of an array of characters.
219      *
220      * <p> Ordinarily this method stores characters from the given array into
221      * this stream's buffer, flushing the buffer to the underlying stream as
222      * needed. If the requested length is at least as large as the buffer,
223      * however, then this method will flush the buffer and write the characters
224      * directly to the underlying stream. Thus redundant
225      * <code>DiscardableBufferedWriter</code>s will not copy data unnecessarily.
226      *
227      * @param cbuf A character array
228      * @param off Offset from which to start reading characters
229      * @param len Number of characters to write
230      *
231      */

232     public final void write(char cbuf[], int off, int len)
233         throws IOException JavaDoc
234     {
235         if (bufferSize == 0)
236         {
237             writer.write(cbuf, off, len);
238             return;
239         }
240
241         if (len == 0)
242         {
243             return;
244         }
245
246         if (len >= bufferSize)
247         {
248             /* If the request length exceeds the size of the output buffer,
249             flush the buffer and then write the data directly. In this
250             way buffered streams will cascade harmlessly. */

251             if (autoFlush)
252                 flushBuffer();
253             else
254                 bufferOverflow();
255                 writer.write(cbuf, off, len);
256             return;
257         }
258
259         int b = off, t = off + len;
260         while (b < t)
261         {
262             int d = min(bufferSize - nextChar, t - b);
263             System.arraycopy(cbuf, b, cb, nextChar, d);
264             b += d;
265             nextChar += d;
266             if (nextChar >= bufferSize)
267                 if (autoFlush)
268                     flushBuffer();
269                 else
270                     bufferOverflow();
271         }
272     }
273
274     /**
275      * Write an array of characters. This method cannot be inherited from the
276      * Writer class because it must suppress I/O exceptions.
277      */

278     public final void write(char buf[]) throws IOException JavaDoc
279     {
280         write(buf, 0, buf.length);
281     }
282
283     /**
284      * Write a portion of a String.
285      *
286      * @param s String to be written
287      * @param off Offset from which to start reading characters
288      * @param len Number of characters to be written
289      *
290      */

291     public final void write(String JavaDoc s, int off, int len) throws IOException JavaDoc
292     {
293         if (bufferSize == 0)
294         {
295             writer.write(s, off, len);
296             return;
297         }
298         int b = off, t = off + len;
299         while (b < t)
300         {
301             int d = min(bufferSize - nextChar, t - b);
302             s.getChars(b, b + d, cb, nextChar);
303             b += d;
304             nextChar += d;
305             if (nextChar >= bufferSize)
306                 if (autoFlush)
307                     flushBuffer();
308                 else
309                     bufferOverflow();
310         }
311     }
312
313     /**
314      * Write a string. This method cannot be inherited from the Writer class
315      * because it must suppress I/O exceptions.
316      */

317     public final void write(String JavaDoc s) throws IOException JavaDoc
318     {
319         write(s, 0, s.length());
320     }
321
322     /**
323      * resets this class so that it can be reused
324      *
325      */

326     public final void recycle( Writer JavaDoc writer)
327     {
328         this.writer = writer;
329         flushed = false;
330         clear();
331     }
332 }
333
Popular Tags