1 // ========================================================================
2 // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
3 // ------------------------------------------------------------------------
4 // All rights reserved. This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v1.0
6 // and Apache License v2.0 which accompanies this distribution.
7 // The Eclipse Public License is available at
8 // http://www.eclipse.org/legal/epl-v10.html
9 // The Apache License v2.0 is available at
10 // http://www.opensource.org/licenses/apache2.0.php
11 // You may elect to redistribute this code under either of these licenses.
12 // ========================================================================
13
14 package org.eclipse.jetty.server;
15
16 import java.io.IOException;
17 import java.io.Writer;
18
19 import javax.servlet.ServletOutputStream;
20
21 import org.eclipse.jetty.http.AbstractGenerator;
22 import org.eclipse.jetty.http.Generator;
23 import org.eclipse.jetty.io.Buffer;
24 import org.eclipse.jetty.io.ByteArrayBuffer;
25 import org.eclipse.jetty.io.EofException;
26 import org.eclipse.jetty.util.ByteArrayOutputStream2;
27
28 /** Output.
29 *
30 * <p>
31 * Implements {@link javax.servlet.ServletOutputStream} from the {@link javax.servlet} package.
32 * </p>
33 * A {@link ServletOutputStream} implementation that writes content
34 * to a {@link AbstractGenerator}. The class is designed to be reused
35 * and can be reopened after a close.
36 */
37 public class HttpOutput extends ServletOutputStream
38 {
39 protected final AbstractGenerator _generator;
40 protected final long _maxIdleTime;
41 protected final ByteArrayBuffer _buf = new ByteArrayBuffer(AbstractGenerator.NO_BYTES);
42 protected boolean _closed;
43
44 // These are held here for reuse by Writer
45 String _characterEncoding;
46 Writer _converter;
47 char[] _chars;
48 ByteArrayOutputStream2 _bytes;
49
50
51 /* ------------------------------------------------------------ */
52 public HttpOutput(AbstractGenerator generator, long maxIdleTime)
53 {
54 _generator=generator;
55 _maxIdleTime=maxIdleTime;
56 }
57
58 /* ------------------------------------------------------------ */
59 /*
60 * @see java.io.OutputStream#close()
61 */
62 public void close() throws IOException
63 {
64 _closed=true;
65 }
66
67 /* ------------------------------------------------------------ */
68 public void reopen()
69 {
70 _closed=false;
71 }
72
73 /* ------------------------------------------------------------ */
74 public void flush() throws IOException
75 {
76 _generator.flush(_maxIdleTime);
77 }
78
79 /* ------------------------------------------------------------ */
80 public void write(byte[] b, int off, int len) throws IOException
81 {
82 _buf.wrap(b, off, len);
83 write(_buf);
84 }
85
86 /* ------------------------------------------------------------ */
87 /*
88 * @see java.io.OutputStream#write(byte[])
89 */
90 public void write(byte[] b) throws IOException
91 {
92 _buf.wrap(b);
93 write(_buf);
94 }
95
96 /* ------------------------------------------------------------ */
97 /*
98 * @see java.io.OutputStream#write(int)
99 */
100 public void write(int b) throws IOException
101 {
102 if (_closed)
103 throw new IOException("Closed");
104 if (!_generator.isOpen())
105 throw new EofException();
106
107 // Block until we can add _content.
108 while (_generator.isBufferFull())
109 {
110 _generator.blockForOutput(_maxIdleTime);
111 if (_closed)
112 throw new IOException("Closed");
113 if (!_generator.isOpen())
114 throw new EofException();
115 }
116
117 // Add the _content
118 if (_generator.addContent((byte)b))
119 // Buffers are full so flush.
120 flush();
121
122 if (_generator.isContentWritten())
123 {
124 flush();
125 close();
126 }
127 }
128
129 /* ------------------------------------------------------------ */
130 private void write(Buffer buffer) throws IOException
131 {
132 if (_closed)
133 throw new IOException("Closed");
134 if (!_generator.isOpen())
135 throw new EofException();
136
137 // Block until we can add _content.
138 while (_generator.isBufferFull())
139 {
140 _generator.blockForOutput(_maxIdleTime);
141 if (_closed)
142 throw new IOException("Closed");
143 if (!_generator.isOpen())
144 throw new EofException();
145 }
146
147 // Add the _content
148 _generator.addContent(buffer, Generator.MORE);
149
150 // Have to flush and complete headers?
151 if (_generator.isBufferFull())
152 flush();
153
154 if (_generator.isContentWritten())
155 {
156 flush();
157 close();
158 }
159
160 // Block until our buffer is free
161 while (buffer.length() > 0 && _generator.isOpen())
162 _generator.blockForOutput(_maxIdleTime);
163 }
164
165 /* ------------------------------------------------------------ */
166 /*
167 * @see javax.servlet.ServletOutputStream#print(java.lang.String)
168 */
169 public void print(String s) throws IOException
170 {
171 write(s.getBytes());
172 }
173 }