1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
27
28 package org.apache.http.entity;
29
30 import java.io.ByteArrayInputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.OutputStream;
34
35 import org.apache.http.HttpEntity;
36 import org.apache.http.annotation.NotThreadSafe;
37 import org.apache.http.util.Args;
38 import org.apache.http.util.EntityUtils;
39
40 /**
41 * A wrapping entity that buffers it content if necessary.
42 * The buffered entity is always repeatable.
43 * If the wrapped entity is repeatable itself, calls are passed through.
44 * If the wrapped entity is not repeatable, the content is read into a
45 * buffer once and provided from there as often as required.
46 *
47 * @since 4.0
48 */
49 @NotThreadSafe
50 public class BufferedHttpEntity extends HttpEntityWrapper {
51
52 private final byte[] buffer;
53
54 /**
55 * Creates a new buffered entity wrapper.
56 *
57 * @param entity the entity to wrap, not null
58 * @throws IllegalArgumentException if wrapped is null
59 */
60 public BufferedHttpEntity(final HttpEntity entity) throws IOException {
61 super(entity);
62 if (!entity.isRepeatable() || entity.getContentLength() < 0) {
63 this.buffer = EntityUtils.toByteArray(entity);
64 } else {
65 this.buffer = null;
66 }
67 }
68
69 @Override
70 public long getContentLength() {
71 if (this.buffer != null) {
72 return this.buffer.length;
73 } else {
74 return wrappedEntity.getContentLength();
75 }
76 }
77
78 @Override
79 public InputStream getContent() throws IOException {
80 if (this.buffer != null) {
81 return new ByteArrayInputStream(this.buffer);
82 } else {
83 return wrappedEntity.getContent();
84 }
85 }
86
87 /**
88 * Tells that this entity does not have to be chunked.
89 *
90 * @return <code>false</code>
91 */
92 @Override
93 public boolean isChunked() {
94 return (buffer == null) && wrappedEntity.isChunked();
95 }
96
97 /**
98 * Tells that this entity is repeatable.
99 *
100 * @return <code>true</code>
101 */
102 @Override
103 public boolean isRepeatable() {
104 return true;
105 }
106
107
108 @Override
109 public void writeTo(final OutputStream outstream) throws IOException {
110 Args.notNull(outstream, "Output stream");
111 if (this.buffer != null) {
112 outstream.write(this.buffer);
113 } else {
114 wrappedEntity.writeTo(outstream);
115 }
116 }
117
118
119 // non-javadoc, see interface HttpEntity
120 @Override
121 public boolean isStreaming() {
122 return (buffer == null) && wrappedEntity.isStreaming();
123 }
124
125 } // class BufferedHttpEntity