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  
28  package org.apache.hc.client5.http.impl.io;
29  
30  import java.io.IOException;
31  import java.net.Socket;
32  import java.nio.charset.Charset;
33  import java.nio.charset.CharsetDecoder;
34  import java.nio.charset.CharsetEncoder;
35  import java.nio.charset.CodingErrorAction;
36  import java.util.concurrent.atomic.AtomicLong;
37  
38  import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
39  import org.apache.hc.core5.annotation.Contract;
40  import org.apache.hc.core5.annotation.ThreadingBehavior;
41  import org.apache.hc.core5.http.ClassicHttpRequest;
42  import org.apache.hc.core5.http.ClassicHttpResponse;
43  import org.apache.hc.core5.http.ContentLengthStrategy;
44  import org.apache.hc.core5.http.config.CharCodingConfig;
45  import org.apache.hc.core5.http.config.Http1Config;
46  import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
47  import org.apache.hc.core5.http.impl.io.DefaultHttpRequestWriterFactory;
48  import org.apache.hc.core5.http.impl.io.NoResponseOutOfOrderStrategy;
49  import org.apache.hc.core5.http.io.HttpConnectionFactory;
50  import org.apache.hc.core5.http.io.HttpMessageParserFactory;
51  import org.apache.hc.core5.http.io.HttpMessageWriterFactory;
52  import org.apache.hc.core5.http.io.ResponseOutOfOrderStrategy;
53  
54  /**
55   * Factory for {@link ManagedHttpClientConnection} instances.
56   * @since 4.3
57   */
58  @Contract(threading = ThreadingBehavior.STATELESS)
59  public class ManagedHttpClientConnectionFactory implements HttpConnectionFactory<ManagedHttpClientConnection> {
60  
61      private static final AtomicLong COUNTER = new AtomicLong();
62  
63      public static final ManagedHttpClientConnectionFactoryentConnectionFactory.html#ManagedHttpClientConnectionFactory">ManagedHttpClientConnectionFactory INSTANCE = new ManagedHttpClientConnectionFactory();
64  
65      private final Http1Config h1Config;
66      private final CharCodingConfig charCodingConfig;
67      private final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory;
68      private final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory;
69      private final ContentLengthStrategy incomingContentStrategy;
70      private final ContentLengthStrategy outgoingContentStrategy;
71      private final ResponseOutOfOrderStrategy responseOutOfOrderStrategy;
72  
73      private ManagedHttpClientConnectionFactory(
74              final Http1Config h1Config,
75              final CharCodingConfig charCodingConfig,
76              final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
77              final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory,
78              final ContentLengthStrategy incomingContentStrategy,
79              final ContentLengthStrategy outgoingContentStrategy,
80              final ResponseOutOfOrderStrategy responseOutOfOrderStrategy) {
81          this.h1Config = h1Config != null ? h1Config : Http1Config.DEFAULT;
82          this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
83          this.requestWriterFactory = requestWriterFactory != null ? requestWriterFactory :
84                  DefaultHttpRequestWriterFactory.INSTANCE;
85          this.responseParserFactory = responseParserFactory != null ? responseParserFactory :
86                  DefaultHttpResponseParserFactory.INSTANCE;
87          this.incomingContentStrategy = incomingContentStrategy != null ? incomingContentStrategy :
88                  DefaultContentLengthStrategy.INSTANCE;
89          this.outgoingContentStrategy = outgoingContentStrategy != null ? outgoingContentStrategy :
90                  DefaultContentLengthStrategy.INSTANCE;
91          this.responseOutOfOrderStrategy = responseOutOfOrderStrategy != null ? responseOutOfOrderStrategy :
92                  NoResponseOutOfOrderStrategy.INSTANCE;
93      }
94  
95      public ManagedHttpClientConnectionFactory(
96              final Http1Config h1Config,
97              final CharCodingConfig charCodingConfig,
98              final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
99              final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory,
100             final ContentLengthStrategy incomingContentStrategy,
101             final ContentLengthStrategy outgoingContentStrategy) {
102         this(
103                 h1Config,
104                 charCodingConfig,
105                 requestWriterFactory,
106                 responseParserFactory,
107                 incomingContentStrategy,
108                 outgoingContentStrategy,
109                 null);
110     }
111 
112     public ManagedHttpClientConnectionFactory(
113             final Http1Config h1Config,
114             final CharCodingConfig charCodingConfig,
115             final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
116             final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
117         this(h1Config, charCodingConfig, requestWriterFactory, responseParserFactory, null, null);
118     }
119 
120     public ManagedHttpClientConnectionFactory(
121             final Http1Config h1Config,
122             final CharCodingConfig charCodingConfig,
123             final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
124         this(h1Config, charCodingConfig, null, responseParserFactory);
125     }
126 
127     public ManagedHttpClientConnectionFactory() {
128         this(null, null, null);
129     }
130 
131     @Override
132     public ManagedHttpClientConnection createConnection(final Socket socket) throws IOException {
133         CharsetDecoder charDecoder = null;
134         CharsetEncoder charEncoder = null;
135         final Charset charset = this.charCodingConfig.getCharset();
136         final CodingErrorAction malformedInputAction = this.charCodingConfig.getMalformedInputAction() != null ?
137                 this.charCodingConfig.getMalformedInputAction() : CodingErrorAction.REPORT;
138         final CodingErrorAction unmappableInputAction = this.charCodingConfig.getUnmappableInputAction() != null ?
139                 this.charCodingConfig.getUnmappableInputAction() : CodingErrorAction.REPORT;
140         if (charset != null) {
141             charDecoder = charset.newDecoder();
142             charDecoder.onMalformedInput(malformedInputAction);
143             charDecoder.onUnmappableCharacter(unmappableInputAction);
144             charEncoder = charset.newEncoder();
145             charEncoder.onMalformedInput(malformedInputAction);
146             charEncoder.onUnmappableCharacter(unmappableInputAction);
147         }
148         final String id = "http-outgoing-" + COUNTER.getAndIncrement();
149         final DefaultManagedHttpClientConnectionagedHttpClientConnection.html#DefaultManagedHttpClientConnection">DefaultManagedHttpClientConnection conn = new DefaultManagedHttpClientConnection(
150                 id,
151                 charDecoder,
152                 charEncoder,
153                 h1Config,
154                 incomingContentStrategy,
155                 outgoingContentStrategy,
156                 responseOutOfOrderStrategy,
157                 requestWriterFactory,
158                 responseParserFactory);
159         if (socket != null) {
160             conn.bind(socket);
161         }
162         return conn;
163     }
164 
165     /**
166      * Create a new {@link Builder}.
167      *
168      * @since 5.1
169      */
170     public static Builder builder()  {
171         return new Builder();
172     }
173 
174     /**
175      * Builder for {@link ManagedHttpClientConnectionFactory}.
176      *
177      * @since 5.1
178      */
179     public static final class Builder {
180 
181         private Http1Config http1Config;
182         private CharCodingConfig charCodingConfig;
183         private ContentLengthStrategy incomingContentLengthStrategy;
184         private ContentLengthStrategy outgoingContentLengthStrategy;
185         private ResponseOutOfOrderStrategy responseOutOfOrderStrategy;
186         private HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory;
187         private HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory;
188 
189         private Builder() {}
190 
191         public Builder http1Config(final Http1Config http1Config) {
192             this.http1Config = http1Config;
193             return this;
194         }
195 
196         public Builder charCodingConfig(final CharCodingConfig charCodingConfig) {
197             this.charCodingConfig = charCodingConfig;
198             return this;
199         }
200 
201         public Builder incomingContentLengthStrategy(final ContentLengthStrategy incomingContentLengthStrategy) {
202             this.incomingContentLengthStrategy = incomingContentLengthStrategy;
203             return this;
204         }
205 
206         public Builder outgoingContentLengthStrategy(final ContentLengthStrategy outgoingContentLengthStrategy) {
207             this.outgoingContentLengthStrategy = outgoingContentLengthStrategy;
208             return this;
209         }
210 
211         public Builder responseOutOfOrderStrategy(final ResponseOutOfOrderStrategy responseOutOfOrderStrategy) {
212             this.responseOutOfOrderStrategy = responseOutOfOrderStrategy;
213             return this;
214         }
215 
216         public Builder requestWriterFactory(
217                 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory) {
218             this.requestWriterFactory = requestWriterFactory;
219             return this;
220         }
221 
222         public Builder responseParserFactory(
223                 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
224             this.responseParserFactory = responseParserFactory;
225             return this;
226         }
227 
228         public ManagedHttpClientConnectionFactory build() {
229             return new ManagedHttpClientConnectionFactory(
230                     http1Config,
231                     charCodingConfig,
232                     requestWriterFactory,
233                     responseParserFactory,
234                     incomingContentLengthStrategy,
235                     outgoingContentLengthStrategy,
236                     responseOutOfOrderStrategy);
237         }
238     }
239 }