1 31 32 package org.apache.commons.httpclient.methods; 33 34 import java.io.ByteArrayInputStream ; 35 import java.io.ByteArrayOutputStream ; 36 import java.io.IOException ; 37 import java.io.InputStream ; 38 import java.io.OutputStream ; 39 40 import org.apache.commons.httpclient.ChunkedOutputStream; 41 import org.apache.commons.httpclient.ContentLengthInputStream; 42 import org.apache.commons.httpclient.HttpConnection; 43 import org.apache.commons.httpclient.HttpConstants; 44 import org.apache.commons.httpclient.HttpException; 45 import org.apache.commons.httpclient.HttpState; 46 import org.apache.commons.logging.Log; 47 import org.apache.commons.logging.LogFactory; 48 49 59 public abstract class EntityEnclosingMethod extends ExpectContinueMethod { 60 61 63 67 public static final int CONTENT_LENGTH_AUTO = -2; 68 69 73 public static final int CONTENT_LENGTH_CHUNKED = -1; 74 75 76 private static final Log LOG = LogFactory.getLog(EntityEnclosingMethod.class); 77 78 79 private byte[] buffer = null; 80 81 82 private InputStream requestStream = null; 83 84 85 private String requestString = null; 86 87 90 private byte[] contentCache = null; 91 92 93 private int repeatCount = 0; 94 95 98 private int requestContentLength = CONTENT_LENGTH_AUTO; 99 100 102 107 public EntityEnclosingMethod() { 108 super(); 109 setFollowRedirects(false); 110 } 111 112 119 public EntityEnclosingMethod(String uri) { 120 super(uri); 121 setFollowRedirects(false); 122 } 123 124 133 public EntityEnclosingMethod(String uri, String tempDir) { 134 super(uri, tempDir); 135 setFollowRedirects(false); 136 } 137 138 148 public EntityEnclosingMethod(String uri, String tempDir, String tempFile) { 149 super(uri, tempDir, tempFile); 150 setFollowRedirects(false); 151 } 152 153 164 protected boolean hasRequestContent() { 165 LOG.trace("enter EntityEnclosingMethod.hasRequestContent()"); 166 return (this.buffer != null) 167 || (this.requestStream != null) 168 || (this.requestString != null); 169 } 170 171 179 protected void clearRequestBody() { 180 LOG.trace("enter EntityEnclosingMethod.clearRequestBody()"); 181 this.requestStream = null; 182 this.requestString = null; 183 this.buffer = null; 184 this.contentCache = null; 185 } 186 187 198 protected byte[] generateRequestBody() { 199 LOG.trace("enter EntityEnclosingMethod.renerateRequestBody()"); 200 if (this.requestStream != null) { 201 bufferContent(); 202 } 203 204 if (this.buffer != null) { 205 return this.buffer; 206 } else if (this.requestString != null) { 207 return HttpConstants.getContentBytes(this.requestString, getRequestCharSet()); 208 } else { 209 return null; 210 } 211 } 212 213 221 public boolean getFollowRedirects() { 222 return false; 223 } 224 225 226 232 public void setFollowRedirects(boolean followRedirects) { 233 if (followRedirects == true) { 234 } 239 super.setFollowRedirects(false); 240 } 241 242 262 public void setRequestContentLength(int length) { 263 LOG.trace("enter EntityEnclosingMethod.setRequestContentLength(int)"); 264 this.requestContentLength = length; 265 } 266 267 273 protected int getRequestContentLength() { 274 LOG.trace("enter EntityEnclosingMethod.getRequestContentLength()"); 275 276 if (!hasRequestContent()) { 277 return 0; 278 } 279 if (this.requestContentLength != CONTENT_LENGTH_AUTO) { 280 return this.requestContentLength; 281 } 282 if (this.contentCache == null) { 283 this.contentCache = generateRequestBody(); 284 } 285 return (this.contentCache == null) ? 0 : this.contentCache.length; 286 } 287 288 303 protected void addContentLengthRequestHeader(HttpState state, 304 HttpConnection conn) 305 throws IOException , HttpException { 306 LOG.trace("enter HttpMethodBase.addContentLengthRequestHeader(" 307 + "HttpState, HttpConnection)"); 308 309 if ((getRequestHeader("content-length") == null) 310 && (getRequestHeader("Transfer-Encoding") == null)) { 311 int len = getRequestContentLength(); 312 if (len >= 0) { 313 addRequestHeader("Content-Length", String.valueOf(len)); 314 } else if ((len == CONTENT_LENGTH_CHUNKED) && (isHttp11())) { 315 addRequestHeader("Transfer-Encoding", "chunked"); 316 } 317 } 318 } 319 320 325 public void setRequestBody(InputStream body) { 326 LOG.trace("enter EntityEnclosingMethod.setRequestBody(InputStream)"); 327 clearRequestBody(); 328 this.requestStream = body; 329 } 330 331 337 public InputStream getRequestBody() { 338 LOG.trace("enter EntityEnclosingMethod.getRequestBody()"); 339 byte [] content = generateRequestBody(); 340 if (content != null) { 341 return new ByteArrayInputStream (content); 342 } else { 343 return new ByteArrayInputStream (new byte[] {}); 344 } 345 } 346 347 359 public void setRequestBody(String body) { 360 LOG.trace("enter EntityEnclosingMethod.setRequestBody(String)"); 361 clearRequestBody(); 362 this.requestString = body; 363 } 364 365 373 public String getRequestBodyAsString() throws IOException { 374 LOG.trace("enter EntityEnclosingMethod.getRequestBodyAsString()"); 375 byte [] content = generateRequestBody(); 376 if (content != null) { 377 return HttpConstants.getContentString(content, getRequestCharSet()); 378 } else { 379 return null; 380 } 381 } 382 383 384 399 protected boolean writeRequestBody(HttpState state, HttpConnection conn) 400 throws IOException , HttpException { 401 LOG.trace( 402 "enter EntityEnclosingMethod.writeRequestBody(HttpState, HttpConnection)"); 403 404 if (!hasRequestContent()) { 405 LOG.debug("Request body has not been specified"); 406 return true; 407 } 408 409 int contentLength = getRequestContentLength(); 410 411 if ((contentLength == CONTENT_LENGTH_CHUNKED) && !isHttp11()) { 412 throw new HttpException( 413 "Chunked transfer encoding not allowed for HTTP/1.0"); 414 } 415 416 InputStream instream = null; 417 if (this.requestStream != null) { 418 LOG.debug("Using unbuffered request body"); 419 instream = this.requestStream; 420 } else { 421 if (this.contentCache == null) { 422 this.contentCache = generateRequestBody(); 423 } 424 if (this.contentCache != null) { 425 LOG.debug("Using buffered request body"); 426 instream = new ByteArrayInputStream (this.contentCache); 427 } 428 } 429 430 if (instream == null) { 431 LOG.debug("Request body is empty"); 432 return true; 433 } 434 435 if ((this.repeatCount > 0) && (this.contentCache == null)) { 436 throw new HttpException( 437 "Unbuffered entity enclosing request can not be repeated."); 438 } 439 440 this.repeatCount++; 441 442 OutputStream outstream = conn.getRequestOutputStream(); 443 444 if (contentLength == CONTENT_LENGTH_CHUNKED) { 445 outstream = new ChunkedOutputStream(outstream); 446 } 447 if (contentLength >= 0) { 448 instream = new ContentLengthInputStream(instream, contentLength); 451 } 452 453 byte[] tmp = new byte[4096]; 454 int total = 0; 455 int i = 0; 456 while ((i = instream.read(tmp)) >= 0) { 457 outstream.write(tmp, 0, i); 458 total += i; 459 } 460 if (outstream instanceof ChunkedOutputStream) { 462 ((ChunkedOutputStream) outstream).writeClosingChunk(); 463 } 464 if ((contentLength > 0) && (total < contentLength)) { 465 throw new IOException ("Unexpected end of input stream after " 466 + total + " bytes (expected " + contentLength + " bytes)"); 467 } 468 LOG.debug("Request body sent"); 469 return true; 470 } 471 472 483 public void recycle() { 484 LOG.trace("enter EntityEnclosingMethod.recycle()"); 485 clearRequestBody(); 486 this.requestContentLength = CONTENT_LENGTH_AUTO; 487 this.repeatCount = 0; 488 super.recycle(); 489 } 490 491 494 private void bufferContent() { 495 LOG.trace("enter EntityEnclosingMethod.bufferContent()"); 496 497 if (this.buffer != null) { 498 return; 500 } 501 if (this.requestStream != null) { 502 try { 503 ByteArrayOutputStream tmp = new ByteArrayOutputStream (); 504 byte[] data = new byte[4096]; 505 int l = 0; 506 while ((l = this.requestStream.read(data)) >= 0) { 507 tmp.write(data, 0, l); 508 } 509 this.buffer = tmp.toByteArray(); 510 this.requestStream = null; 511 } catch (IOException e) { 512 LOG.error(e.getMessage(), e); 513 this.buffer = null; 514 this.requestStream = null; 515 } 516 } 517 } 518 } 519 | Popular Tags |