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.nio.entity; 029 030import java.io.IOException; 031import java.io.InputStream; 032import java.nio.ByteBuffer; 033import java.nio.channels.Channels; 034import java.nio.channels.ReadableByteChannel; 035 036import org.apache.http.HttpEntity; 037import org.apache.http.nio.ContentEncoder; 038import org.apache.http.nio.IOControl; 039import org.apache.http.util.Args; 040 041/** 042 * Basic implementation of {@link HttpAsyncContentProducer} that relies on 043 * inefficient and potentially blocking I/O operation redirection through 044 * {@link Channels#newChannel(java.io.InputStream)}. 045 * 046 * @since 4.2 047 */ 048public class EntityAsyncContentProducer implements HttpAsyncContentProducer { 049 050 private final HttpEntity entity; 051 private final ByteBuffer buffer; 052 private ReadableByteChannel channel; 053 054 public EntityAsyncContentProducer(final HttpEntity entity) { 055 super(); 056 Args.notNull(entity, "HTTP entity"); 057 this.entity = entity; 058 this.buffer = ByteBuffer.allocate(4096); 059 } 060 061 @Override 062 public void produceContent( 063 final ContentEncoder encoder, final IOControl ioctrl) throws IOException { 064 if (this.channel == null) { 065 this.channel = Channels.newChannel(this.entity.getContent()); 066 } 067 final int i = this.channel.read(this.buffer); 068 this.buffer.flip(); 069 encoder.write(this.buffer); 070 final boolean buffering = this.buffer.hasRemaining(); 071 this.buffer.compact(); 072 if (i == -1 && !buffering) { 073 encoder.complete(); 074 close(); 075 } 076 } 077 078 @Override 079 public boolean isRepeatable() { 080 return this.entity.isRepeatable(); 081 } 082 083 @Override 084 public void close() throws IOException { 085 final ReadableByteChannel local = this.channel; 086 this.channel = null; 087 if (local != null) { 088 local.close(); 089 } 090 if (this.entity.isStreaming()) { 091 final InputStream instream = this.entity.getContent(); 092 instream.close(); 093 } 094 } 095 096 @Override 097 public String toString() { 098 return this.entity.toString(); 099 } 100 101}