KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > http > HttpInputStream


1 // ========================================================================
2
// $Id: HttpInputStream.java,v 1.13 2005/08/23 20:02:26 gregwilkins Exp $
3
// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.http;
17
18 import java.io.FilterInputStream JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.io.OutputStream JavaDoc;
22 import java.io.UnsupportedEncodingException JavaDoc;
23
24 import org.apache.commons.logging.Log;
25 import org.mortbay.log.LogFactory;
26 import org.mortbay.util.LineInput;
27 import org.mortbay.util.StringUtil;
28
29
30 /* ------------------------------------------------------------ */
31 /** HTTP Chunking InputStream.
32  * This FilterInputStream acts as a BufferedInputStream until
33  * setChunking(true) is called. Once chunking is
34  * enabled, the raw stream is chunk decoded as per RFC2616.
35  *
36  * The "8859-1" encoding is used on underlying LineInput instance for
37  * line based reads from the raw stream.
38  *
39  * This class is not synchronized and should be synchronized
40  * explicitly if an instance is used by multiple threads.
41  *
42  * @see org.mortbay.util.LineInput
43  * @version $Id: HttpInputStream.java,v 1.13 2005/08/23 20:02:26 gregwilkins Exp $
44  * @author Greg Wilkins (gregw)
45  */

