001/* 002 * ==================================================================== 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 * ==================================================================== 020 * 021 * This software consists of voluntary contributions made by many 022 * individuals on behalf of the Apache Software Foundation. For more 023 * information on the Apache Software Foundation, please see 024 * <http://www.apache.org/>. 025 * 026 */ 027 028package org.apache.http.entity; 029 030import java.io.ByteArrayInputStream; 031import java.io.ByteArrayOutputStream; 032import java.io.IOException; 033import java.io.InputStream; 034import java.io.OutputStream; 035 036import org.apache.http.HttpEntity; 037import org.apache.http.util.Args; 038 039/** 040 * A wrapping entity that buffers it content if necessary. 041 * The buffered entity is always repeatable. 042 * If the wrapped entity is repeatable itself, calls are passed through. 043 * If the wrapped entity is not repeatable, the content is read into a 044 * buffer once and provided from there as often as required. 045 * 046 * @since 4.0 047 */ 048public class BufferedHttpEntity extends HttpEntityWrapper { 049 050 private final byte[] buffer; 051 052 /** 053 * Creates a new buffered entity wrapper. 054 * 055 * @param entity the entity to wrap, not null 056 * @throws IllegalArgumentException if wrapped is null 057 */ 058 public BufferedHttpEntity(final HttpEntity entity) throws IOException { 059 super(entity); 060 if (!entity.isRepeatable() || entity.getContentLength() < 0) { 061 final ByteArrayOutputStream out = new ByteArrayOutputStream(); 062 entity.writeTo(out); 063 out.flush(); 064 this.buffer = out.toByteArray(); 065 } else { 066 this.buffer = null; 067 } 068 } 069 070 @Override 071 public long getContentLength() { 072 if (this.buffer != null) { 073 return this.buffer.length; 074 } else { 075 return super.getContentLength(); 076 } 077 } 078 079 @Override 080 public InputStream getContent() throws IOException { 081 if (this.buffer != null) { 082 return new ByteArrayInputStream(this.buffer); 083 } else { 084 return super.getContent(); 085 } 086 } 087 088 /** 089 * Tells that this entity does not have to be chunked. 090 * 091 * @return {@code false} 092 */ 093 @Override 094 public boolean isChunked() { 095 return (buffer == null) && super.isChunked(); 096 } 097 098 /** 099 * Tells that this entity is repeatable. 100 * 101 * @return {@code true} 102 */ 103 @Override 104 public boolean isRepeatable() { 105 return true; 106 } 107 108 109 @Override 110 public void writeTo(final OutputStream outstream) throws IOException { 111 Args.notNull(outstream, "Output stream"); 112 if (this.buffer != null) { 113 outstream.write(this.buffer); 114 } else { 115 super.writeTo(outstream); 116 } 117 } 118 119 120 // non-javadoc, see interface HttpEntity 121 @Override 122 public boolean isStreaming() { 123 return (buffer == null) && super.isStreaming(); 124 } 125 126} // class BufferedHttpEntity