1 /* 2 * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java,v 1.4 2004/05/17 21:46:03 olegk Exp $ 3 * $Revision: 480424 $ 4 * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $ 5 * 6 * ==================================================================== 7 * 8 * Licensed to the Apache Software Foundation (ASF) under one or more 9 * contributor license agreements. See the NOTICE file distributed with 10 * this work for additional information regarding copyright ownership. 11 * The ASF licenses this file to You under the Apache License, Version 2.0 12 * (the "License"); you may not use this file except in compliance with 13 * the License. You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 * ==================================================================== 23 * 24 * This software consists of voluntary contributions made by many 25 * individuals on behalf of the Apache Software Foundation. For more 26 * information on the Apache Software Foundation, please see 27 * <http://www.apache.org/>. 28 * 29 * [Additional notices, if required by prior licensing conditions] 30 * 31 */ 32 package org.apache.commons.httpclient.methods; 33 34 import java.io.ByteArrayOutputStream; 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.io.OutputStream; 38 39 import org.apache.commons.logging.Log; 40 import org.apache.commons.logging.LogFactory; 41 42 /** 43 * A RequestEntity that contains an InputStream. 44 * 45 * @since 3.0 46 */ 47 public class InputStreamRequestEntity implements RequestEntity { 48 49 /** 50 * The content length will be calculated automatically. This implies 51 * buffering of the content. 52 */ 53 public static final int CONTENT_LENGTH_AUTO = -2; 54 55 private static final Log LOG = LogFactory.getLog(InputStreamRequestEntity.class); 56 57 private long contentLength; 58 59 private InputStream content; 60 61 /** The buffered request body, if any. */ 62 private byte[] buffer = null; 63 64 /** The content type */ 65 private String contentType; 66 67 /** 68 * Creates a new InputStreamRequestEntity with the given content and a content type of 69 * {@link #CONTENT_LENGTH_AUTO}. 70 * @param content The content to set. 71 */ InputStreamRequestEntity(InputStream content)72 public InputStreamRequestEntity(InputStream content) { 73 this(content, null); 74 } 75 76 /** 77 * Creates a new InputStreamRequestEntity with the given content, content type, and a 78 * content length of {@link #CONTENT_LENGTH_AUTO}. 79 * @param content The content to set. 80 * @param contentType The type of the content, or <code>null</code>. 81 */ InputStreamRequestEntity(InputStream content, String contentType)82 public InputStreamRequestEntity(InputStream content, String contentType) { 83 this(content, CONTENT_LENGTH_AUTO, contentType); 84 } 85 86 /** 87 * Creates a new InputStreamRequestEntity with the given content and content length. 88 * @param content The content to set. 89 * @param contentLength The content size in bytes or a negative number if not known. 90 * If {@link #CONTENT_LENGTH_AUTO} is given the content will be buffered in order to 91 * determine its size when {@link #getContentLength()} is called. 92 */ InputStreamRequestEntity(InputStream content, long contentLength)93 public InputStreamRequestEntity(InputStream content, long contentLength) { 94 this(content, contentLength, null); 95 } 96 97 /** 98 * Creates a new InputStreamRequestEntity with the given content, content length, and 99 * content type. 100 * @param content The content to set. 101 * @param contentLength The content size in bytes or a negative number if not known. 102 * If {@link #CONTENT_LENGTH_AUTO} is given the content will be buffered in order to 103 * determine its size when {@link #getContentLength()} is called. 104 * @param contentType The type of the content, or <code>null</code>. 105 */ InputStreamRequestEntity(InputStream content, long contentLength, String contentType)106 public InputStreamRequestEntity(InputStream content, long contentLength, String contentType) { 107 if (content == null) { 108 throw new IllegalArgumentException("The content cannot be null"); 109 } 110 this.content = content; 111 this.contentLength = contentLength; 112 this.contentType = contentType; 113 } 114 115 /* (non-Javadoc) 116 * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType() 117 */ getContentType()118 public String getContentType() { 119 return contentType; 120 } 121 122 /** 123 * Buffers request body input stream. 124 */ bufferContent()125 private void bufferContent() { 126 127 if (this.buffer != null) { 128 // Already been buffered 129 return; 130 } 131 if (this.content != null) { 132 try { 133 ByteArrayOutputStream tmp = new ByteArrayOutputStream(); 134 byte[] data = new byte[4096]; 135 int l = 0; 136 while ((l = this.content.read(data)) >= 0) { 137 tmp.write(data, 0, l); 138 } 139 this.buffer = tmp.toByteArray(); 140 this.content = null; 141 this.contentLength = buffer.length; 142 } catch (IOException e) { 143 LOG.error(e.getMessage(), e); 144 this.buffer = null; 145 this.content = null; 146 this.contentLength = 0; 147 } 148 } 149 } 150 151 /** 152 * Tests if this method is repeatable. Only <code>true</code> if the content has been 153 * buffered. 154 * 155 * @see #getContentLength() 156 */ isRepeatable()157 public boolean isRepeatable() { 158 return buffer != null; 159 } 160 161 /* (non-Javadoc) 162 * @see org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream) 163 */ writeRequest(OutputStream out)164 public void writeRequest(OutputStream out) throws IOException { 165 166 if (content != null) { 167 byte[] tmp = new byte[4096]; 168 int total = 0; 169 int i = 0; 170 while ((i = content.read(tmp)) >= 0) { 171 out.write(tmp, 0, i); 172 total += i; 173 } 174 } else if (buffer != null) { 175 out.write(buffer); 176 } else { 177 throw new IllegalStateException("Content must be set before entity is written"); 178 } 179 } 180 181 /** 182 * Gets the content length. If the content length has not been set, the content will be 183 * buffered to determine the actual content length. 184 */ getContentLength()185 public long getContentLength() { 186 if (contentLength == CONTENT_LENGTH_AUTO && buffer == null) { 187 bufferContent(); 188 } 189 return contentLength; 190 } 191 192 /** 193 * @return Returns the content. 194 */ getContent()195 public InputStream getContent() { 196 return content; 197 } 198 199 } 200