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 package org.apache.http.nio.protocol;
28
29 import java.io.IOException;
30
31 import org.apache.http.HttpEntity;
32 import org.apache.http.HttpEntityEnclosingRequest;
33 import org.apache.http.HttpHost;
34 import org.apache.http.HttpRequest;
35 import org.apache.http.annotation.ThreadSafe;
36 import org.apache.http.nio.ContentEncoder;
37 import org.apache.http.nio.IOControl;
38 import org.apache.http.nio.entity.EntityAsyncContentProducer;
39 import org.apache.http.nio.entity.HttpAsyncContentProducer;
40 import org.apache.http.protocol.HttpContext;
41 import org.apache.http.util.Args;
42
43 /**
44 * Basic implementation of {@link HttpAsyncRequestProducer}. The producer
45 * can make use of the {@link HttpAsyncContentProducer} interface to
46 * efficiently stream out message content to the underlying non-blocking HTTP
47 * connection, if it is implemented by the enclosed {@link HttpEntity}.
48 *
49 * @see HttpAsyncContentProducer
50 *
51 * @since 4.2
52 */
53 @ThreadSafe
54 public class BasicAsyncRequestProducer implements HttpAsyncRequestProducer {
55
56 private final HttpHost target;
57 private final HttpRequest request;
58 private final HttpAsyncContentProducer producer;
59
60 /**
61 * Creates a producer that can be used to transmit the given request
62 * message. The given content producer will be used to stream out message
63 * content. Please note that the request message is expected to enclose
64 * an {@link HttpEntity} whose properties are consistent with the behavior
65 * of the content producer.
66 *
67 * @param target target host.
68 * @param request request message.
69 * @param producer request content producer.
70 */
71 protected BasicAsyncRequestProducer(
72 final HttpHost target,
73 final HttpEntityEnclosingRequest request,
74 final HttpAsyncContentProducer producer) {
75 super();
76 Args.notNull(target, "HTTP host");
77 Args.notNull(request, "HTTP request");
78 Args.notNull(producer, "HTTP content producer");
79 this.target = target;
80 this.request = request;
81 this.producer = producer;
82 }
83
84 /**
85 * Creates a producer that can be used to transmit the given request
86 * message. If the request message encloses an {@link HttpEntity}
87 * it is also expected to implement {@link HttpAsyncContentProducer}.
88 *
89 * @param target target host.
90 * @param request request message.
91 */
92 public BasicAsyncRequestProducer(final HttpHost target, final HttpRequest request) {
93 Args.notNull(target, "HTTP host");
94 Args.notNull(request, "HTTP request");
95 this.target = target;
96 this.request = request;
97 if (request instanceof HttpEntityEnclosingRequest) {
98 final HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
99 if (entity != null) {
100 if (entity instanceof HttpAsyncContentProducer) {
101 this.producer = (HttpAsyncContentProducer) entity;
102 } else {
103 this.producer = new EntityAsyncContentProducer(entity);
104 }
105 } else {
106 this.producer = null;
107 }
108 } else {
109 this.producer = null;
110 }
111 }
112
113 public synchronized HttpRequest generateRequest() {
114 return this.request;
115 }
116
117 public HttpHost getTarget() {
118 return this.target;
119 }
120
121 public synchronized void produceContent(
122 final ContentEncoder encoder, final IOControl ioctrl) throws IOException {
123 if (this.producer != null) {
124 this.producer.produceContent(encoder, ioctrl);
125 if (encoder.isCompleted()) {
126 this.producer.close();
127 }
128 }
129 }
130
131 public void requestCompleted(final HttpContext context) {
132 }
133
134 public void failed(final Exception ex) {
135 }
136
137 public synchronized boolean isRepeatable() {
138 return this.producer == null || this.producer.isRepeatable();
139 }
140
141 public synchronized void resetRequest() throws IOException {
142 if (this.producer != null) {
143 this.producer.close();
144 }
145 }
146
147 public synchronized void close() throws IOException {
148 if (this.producer != null) {
149 this.producer.close();
150 }
151 }
152
153 }