1 28 29 package HTTPClient; 30 31 32 import java.io.OutputStream ; 33 import java.io.ByteArrayOutputStream ; 34 import java.io.IOException ; 35 36 90 91 public class HttpOutputStream extends OutputStream implements GlobalConstants 92 { 93 94 private static final NVPair[] empty = new NVPair[0]; 95 96 97 private int length; 98 99 100 private int rcvd = 0; 101 102 103 private Request req = null; 104 105 106 private Response resp = null; 107 108 109 private OutputStream os = null; 110 111 112 private ByteArrayOutputStream bos = null; 113 114 115 private NVPair[] trailers = empty; 116 117 118 private int con_to = 0; 119 120 121 private boolean ignore = false; 122 123 124 126 133 public HttpOutputStream() 134 { 135 length = -1; 136 } 137 138 139 145 public HttpOutputStream(int length) 146 { 147 if (length < 0) 148 throw new IllegalArgumentException ("Length must be greater equal 0"); 149 this.length = length; 150 } 151 152 153 155 165 void goAhead(Request req, OutputStream os, int con_to) 166 { 167 this.req = req; 168 this.os = os; 169 this.con_to = con_to; 170 171 if (os == null) 172 bos = new ByteArrayOutputStream (); 173 174 if (DebugConn) 175 { 176 System.err.println("OutS: Stream ready for writing"); 177 if (bos != null) 178 System.err.println("OutS: Buffering all data before sending " + 179 "request"); 180 } 181 } 182 183 184 190 void ignoreData(Request req) 191 { 192 this.req = req; 193 ignore = true; 194 } 195 196 197 203 synchronized Response getResponse() 204 { 205 while (resp == null) 206 try { wait(); } catch (InterruptedException ie) { } 207 208 return resp; 209 } 210 211 212 218 public int getLength() 219 { 220 return length; 221 } 222 223 224 230 public NVPair[] getTrailers() 231 { 232 return trailers; 233 } 234 235 236 252 public void setTrailers(NVPair[] trailers) 253 { 254 if (trailers != null) 255 this.trailers = trailers; 256 else 257 this.trailers = empty; 258 } 259 260 261 269 public void write(int b) throws IOException , IllegalAccessError 270 { 271 byte[] tmp = { (byte) b }; 272 write(tmp, 0, 1); 273 } 274 275 276 290 public synchronized void write(byte[] buf, int off, int len) 291 throws IOException , IllegalAccessError 292 { 293 if (req == null) 294 throw new IllegalAccessError ("Stream not associated with a request"); 295 296 if (ignore) return; 297 298 if (length != -1 && rcvd+len > length) 299 { 300 IOException ioe = 301 new IOException ("Tried to write too many bytes (" + (rcvd+len) + 302 " > " + length + ")"); 303 req.getConnection().closeDemux(ioe, false); 304 req.getConnection().outputFinished(); 305 throw ioe; 306 } 307 308 try 309 { 310 if (bos != null) 311 bos.write(buf, off, len); 312 else if (length != -1) 313 os.write(buf, off, len); 314 else 315 os.write(Codecs.chunkedEncode(buf, off, len, null, false)); 316 } 317 catch (IOException ioe) 318 { 319 req.getConnection().closeDemux(ioe, true); 320 req.getConnection().outputFinished(); 321 throw ioe; 322 } 323 324 rcvd += len; 325 } 326 327 328 338 public synchronized void close() throws IOException , IllegalAccessError 339 { 340 if (req == null) 341 throw new IllegalAccessError ("Stream not associated with a request"); 342 343 if (ignore) return; 344 345 if (bos != null) 346 { 347 req.setData(bos.toByteArray()); 348 req.setStream(null); 349 350 if (trailers.length > 0) 351 { 352 NVPair[] hdrs = req.getHeaders(); 353 354 356 int len = hdrs.length; 357 for (int idx=0; idx<len; idx++) 358 { 359 if (hdrs[idx].getName().equalsIgnoreCase("Trailer")) 360 { 361 System.arraycopy(hdrs, idx+1, hdrs, idx, len-idx-1); 362 len--; 363 } 364 } 365 366 367 369 hdrs = Util.resizeArray(hdrs, len+trailers.length); 370 System.arraycopy(trailers, 0, hdrs, len, trailers.length); 371 372 req.setHeaders(hdrs); 373 } 374 375 if (DebugConn) System.err.println("OutS: Sending request"); 376 377 try 378 { resp = req.getConnection().sendRequest(req, con_to); } 379 catch (ModuleException me) 380 { throw new IOException (me.toString()); } 381 notify(); 382 } 383 else 384 { 385 if (rcvd < length) 386 { 387 IOException ioe = 388 new IOException ("Premature close: only " + rcvd + 389 " bytes written instead of the " + 390 "expected " + length); 391 req.getConnection().closeDemux(ioe, false); 392 req.getConnection().outputFinished(); 393 throw ioe; 394 } 395 396 try 397 { 398 if (length == -1) 399 { 400 if (DebugConn && trailers.length > 0) 401 { 402 System.err.println("OutS: Sending trailers:"); 403 for (int idx=0; idx<trailers.length; idx++) 404 System.err.println(" " + 405 trailers[idx].getName() + ": " + 406 trailers[idx].getValue()); 407 } 408 409 os.write(Codecs.chunkedEncode(null, 0, 0, trailers, true)); 410 } 411 412 os.flush(); 413 414 if (DebugConn) System.err.println("OutS: All data sent"); 415 } 416 catch (IOException ioe) 417 { 418 req.getConnection().closeDemux(ioe, true); 419 throw ioe; 420 } 421 finally 422 { 423 req.getConnection().outputFinished(); 424 } 425 } 426 } 427 428 429 434 public String toString() 435 { 436 return getClass().getName() + "[length=" + length + "]"; 437 } 438 } 439 440 | Popular Tags |