001: /*
002: * $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 $
003: * $Revision: 480424 $
004: * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
005: *
006: * ====================================================================
007: *
008: * Licensed to the Apache Software Foundation (ASF) under one or more
009: * contributor license agreements. See the NOTICE file distributed with
010: * this work for additional information regarding copyright ownership.
011: * The ASF licenses this file to You under the Apache License, Version 2.0
012: * (the "License"); you may not use this file except in compliance with
013: * the License. You may obtain a copy of the License at
014: *
015: * http://www.apache.org/licenses/LICENSE-2.0
016: *
017: * Unless required by applicable law or agreed to in writing, software
018: * distributed under the License is distributed on an "AS IS" BASIS,
019: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
020: * See the License for the specific language governing permissions and
021: * limitations under the License.
022: * ====================================================================
023: *
024: * This software consists of voluntary contributions made by many
025: * individuals on behalf of the Apache Software Foundation. For more
026: * information on the Apache Software Foundation, please see
027: * <http://www.apache.org/>.
028: *
029: * [Additional notices, if required by prior licensing conditions]
030: *
031: */
032: package org.apache.commons.httpclient.methods;
033:
034: import java.io.ByteArrayOutputStream;
035: import java.io.IOException;
036: import java.io.InputStream;
037: import java.io.OutputStream;
038:
039: import org.apache.commons.logging.Log;
040: import org.apache.commons.logging.LogFactory;
041:
042: /**
043: * A RequestEntity that contains an InputStream.
044: *
045: * @since 3.0
046: */
047: public class InputStreamRequestEntity implements RequestEntity {
048:
049: /**
050: * The content length will be calculated automatically. This implies
051: * buffering of the content.
052: */
053: public static final int CONTENT_LENGTH_AUTO = -2;
054:
055: private static final Log LOG = LogFactory
056: .getLog(InputStreamRequestEntity.class);
057:
058: private long contentLength;
059:
060: private InputStream content;
061:
062: /** The buffered request body, if any. */
063: private byte[] buffer = null;
064:
065: /** The content type */
066: private String contentType;
067:
068: /**
069: * Creates a new InputStreamRequestEntity with the given content and a content type of
070: * {@link #CONTENT_LENGTH_AUTO}.
071: * @param content The content to set.
072: */
073: public InputStreamRequestEntity(InputStream content) {
074: this (content, null);
075: }
076:
077: /**
078: * Creates a new InputStreamRequestEntity with the given content, content type, and a
079: * content length of {@link #CONTENT_LENGTH_AUTO}.
080: * @param content The content to set.
081: * @param contentType The type of the content, or <code>null</code>.
082: */
083: public InputStreamRequestEntity(InputStream content,
084: String contentType) {
085: this (content, CONTENT_LENGTH_AUTO, contentType);
086: }
087:
088: /**
089: * Creates a new InputStreamRequestEntity with the given content and content length.
090: * @param content The content to set.
091: * @param contentLength The content size in bytes or a negative number if not known.
092: * If {@link #CONTENT_LENGTH_AUTO} is given the content will be buffered in order to
093: * determine its size when {@link #getContentLength()} is called.
094: */
095: public InputStreamRequestEntity(InputStream content,
096: long contentLength) {
097: this (content, contentLength, null);
098: }
099:
100: /**
101: * Creates a new InputStreamRequestEntity with the given content, content length, and
102: * content type.
103: * @param content The content to set.
104: * @param contentLength The content size in bytes or a negative number if not known.
105: * If {@link #CONTENT_LENGTH_AUTO} is given the content will be buffered in order to
106: * determine its size when {@link #getContentLength()} is called.
107: * @param contentType The type of the content, or <code>null</code>.
108: */
109: public InputStreamRequestEntity(InputStream content,
110: long contentLength, String contentType) {
111: if (content == null) {
112: throw new IllegalArgumentException(
113: "The content cannot be null");
114: }
115: this .content = content;
116: this .contentLength = contentLength;
117: this .contentType = contentType;
118: }
119:
120: /* (non-Javadoc)
121: * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
122: */
123: public String getContentType() {
124: return contentType;
125: }
126:
127: /**
128: * Buffers request body input stream.
129: */
130: private void bufferContent() {
131:
132: if (this .buffer != null) {
133: // Already been buffered
134: return;
135: }
136: if (this .content != null) {
137: try {
138: ByteArrayOutputStream tmp = new ByteArrayOutputStream();
139: byte[] data = new byte[4096];
140: int l = 0;
141: while ((l = this .content.read(data)) >= 0) {
142: tmp.write(data, 0, l);
143: }
144: this .buffer = tmp.toByteArray();
145: this .content = null;
146: this .contentLength = buffer.length;
147: } catch (IOException e) {
148: LOG.error(e.getMessage(), e);
149: this .buffer = null;
150: this .content = null;
151: this .contentLength = 0;
152: }
153: }
154: }
155:
156: /**
157: * Tests if this method is repeatable. Only <code>true</code> if the content has been
158: * buffered.
159: *
160: * @see #getContentLength()
161: */
162: public boolean isRepeatable() {
163: return buffer != null;
164: }
165:
166: /* (non-Javadoc)
167: * @see org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream)
168: */
169: public void writeRequest(OutputStream out) throws IOException {
170:
171: if (content != null) {
172: byte[] tmp = new byte[4096];
173: int total = 0;
174: int i = 0;
175: while ((i = content.read(tmp)) >= 0) {
176: out.write(tmp, 0, i);
177: total += i;
178: }
179: } else if (buffer != null) {
180: out.write(buffer);
181: } else {
182: throw new IllegalStateException(
183: "Content must be set before entity is written");
184: }
185: }
186:
187: /**
188: * Gets the content length. If the content length has not been set, the content will be
189: * buffered to determine the actual content length.
190: */
191: public long getContentLength() {
192: if (contentLength == CONTENT_LENGTH_AUTO && buffer == null) {
193: bufferContent();
194: }
195: return contentLength;
196: }
197:
198: /**
199: * @return Returns the content.
200: */
201: public InputStream getContent() {
202: return content;
203: }
204:
205: }
|