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 */ 027package org.apache.http.client.entity; 028 029import java.io.IOException; 030import java.io.InputStream; 031import java.io.OutputStream; 032 033import org.apache.http.Header; 034import org.apache.http.HttpEntity; 035import org.apache.http.entity.HttpEntityWrapper; 036import org.apache.http.util.Args; 037 038/** 039 * Common base class for decompressing {@link HttpEntity} implementations. 040 * 041 * @since 4.4 042 */ 043public class DecompressingEntity extends HttpEntityWrapper { 044 045 /** 046 * Default buffer size. 047 */ 048 private static final int BUFFER_SIZE = 1024 * 2; 049 050 private final InputStreamFactory inputStreamFactory; 051 /** 052 * {@link #getContent()} method must return the same {@link InputStream} 053 * instance when DecompressingEntity is wrapping a streaming entity. 054 */ 055 private InputStream content; 056 057 /** 058 * Creates a new {@link DecompressingEntity}. 059 * 060 * @param wrapped the non-null {@link HttpEntity} to be wrapped 061 * @param inputStreamFactory factory to create decompressing stream. 062 */ 063 public DecompressingEntity( 064 final HttpEntity wrapped, 065 final InputStreamFactory inputStreamFactory) { 066 super(wrapped); 067 this.inputStreamFactory = inputStreamFactory; 068 } 069 070 private InputStream getDecompressingStream() throws IOException { 071 final InputStream in = wrappedEntity.getContent(); 072 return new LazyDecompressingInputStream(in, inputStreamFactory); 073 } 074 075 @Override 076 public InputStream getContent() throws IOException { 077 if (wrappedEntity.isStreaming()) { 078 if (content == null) { 079 content = getDecompressingStream(); 080 } 081 return content; 082 } else { 083 return getDecompressingStream(); 084 } 085 } 086 087 @Override 088 public void writeTo(final OutputStream outstream) throws IOException { 089 Args.notNull(outstream, "Output stream"); 090 final InputStream instream = getContent(); 091 try { 092 final byte[] buffer = new byte[BUFFER_SIZE]; 093 int l; 094 while ((l = instream.read(buffer)) != -1) { 095 outstream.write(buffer, 0, l); 096 } 097 } finally { 098 instream.close(); 099 } 100 } 101 102 @Override 103 public Header getContentEncoding() { 104 /* Content encoding is now 'identity' */ 105 return null; 106 } 107 108 @Override 109 public long getContentLength() { 110 /* length of decompressed content is not known */ 111 return -1; 112 } 113 114}