KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > transport > http > ChunkedInputStream


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.axis.transport.http;
17
18
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21
22
23 /**
24  *
25  * @author Rick Rineholt
26  */

27
28 public class ChunkedInputStream extends java.io.FilterInputStream JavaDoc {
29
30     protected long chunkSize = 0l;
31     protected volatile boolean closed = false;
32     
33     private static final int maxCharLong =
34         (Long.toHexString(Long.MAX_VALUE)).toString().length();
35     
36     private byte[] buf = new byte[maxCharLong + 2];
37
38     private ChunkedInputStream () {
39         super(null);
40     }
41
42     public ChunkedInputStream (InputStream JavaDoc is) {
43         super(is);
44     }
45
46     public synchronized int read()
47         throws IOException JavaDoc {
48         if (closed) {
49             return -1;
50         }
51         try {
52             if (chunkSize < 1L) {
53                 if (0l == getChunked()) {
54                     return -1;
55                 }
56             }
57             int rc = in.read();
58             if (rc > 0) {
59                 chunkSize--;
60             }
61             return rc;
62         } catch (IOException JavaDoc e) {
63             closed = true;
64             throw e;
65         }
66     }
67
68     public int read(byte[] b)
69         throws IOException JavaDoc {
70         return read(b, 0, b.length);
71     }
72
73     public synchronized int read(byte[] b,
74                                  int off,
75                                  int len)
76         throws IOException JavaDoc {
77         if (closed) {
78             return -1;
79         }
80
81         int totalread = 0;
82         int bytesread = 0;
83
84         try {
85             do {
86                 if (chunkSize < 1L) {
87                     if (0l == getChunked()) {
88                         if (totalread == 0) return -1;
89                         else return totalread;
90                     }
91                 }
92                 bytesread = in.read(b, off + totalread, Math.min(len - totalread,
93                                 (int) Math.min(chunkSize, Integer.MAX_VALUE)));
94                 if (bytesread > 0) {
95                     totalread += bytesread;
96                     chunkSize -= bytesread;
97                 }
98             }
99             while (len - totalread > 0 && bytesread > -1);
100         } catch (IOException JavaDoc e) {
101             closed = true;
102             throw e;
103         }
104         return totalread;
105     }
106
107     public long skip(final long n)
108         throws IOException JavaDoc {
109         if (closed) {
110             return 0;
111         }
112         long skipped = 0l;
113         byte[] b = new byte[1024];
114         int bread = -1;
115
116         do {
117             bread = read(b, 0, b.length);
118             if (bread > 0) skipped += bread;
119         }
120         while (bread != -1 && skipped < n);
121         return skipped;
122     }
123
124     public int available()
125         throws IOException JavaDoc {
126         if (closed) {
127             return 0;
128         }
129         int rc = (int) Math.min(chunkSize, Integer.MAX_VALUE);
130
131         return Math.min(rc, in.available());
132     }
133               
134     protected long getChunked()throws IOException JavaDoc {
135         int bufsz = 0;
136         chunkSize = -1L;
137         int c = -1;
138
139         do {
140             c = in.read();
141             if (c > -1) {
142                 if (c != '\r' && c != '\n' && c != ' ' && c != '\t') {
143                     buf[bufsz++] = ((byte) c);
144                 }
145             }
146         }
147         while (c > -1 && (c != '\n' || bufsz == 0) && bufsz < buf.length);
148         if (c < 0) {
149             closed = true;
150         }
151         String JavaDoc sbuf = new String JavaDoc(buf, 0, bufsz);
152
153         if (bufsz > maxCharLong) {
154             closed = true;
155             throw new IOException JavaDoc("Chunked input stream failed to receive valid chunk size:" + sbuf);
156         }
157         try {
158             chunkSize = Long.parseLong(sbuf, 16);
159         } catch (NumberFormatException JavaDoc ne) {
160             closed = true;
161             throw new IOException JavaDoc("'" + sbuf + "' " + ne.getMessage());
162         }
163         if (chunkSize < 0L) {
164             closed = true;
165         } if (chunkSize == 0) {
166             closed = true;
167             // consume last \r\n tokens of 0\r\n\r\n chunk
168
if (in.read() != -1) {
169                 in.read();
170             }
171         }
172         if (chunkSize != 0L && c < 0) {
173             //If chunk size is zero try and be tolerant that there maybe no cr or lf at the end.
174
throw new IOException JavaDoc("HTTP Chunked stream closed in middle of chunk.");
175         }
176         if (chunkSize < 0L) {
177             throw new IOException JavaDoc("HTTP Chunk size received " +
178                                   chunkSize + " is less than zero.");
179         }
180         return chunkSize;
181     }
182
183     public void close() throws IOException JavaDoc {
184    
185         synchronized (this) {
186             if (closed) {
187                 return;
188             }
189             closed = true;
190         }
191
192         byte[] b = new byte[1024];
193         int bread = -1;
194
195         do {
196             bread = read(b, 0, b.length);
197         }
198         while (bread != -1);
199     }
200
201     /*
202      public void mark(int readlimit)
203      {
204      
205      }
206      */

207
208     public void reset()
209         throws IOException JavaDoc {
210         throw new IOException JavaDoc("Don't support marked streams");
211     }
212
213     public boolean markSupported() {
214         return false;
215     }
216
217 }
218
Popular Tags