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.nio.protocol; 028 029import java.io.IOException; 030 031import org.apache.http.HttpEntity; 032import org.apache.http.HttpEntityEnclosingRequest; 033import org.apache.http.HttpHost; 034import org.apache.http.HttpRequest; 035import org.apache.http.nio.ContentEncoder; 036import org.apache.http.nio.IOControl; 037import org.apache.http.nio.entity.EntityAsyncContentProducer; 038import org.apache.http.nio.entity.HttpAsyncContentProducer; 039import org.apache.http.protocol.HttpContext; 040import org.apache.http.util.Args; 041 042/** 043 * Basic implementation of {@link HttpAsyncRequestProducer}. The producer 044 * can make use of the {@link HttpAsyncContentProducer} interface to 045 * efficiently stream out message content to the underlying non-blocking HTTP 046 * connection, if it is implemented by the enclosed {@link HttpEntity}. 047 * 048 * @see HttpAsyncContentProducer 049 * 050 * @since 4.2 051 */ 052public class BasicAsyncRequestProducer implements HttpAsyncRequestProducer { 053 054 private final HttpHost target; 055 private final HttpRequest request; 056 private final HttpAsyncContentProducer producer; 057 058 /** 059 * Creates a producer that can be used to transmit the given request 060 * message. The given content producer will be used to stream out message 061 * content. Please note that the request message is expected to enclose 062 * an {@link HttpEntity} whose properties are consistent with the behavior 063 * of the content producer. 064 * 065 * @param target target host. 066 * @param request request message. 067 * @param producer request content producer. 068 */ 069 protected BasicAsyncRequestProducer( 070 final HttpHost target, 071 final HttpEntityEnclosingRequest request, 072 final HttpAsyncContentProducer producer) { 073 super(); 074 Args.notNull(target, "HTTP host"); 075 Args.notNull(request, "HTTP request"); 076 Args.notNull(producer, "HTTP content producer"); 077 this.target = target; 078 this.request = request; 079 this.producer = producer; 080 } 081 082 /** 083 * Creates a producer that can be used to transmit the given request 084 * message. If the request message encloses an {@link HttpEntity} 085 * it is also expected to implement {@link HttpAsyncContentProducer}. 086 * 087 * @param target target host. 088 * @param request request message. 089 */ 090 public BasicAsyncRequestProducer(final HttpHost target, final HttpRequest request) { 091 Args.notNull(target, "HTTP host"); 092 Args.notNull(request, "HTTP request"); 093 this.target = target; 094 this.request = request; 095 if (request instanceof HttpEntityEnclosingRequest) { 096 final HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity(); 097 if (entity != null) { 098 if (entity instanceof HttpAsyncContentProducer) { 099 this.producer = (HttpAsyncContentProducer) entity; 100 } else { 101 this.producer = new EntityAsyncContentProducer(entity); 102 } 103 } else { 104 this.producer = null; 105 } 106 } else { 107 this.producer = null; 108 } 109 } 110 111 @Override 112 public HttpRequest generateRequest() { 113 return this.request; 114 } 115 116 @Override 117 public HttpHost getTarget() { 118 return this.target; 119 } 120 121 @Override 122 public void produceContent( 123 final ContentEncoder encoder, final IOControl ioctrl) throws IOException { 124 if (this.producer != null) { 125 this.producer.produceContent(encoder, ioctrl); 126 if (encoder.isCompleted()) { 127 this.producer.close(); 128 } 129 } 130 } 131 132 @Override 133 public void requestCompleted(final HttpContext context) { 134 } 135 136 @Override 137 public void failed(final Exception ex) { 138 } 139 140 @Override 141 public boolean isRepeatable() { 142 return this.producer == null || this.producer.isRepeatable(); 143 } 144 145 @Override 146 public void resetRequest() throws IOException { 147 if (this.producer != null) { 148 this.producer.close(); 149 } 150 } 151 152 @Override 153 public void close() throws IOException { 154 if (this.producer != null) { 155 this.producer.close(); 156 } 157 } 158 159 @Override 160 public String toString() { 161 final StringBuilder sb = new StringBuilder(); 162 sb.append(this.target); 163 sb.append(' '); 164 sb.append(this.request); 165 if (this.producer != null) { 166 sb.append(' '); 167 sb.append(this.producer); 168 } 169 return sb.toString(); 170 } 171 172}