46 public class HttpInputStream extends FilterInputStream JavaDoc
47 {
48     private static Log log = LogFactory.getLog(HttpInputStream.class);
49
50     /* ------------------------------------------------------------ */
51     private static ClosedStream __closedStream=new ClosedStream();
52     
53     /* ------------------------------------------------------------ */
54     private ChunkingInputStream _deChunker;
55     private LineInput _realIn;
56     private boolean _chunking;
57     private OutputStream JavaDoc _expectContinues;
58     
59     /* ------------------------------------------------------------ */
60     /** Constructor.
61      */

62     public HttpInputStream( InputStream JavaDoc in)
63     {
64         this(in,4096);
65     }
66     
67     /* ------------------------------------------------------------ */
68     /** Constructor.
69      */

70     public HttpInputStream(InputStream JavaDoc in, int bufferSize)
71     {
72         super(null);
73         try {
74             _realIn= new LineInput(in,bufferSize,StringUtil.__ISO_8859_1);
75         }
76         catch(UnsupportedEncodingException JavaDoc e)
77         {
78             log.fatal(e); System.exit(1);
79         }
80         this.in=_realIn;
81     }
82     
83     /* ------------------------------------------------------------ */
84     /**
85      * @param expectContinues The expectContinues to set.
86      */

87     public OutputStream JavaDoc getExpectContinues()
88     {
89         return _expectContinues;
90     }
91     
92     /* ------------------------------------------------------------ */
93     /**
94      * @param expectContinues The expectContinues to set.
95      */

96     public void setExpectContinues(OutputStream JavaDoc expectContinues)
97     {
98         _expectContinues = expectContinues;
99     }
100     
101     /* ------------------------------------------------------------ */
102     /*
103      * @see java.io.InputStream#read()
104      */

105     public int read() throws IOException JavaDoc
106     {
107         if (_expectContinues!=null)
108             expectContinues();
109         return super.read();
110     }
111     
112     /* ------------------------------------------------------------ */
113     /*
114      * @see java.io.InputStream#read(byte[], int, int)
115      */

116     public int read(byte[] b, int off, int len) throws IOException JavaDoc
117     {
118         if (_expectContinues!=null)
119             expectContinues();
120         return super.read(b, off, len);
121     }
122     
123     /* ------------------------------------------------------------ */
124     /*
125      * @see java.io.InputStream#read(byte[])
126      */

127     public int read(byte[] b) throws IOException JavaDoc
128     {
129         if (_expectContinues!=null)
130             expectContinues();
131         return super.read(b);
132     }
133     
134     /* ------------------------------------------------------------ */
135     /*
136      * @see java.io.InputStream#skip(long)
137      */

138     public long skip(long n) throws IOException JavaDoc
139     {
140         if (_expectContinues!=null)
141             expectContinues();
142         return super.skip(n);
143     }
144     
145     /* ------------------------------------------------------------ */
146     private void expectContinues()
147         throws IOException JavaDoc
148         {
149         try
150         {
151             if (available()<=0)
152             {
153                 _expectContinues.write(HttpResponse.__Continue);
154                 _expectContinues.flush();
155             }
156         }
157         finally
158         {
159             _expectContinues=null;
160         }
161             
162     }
163     
164     /* ------------------------------------------------------------ */
165     /** Get the raw stream.
166      * A stream without filters or chunking is returned. This stream
167      * may still be buffered and uprocessed bytes may be in the buffer.
168      * @return Raw InputStream.
169      */

170     public InputStream JavaDoc getInputStream()
171     {
172         return _realIn;
173     }
174     
175     /* ------------------------------------------------------------ */
176     /** Get Filter InputStream.
177      * Get the current top of the InputStream filter stack
178      * @return InputStream.
179      */

180     public InputStream JavaDoc getFilterStream()
181     {
182         return in;
183     }
184     
185     /* ------------------------------------------------------------ */
186     /** Set Filter InputStream.
187      * Set input filter stream, which should be constructed to wrap
188      * the stream returned from get FilterStream.
189      */

190     public void setFilterStream(InputStream JavaDoc filter)
191     {
192         in=filter;
193     }
194     
195     /* ------------------------------------------------------------ */
196     /** Get chunking mode
197      */

198     public boolean isChunking()
199     {
200         return _chunking;
201     }
202     
203     /* ------------------------------------------------------------ */
204     /** Set chunking mode.
205      * Chunking can only be turned off with a call to resetStream().
206      * @exception IllegalStateException Checking cannot be set if
207      * a content length has been set.
208      */

209     public void setChunking()
210         throws IllegalStateException JavaDoc
211     {
212         if (_realIn.getByteLimit()>=0)
213             throw new IllegalStateException JavaDoc("Has Content-Length");
214         if (_deChunker==null)
215             _deChunker=new ChunkingInputStream(_realIn);
216         in=_deChunker;
217         
218         _chunking=true;
219         _deChunker._trailer=null;
220     }
221
222     /* ------------------------------------------------------------ */
223     /** Reset the stream.
224      * Turn chunking off and disable all filters.
225      * @exception IllegalStateException The stream cannot be reset if
226      * there is some unread chunked input or a content length greater
227      * than zero remaining.
228      */

229     public void resetStream()
230         throws IllegalStateException JavaDoc
231     {
232         if ((_deChunker!=null && _deChunker._chunkSize>0) ||
233             _realIn.getByteLimit()>0)
234             throw new IllegalStateException JavaDoc("Unread input");
235         if(log.isTraceEnabled())log.trace("resetStream()");
236         in=_realIn;
237         if (_deChunker!=null)
238             _deChunker.resetStream();
239         _chunking=false;
240         _realIn.setByteLimit(-1);
241     }
242  
243     /* ------------------------------------------------------------ */
244     public void close()
245         throws IOException JavaDoc
246     {
247         in=__closedStream;
248     }
249     
250     
251     /* ------------------------------------------------------------ */
252     /** Set the content length.
253      * Only this number of bytes can be read before EOF is returned.
254      * @param len length.
255      */

256     public void setContentLength(int len)
257     {
258         if (_chunking && len>=0 && getExpectContinues()==null)
259             throw new IllegalStateException JavaDoc("Chunking");
260         _realIn.setByteLimit(len);
261     }
262
263     /* ------------------------------------------------------------ */
264     void unsafeSetContentLength(int len)
265     {
266         _realIn.setByteLimit(len);
267     }
268     
269     /* ------------------------------------------------------------ */
270     /** Get the content length.
271      * @return Number of bytes until EOF is returned or -1 for no limit.
272      */

273     public int getContentLength()
274     {
275         return _realIn.getByteLimit();
276     }
277
278     /* ------------------------------------------------------------ */
279     public HttpFields getTrailer()
280     {
281         return _deChunker._trailer;
282     }
283
284     /* ------------------------------------------------------------ */
285     public void destroy()
286     {
287         if (_realIn!=null)
288             _realIn.destroy();
289         _realIn=null;
290         _deChunker=null;
291         _expectContinues=null;
292     }
293     
294     
295     /* ------------------------------------------------------------ */
296     /** A closed input stream.
297      */

298     private static class ClosedStream extends InputStream JavaDoc
299     {
300         /* ------------------------------------------------------------ */
301         public int read()
302             throws IOException JavaDoc
303         {
304             return -1;
305         }
306     }
307 }
308
Popular Tags