KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > env > OutputBuffer


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.quercus.env;
31
32 import com.caucho.vfs.ReadStream;
33 import com.caucho.vfs.TempStream;
34 import com.caucho.vfs.WriteStream;
35
36 import java.io.IOException JavaDoc;
37 import java.util.logging.Logger JavaDoc;
38
39 /**
40  * Represents a PHP output buffer
41  */

42 public class OutputBuffer {
43   public static final int PHP_OUTPUT_HANDLER_START = 0;
44   public static final int PHP_OUTPUT_HANDLER_CONT = 1;
45   public static final int PHP_OUTPUT_HANDLER_END = 2;
46
47   private static final Logger JavaDoc log
48     = Logger.getLogger(OutputBuffer.class.getName());
49
50   private int _state;
51   private boolean _haveFlushed;
52   private Callback _callback;
53   
54   private final boolean _erase;
55   private final int _chunkSize;
56   private final int _level;
57
58   private final OutputBuffer _next;
59
60   private final TempStream _tempStream;
61   private final WriteStream _out;
62
63   private final Env _env;
64
65   OutputBuffer(OutputBuffer next, Env env, Callback callback,
66                int chunkSize, boolean erase)
67   {
68     _next = next;
69
70     if (_next != null)
71       _level = _next._level + 1;
72     else
73       _level = 1;
74
75     _erase = erase;
76     _chunkSize = chunkSize;
77
78     _env = env;
79     _callback = callback;
80
81     _tempStream = new TempStream();
82     _out = new WriteStream(_tempStream);
83     _state = 1 << PHP_OUTPUT_HANDLER_START;
84     _haveFlushed = false;
85   }
86
87   /**
88    * Returns the next output buffer;
89    */

90   public OutputBuffer getNext()
91   {
92     return _next;
93   }
94
95   /**
96    * Returns the writer.
97    */

98   public WriteStream getOut()
99   {
100     return _out;
101   }
102
103   /**
104    * Returns the buffer contents.
105    */

106   public Value getContents()
107   {
108     try {
109       _out.flush();
110
111       ReadStream rs = _tempStream.openRead(false);
112       BinaryBuilderValue bb = new BinaryBuilderValue();
113       int ch;
114
115       // XXX: encoding
116
while ((ch = rs.read()) >= 0) {
117         bb.appendByte(ch);
118       }
119
120       return bb;
121     } catch (IOException JavaDoc e) {
122       _env.error(e.toString(), e);
123
124       return BooleanValue.FALSE;
125     }
126   }
127
128   /**
129    * Returns the buffer length.
130    */

131   public long getLength()
132   {
133     try {
134       _out.flush();
135
136       return (long)_tempStream.getLength();
137     } catch (IOException JavaDoc e) {
138       _env.error(e.toString(), e);
139
140       return -1L;
141     }
142   }
143
144   /**
145    * Returns the nesting level.
146    */

147   public int getLevel()
148   {
149     return _level;
150   }
151
152   /**
153    * Returns true if this buffer has ever been flushed.
154    */

155   public boolean haveFlushed()
156   {
157     return _haveFlushed;
158   }
159
160   /**
161    * Returns the erase flag.
162    */

163   public boolean getEraseFlag()
164   {
165     // XXX: Why would anyone need this? If the erase flag is false,
166
// that supposedly means that the buffer will not be destroyed
167
// until the script finishes, but you can't access the buffer
168
// after it has been popped anyway, so who cares if you delete
169
// it or not? It is also confusingly named. More research may
170
// be necessary...
171
return _erase;
172   }
173
174   /**
175    * Returns the chunk size.
176    */

177   public int getChunkSize()
178   {
179     return _chunkSize;
180   }
181
182   /**
183    * Cleans (clears) the buffer.
184    */

185   public void clean()
186   {
187     try {
188       _out.flush();
189
190       _tempStream.clearWrite();
191     } catch (IOException JavaDoc e) {
192       _env.error(e.toString(), e);
193     }
194   }
195
196   /**
197    * Flushes the data without calling the callback.
198    */

199   private void doFlush()
200   {
201     try {
202       _out.flush();
203
204       ReadStream rs = _tempStream.openRead(true);
205
206       WriteStream out;
207
208       if (_next != null)
209         out = _next.getOut();
210       else
211         out = _env.getOriginalOut();
212
213       rs.writeToStream(out);
214
215       rs.close();
216     } catch (IOException JavaDoc e) {
217       _env.error(e.toString(), e);
218     }
219   }
220
221   /**
222    * Invokes the callback using the data in the current buffer.
223    */

224   private void callCallback()
225   {
226     if (_callback != null) {
227       Value result =
228         _callback.call(_env, getContents(), LongValue.create(_state));
229
230       // special code to do nothing to the buffer
231
if (result.isNull())
232         return;
233       
234       clean();
235
236       try {
237         if (result instanceof BinaryValue)
238           _out.write(((BinaryValue) result).toBytes());
239         else
240           _out.print(result.toString(_env).toString());
241       } catch (IOException JavaDoc e) {
242         _env.error(e.toString(), e);
243       }
244     }
245   }
246
247   /**
248    * Flushs the data in the stream, calling the callback with appropriate
249    * flags if necessary.
250    */

251   public void flush()
252   {
253     _state |= 1 << PHP_OUTPUT_HANDLER_CONT;
254
255     callCallback();
256
257     // clear the start and cont flags
258
_state &= ~(1 << PHP_OUTPUT_HANDLER_START);
259     _state &= ~(1 << PHP_OUTPUT_HANDLER_CONT);
260
261     doFlush();
262
263     _haveFlushed = true;
264   }
265
266   /**
267    * Closes the output buffer.
268    */

269   public void close()
270   {
271     _state |= 1 << PHP_OUTPUT_HANDLER_END;
272
273     callCallback();
274     
275     // all data that has and ever will be written has now been processed
276
_state = 0;
277
278     doFlush();
279   }
280
281   /**
282    * Returns the callback for this output buffer.
283    */

284   public Callback getCallback()
285   {
286     return _callback;
287   }
288
289   /**
290    * Sets the callback for this output buffer.
291    */

292   public void setCallback(Callback callback)
293   {
294     _callback = callback;
295   }
296 }
297
298
Popular Tags