View Javadoc

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