KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > connection > ToByteResponseStream


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.server.connection;
31
32 import com.caucho.log.Log;
33 import com.caucho.util.L10N;
34 import com.caucho.vfs.Encoding;
35 import com.caucho.vfs.TempBuffer;
36 import com.caucho.vfs.i18n.EncodingWriter;
37
38 import java.io.IOException JavaDoc;
39 import java.io.UnsupportedEncodingException JavaDoc;
40 import java.util.Locale JavaDoc;
41 import java.util.logging.Logger JavaDoc;
42
43 /**
44  * Handles the dual char/byte buffering for the response stream.
45  */

46 public abstract class ToByteResponseStream extends AbstractResponseStream {
47   private static final Logger JavaDoc log = Log.open(ToByteResponseStream.class);
48   private static final L10N L = new L10N(ToByteResponseStream.class);
49
50   protected static final int SIZE = TempBuffer.SIZE;
51
52   private final char []_charBuffer = new char[SIZE];
53   private int _charLength;
54
55   // head of the expandable buffer
56
private TempBuffer _head = TempBuffer.allocate();
57   private TempBuffer _tail;
58   
59   private byte []_byteBuffer;
60   private int _byteLength;
61   
62   private int _bufferCapacity;
63   private int _bufferSize;
64   
65   private boolean _isHead;
66   private boolean _isClosed;
67   protected boolean _isFinished;
68
69   private EncodingWriter _toByte = Encoding.getLatin1Writer();
70
71   protected ToByteResponseStream()
72   {
73   }
74   
75   /**
76    * Initializes the Buffered Response stream at the beginning of a request.
77    */

78   public void start()
79   {
80     _bufferCapacity = SIZE;
81     
82     _charLength = 0;
83     
84     _head.clear();
85     _tail = _head;
86     _byteBuffer = _tail.getBuffer();
87     _byteLength = 0;
88     
89     _bufferSize = 0;
90     
91     _isHead = false;
92     _isClosed = false;
93     _isFinished = false;
94
95     _toByte = Encoding.getLatin1Writer();
96   }
97
98   /**
99    * Returns true for a caucho response stream.
100    */

101   public boolean isCauchoResponseStream()
102   {
103     return true;
104   }
105
106   /**
107    * Sets the head.
108    */

109   public void setHead()
110   {
111     _isHead = true;
112   }
113
114   /**
115    * Sets the encoding.
116    */

117   public void setEncoding(String JavaDoc encoding)
118     throws UnsupportedEncodingException JavaDoc
119   {
120     EncodingWriter toByte;
121     
122     if (encoding == null)
123       toByte = Encoding.getLatin1Writer();
124     else
125       toByte = Encoding.getWriteEncoding(encoding);
126
127     if (toByte != null)
128       _toByte = toByte;
129     else {
130       _toByte = Encoding.getLatin1Writer();
131     
132       throw new UnsupportedEncodingException JavaDoc(encoding);
133     }
134   }
135
136   /**
137    * Sets the locale.
138    */

139   public void setLocale(Locale JavaDoc locale)
140     throws UnsupportedEncodingException JavaDoc
141   {
142   }
143
144   /**
145    * Returns the char buffer.
146    */

147   public char []getCharBuffer()
148   {
149     return _charBuffer;
150   }
151
152   /**
153    * Returns the char offset.
154    */

155   public int getCharOffset()
156     throws IOException JavaDoc
157   {
158     return _charLength;
159   }
160
161   /**
162    * Sets the char offset.
163    */

164   public void setCharOffset(int offset)
165     throws IOException JavaDoc
166   {
167     _charLength = offset;
168
169     if (_charLength == SIZE)
170       flushCharBuffer();
171   }
172
173   /**
174    * Returns the byte buffer.
175    */

176   public byte []getBuffer()
177     throws IOException JavaDoc
178   {
179     return _byteBuffer;
180   }
181
182   /**
183    * Returns the byte offset.
184    */

185   public int getBufferOffset()
186     throws IOException JavaDoc
187   {
188     return _byteLength;
189   }
190
191   /**
192    * Sets the byte offset.
193    */

194   public void setBufferOffset(int offset)
195     throws IOException JavaDoc
196   {
197     if (_charLength > 0)
198       flushCharBuffer();
199     
200     _byteLength = offset;
201   }
202
203   /**
204    * Returns the buffer capacity.
205    */

206   public int getBufferSize()
207   {
208     return _bufferCapacity;
209   }
210
211   /**
212    * Returns true for extended buffers.
213    */

214   /*
215   public boolean isExtendedBuffer()
216   {
217     return _bufferCapacity < SIZE;
218   }
219   */

220
221   /**
222    * Sets the buffer capacity.
223    */

224   public void setBufferSize(int size)
225   {
226     _bufferCapacity = SIZE * ((size + SIZE - 1) / SIZE);
227
228     if (_bufferCapacity <= 0)
229       _bufferCapacity = 0;
230   }
231
232   /**
233    * Returns the remaining value left.
234    */

235   public int getRemaining()
236   {
237     return _bufferCapacity - getBufferLength();
238   }
239
240   /**
241    * Returns the remaining value left.
242    */

243   protected int getBufferLength()
244   {
245     return _bufferSize + _byteLength + _charLength;
246   }
247
248   /**
249    * Clears the response buffer.
250    */

251   public void clearBuffer()
252   {
253     TempBuffer next = _head.getNext();
254     if (next != null) {
255       _head.setNext(null);
256       TempBuffer.freeAll(next);
257     }
258     _head.clear();
259     _tail = _head;
260     _byteBuffer = _tail.getBuffer();
261     _byteLength = 0;
262     
263     _charLength = 0;
264
265     _bufferSize = 0;
266   }
267
268   /**
269    * Writes a character to the output.
270    */

271   public void write(int ch)
272     throws IOException JavaDoc
273   {
274     if (_isClosed)
275       return;
276     else if (_isHead) {
277       return;
278     }
279
280     if (_charLength > 0)
281       flushCharBuffer();
282
283     if (_bufferCapacity <= _bufferSize + _byteLength + 1) {
284       flushByteBuffer();
285     }
286     else if (_byteLength == SIZE) {
287       _tail.setLength(_byteLength);
288       _bufferSize += _byteLength;
289     
290       TempBuffer tempBuf = TempBuffer.allocate();
291       _tail.setNext(tempBuf);
292       _tail = tempBuf;
293
294       _byteBuffer = _tail.getBuffer();
295       _byteLength = 0;
296     }
297
298     _byteBuffer[_byteLength++] = (byte) ch;
299   }
300
301   /**
302    * Writes a chunk of bytes to the stream.
303    */

304   public void write(byte []buffer, int offset, int length)
305     throws IOException JavaDoc
306   {
307     boolean isFinished = false;
308
309     if (_isClosed)
310       return;
311     else if (_isHead) {
312       return;
313     }
314
315     if (_charLength > 0)
316       flushCharBuffer();
317
318     if (_bufferCapacity <= _bufferSize + _byteLength + length) {
319       if (_bufferSize + _byteLength > 0)
320     flushByteBuffer();
321
322       if (_bufferCapacity <= length) {
323     _bufferSize = length;
324     writeNext(buffer, offset, length, isFinished);
325     _bufferSize = 0;
326     return;
327       }
328     }
329
330     int byteLength = _byteLength;
331     while (length > 0) {
332       if (SIZE <= byteLength) {
333     _tail.setLength(byteLength);
334     _bufferSize += byteLength;
335     
336     TempBuffer tempBuf = TempBuffer.allocate();
337     _tail.setNext(tempBuf);
338     _tail = tempBuf;
339
340     _byteBuffer = _tail.getBuffer();
341     byteLength = 0;
342       }
343
344       int sublen = length;
345       if (SIZE - byteLength < sublen)
346     sublen = SIZE - byteLength;
347
348       System.arraycopy(buffer, offset, _byteBuffer, byteLength, sublen);
349
350       offset += sublen;
351       length -= sublen;
352       byteLength += sublen;
353     }
354
355     _byteLength = byteLength;
356   }
357
358   /**
359    * Writes a character to the output.
360    */

361   public void print(int ch)
362     throws IOException JavaDoc
363   {
364     if (_isClosed)
365       return;
366     else if (_isHead)
367       return;
368     
369     _charBuffer[_charLength++] = (char) ch;
370     
371     if (_charLength == SIZE)
372       flushCharBuffer();
373   }
374
375   /**
376    * Writes a char array to the output.
377    */

378   public void print(char []buffer, int offset, int length)
379     throws IOException JavaDoc
380   {
381     if (_isClosed)
382       return;
383     else if (_isHead)
384       return;
385     
386     int charLength = _charLength;
387
388     while (length > 0) {
389       int sublen = SIZE - charLength;
390
391       if (length < sublen)
392     sublen = length;
393
394       System.arraycopy(buffer, offset, _charBuffer, charLength, sublen);
395
396       offset += sublen;
397       length -= sublen;
398       charLength += sublen;
399       
400       if (charLength == SIZE) {
401     _charLength = charLength;
402     charLength = 0;
403     flushCharBuffer();
404       }
405     }
406
407     _charLength = charLength;
408   }
409
410   /**
411    * Flushes the buffer.
412    */

413   public void flushBuffer()
414     throws IOException JavaDoc
415   {
416     if (_charLength > 0)
417       flushCharBuffer();
418
419     flushByteBuffer();
420   }
421
422   /**
423    * Flushes the buffered response to the output stream.
424    */

425   public void flush()
426     throws IOException JavaDoc
427   {
428     flushBuffer();
429   }
430
431   /**
432    * Closes the response stream.
433    */

434   public void close()
435     throws IOException JavaDoc
436   {
437     flushBuffer();
438
439     _isClosed = true;
440   }
441
442   /**
443    * Converts the char buffer.
444    */

445   public char []nextCharBuffer(int offset)
446     throws IOException JavaDoc
447   {
448     _charLength = offset;
449     flushCharBuffer();
450
451     return _charBuffer;
452   }
453
454   /**
455    * Converts the char buffer.
456    */

457   protected void flushCharBuffer()
458     throws IOException JavaDoc
459   {
460     int charLength = _charLength;
461     _charLength = 0;
462
463     if (charLength > 0) {
464       _toByte.write(this, _charBuffer, 0, charLength);
465
466       if (_bufferCapacity <= _byteLength + _bufferSize)
467     flushByteBuffer();
468     }
469   }
470
471   /**
472    * Returns the next byte buffer.
473    */

474   public byte []nextBuffer(int offset)
475     throws IOException JavaDoc
476   {
477     if (_byteLength + _bufferSize < _bufferCapacity) {
478       _tail.setLength(offset);
479       _bufferSize += offset;
480     
481       TempBuffer tempBuf = TempBuffer.allocate();
482       _tail.setNext(tempBuf);
483       _tail = tempBuf;
484
485       _byteBuffer = _tail.getBuffer();
486       _byteLength = 0;
487     }
488     else {
489       _byteLength = offset;
490       flushByteBuffer();
491     }
492
493     return _byteBuffer;
494   }
495
496   /**
497    * Flushes the buffered response to the output stream.
498    */

499   protected void flushByteBuffer()
500     throws IOException JavaDoc
501   {
502     _tail.setLength(_byteLength);
503     _bufferSize += _byteLength;
504     _byteLength = 0;
505
506     TempBuffer ptr = _head;
507     do {
508       _head = ptr;
509       
510       TempBuffer next = ptr.getNext();
511       ptr.setNext(null);
512
513       writeNext(ptr.getBuffer(), 0, ptr.getLength(), _isFinished);
514
515       if (next != null)
516     TempBuffer.free(ptr);
517
518       ptr = next;
519     } while (ptr != null);
520
521     _tail = _head;
522     _byteBuffer = _tail.getBuffer();
523     _bufferSize = 0;
524   }
525
526   /**
527    * Writes the chunk to the downward stream.
528    */

529   abstract protected void writeNext(byte []buffer, int offset,
530                     int length, boolean isEnd)
531     throws IOException JavaDoc;
532
533   /**
534    * Clears the close.
535    */

536   public void clearClose()
537   {
538     _isClosed = false;
539   }
540 }
541
Popular Tags