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.impl.nio.bootstrap;
28  
29  import java.net.InetAddress;
30  import java.util.HashMap;
31  import java.util.LinkedList;
32  import java.util.Map;
33  
34  import javax.net.ssl.SSLContext;
35  
36  import org.apache.http.ConnectionReuseStrategy;
37  import org.apache.http.ExceptionLogger;
38  import org.apache.http.HttpRequestInterceptor;
39  import org.apache.http.HttpResponseFactory;
40  import org.apache.http.HttpResponseInterceptor;
41  import org.apache.http.config.ConnectionConfig;
42  import org.apache.http.impl.DefaultConnectionReuseStrategy;
43  import org.apache.http.impl.DefaultHttpResponseFactory;
44  import org.apache.http.impl.nio.DefaultNHttpServerConnection;
45  import org.apache.http.impl.nio.DefaultNHttpServerConnectionFactory;
46  import org.apache.http.impl.nio.SSLNHttpServerConnectionFactory;
47  import org.apache.http.impl.nio.reactor.IOReactorConfig;
48  import org.apache.http.nio.NHttpConnectionFactory;
49  import org.apache.http.nio.protocol.HttpAsyncExpectationVerifier;
50  import org.apache.http.nio.protocol.HttpAsyncRequestHandler;
51  import org.apache.http.nio.protocol.HttpAsyncRequestHandlerMapper;
52  import org.apache.http.nio.protocol.HttpAsyncService;
53  import org.apache.http.nio.protocol.UriHttpAsyncRequestHandlerMapper;
54  import org.apache.http.nio.reactor.ssl.SSLSetupHandler;
55  import org.apache.http.protocol.HttpProcessor;
56  import org.apache.http.protocol.HttpProcessorBuilder;
57  import org.apache.http.protocol.ResponseConnControl;
58  import org.apache.http.protocol.ResponseContent;
59  import org.apache.http.protocol.ResponseDate;
60  import org.apache.http.protocol.ResponseServer;
61  
62  /**
63   * @since 4.4
64   */
65  public class ServerBootstrap {
66  
67      private int listenerPort;
68      private InetAddress localAddress;
69      private IOReactorConfig ioReactorConfig;
70      private ConnectionConfig connectionConfig;
71      private LinkedList<HttpRequestInterceptor> requestFirst;
72      private LinkedList<HttpRequestInterceptor> requestLast;
73      private LinkedList<HttpResponseInterceptor> responseFirst;
74      private LinkedList<HttpResponseInterceptor> responseLast;
75      private String serverInfo;
76      private HttpProcessor httpProcessor;
77      private ConnectionReuseStrategy connStrategy;
78      private HttpResponseFactory responseFactory;
79      private HttpAsyncRequestHandlerMapper handlerMapper;
80      private Map<String, HttpAsyncRequestHandler<?>> handlerMap;
81      private HttpAsyncExpectationVerifier expectationVerifier;
82      private SSLContext sslContext;
83      private SSLSetupHandler sslSetupHandler;
84      private NHttpConnectionFactory<? extends DefaultNHttpServerConnection> connectionFactory;
85      private ExceptionLogger exceptionLogger;
86  
87      private ServerBootstrap() {
88      }
89  
90      public static ServerBootstrap bootstrap() {
91          return new ServerBootstrap();
92      }
93  
94      /**
95       * Sets listener port number.
96       */
97      public final ServerBootstrap setListenerPort(final int listenerPort) {
98          this.listenerPort = listenerPort;
99          return this;
100     }
101 
102     /**
103      * Assigns local interface for the listener.
104      */
105     public final ServerBootstrap setLocalAddress(final InetAddress localAddress) {
106         this.localAddress = localAddress;
107         return this;
108     }
109 
110     /**
111      * Sets I/O reactor configuration.
112      */
113     public final ServerBootstrap setIOReactorConfig(final IOReactorConfig ioReactorConfig) {
114         this.ioReactorConfig = ioReactorConfig;
115         return this;
116     }
117 
118     /**
119      * Sets connection configuration.
120      * <p>
121      * Please note this value can be overridden by the {@link #setConnectionFactory(
122      *   org.apache.http.nio.NHttpConnectionFactory)} method.
123      */
124     public final ServerBootstrap setConnectionConfig(final ConnectionConfig connectionConfig) {
125         this.connectionConfig = connectionConfig;
126         return this;
127     }
128 
129     /**
130      * Assigns {@link org.apache.http.protocol.HttpProcessor} instance.
131      */
132     public final ServerBootstrap setHttpProcessor(final HttpProcessor httpProcessor) {
133         this.httpProcessor = httpProcessor;
134         return this;
135     }
136 
137     /**
138      * Adds this protocol interceptor to the head of the protocol processing list.
139      * <p>
140      * Please note this value can be overridden by the {@link #setHttpProcessor(
141      * org.apache.http.protocol.HttpProcessor)} method.
142      */
143     public final ServerBootstrap addInterceptorFirst(final HttpResponseInterceptor itcp) {
144         if (itcp == null) {
145             return this;
146         }
147         if (responseFirst == null) {
148             responseFirst = new LinkedList<HttpResponseInterceptor>();
149         }
150         responseFirst.addFirst(itcp);
151         return this;
152     }
153 
154     /**
155      * Adds this protocol interceptor to the tail of the protocol processing list.
156      * <p>
157      * Please note this value can be overridden by the {@link #setHttpProcessor(
158      * org.apache.http.protocol.HttpProcessor)} method.
159      */
160     public final ServerBootstrap addInterceptorLast(final HttpResponseInterceptor itcp) {
161         if (itcp == null) {
162             return this;
163         }
164         if (responseLast == null) {
165             responseLast = new LinkedList<HttpResponseInterceptor>();
166         }
167         responseLast.addLast(itcp);
168         return this;
169     }
170 
171     /**
172      * Adds this protocol interceptor to the head of the protocol processing list.
173      * <p>
174      * Please note this value can be overridden by the {@link #setHttpProcessor(
175      * org.apache.http.protocol.HttpProcessor)} method.
176      */
177     public final ServerBootstrap addInterceptorFirst(final HttpRequestInterceptor itcp) {
178         if (itcp == null) {
179             return this;
180         }
181         if (requestFirst == null) {
182             requestFirst = new LinkedList<HttpRequestInterceptor>();
183         }
184         requestFirst.addFirst(itcp);
185         return this;
186     }
187 
188     /**
189      * Adds this protocol interceptor to the tail of the protocol processing list.
190      * <p>
191      * Please note this value can be overridden by the {@link #setHttpProcessor(
192      * org.apache.http.protocol.HttpProcessor)} method.
193      */
194     public final ServerBootstrap addInterceptorLast(final HttpRequestInterceptor itcp) {
195         if (itcp == null) {
196             return this;
197         }
198         if (requestLast == null) {
199             requestLast = new LinkedList<HttpRequestInterceptor>();
200         }
201         requestLast.addLast(itcp);
202         return this;
203     }
204 
205     /**
206      * Assigns {@code Server} response header value.
207      * <p>
208      * Please note this value can be overridden by the {@link #setHttpProcessor(
209      * org.apache.http.protocol.HttpProcessor)} method.
210      */
211     public final ServerBootstrap setServerInfo(final String serverInfo) {
212         this.serverInfo = serverInfo;
213         return this;
214     }
215 
216     /**
217      * Assigns {@link org.apache.http.ConnectionReuseStrategy} instance.
218      */
219     public final ServerBootstrap setConnectionReuseStrategy(final ConnectionReuseStrategy connStrategy) {
220         this.connStrategy = connStrategy;
221         return this;
222     }
223 
224     /**
225      * Assigns {@link org.apache.http.HttpResponseFactory} instance.
226      */
227     public final ServerBootstrap setResponseFactory(final HttpResponseFactory responseFactory) {
228         this.responseFactory = responseFactory;
229         return this;
230     }
231 
232     /**
233      * Assigns {@link org.apache.http.nio.protocol.HttpAsyncRequestHandlerMapper} instance.
234      */
235     public final ServerBootstrap setHandlerMapper(final HttpAsyncRequestHandlerMapper handlerMapper) {
236         this.handlerMapper = handlerMapper;
237         return this;
238     }
239 
240     /**
241      * Registers the given {@link org.apache.http.nio.protocol.HttpAsyncRequestHandler}
242      * as a handler for URIs matching the given pattern.
243      * <p>
244      * Please note this value can be overridden by the {@link #setHandlerMapper(
245      *   org.apache.http.nio.protocol.HttpAsyncRequestHandlerMapper)} )} method.
246      *
247      * @param pattern the pattern to register the handler for.
248      * @param handler the handler.
249      */
250     public final ServerBootstrap registerHandler(final String pattern, final HttpAsyncRequestHandler<?> handler) {
251         if (pattern == null || handler == null) {
252             return this;
253         }
254         if (handlerMap == null) {
255             handlerMap = new HashMap<String, HttpAsyncRequestHandler<?>>();
256         }
257         handlerMap.put(pattern, handler);
258         return this;
259     }
260 
261     /**
262      * Assigns {@link org.apache.http.nio.protocol.HttpAsyncExpectationVerifier} instance.
263      */
264     public final ServerBootstrap setExpectationVerifier(final HttpAsyncExpectationVerifier expectationVerifier) {
265         this.expectationVerifier = expectationVerifier;
266         return this;
267     }
268 
269     /**
270      * Assigns {@link org.apache.http.nio.NHttpConnectionFactory} instance.
271      */
272     public final ServerBootstrap setConnectionFactory(
273             final NHttpConnectionFactory<? extends DefaultNHttpServerConnection> connectionFactory) {
274         this.connectionFactory = connectionFactory;
275         return this;
276     }
277 
278     /**
279      * Assigns {@link javax.net.ssl.SSLContext} instance.
280      * <p>
281      * Please note this value can be overridden by the {@link #setConnectionFactory(
282      *   org.apache.http.nio.NHttpConnectionFactory)} method.
283      */
284     public final ServerBootstrap setSslContext(final SSLContext sslContext) {
285         this.sslContext = sslContext;
286         return this;
287     }
288 
289     /**
290      * Assigns {@link org.apache.http.nio.reactor.ssl.SSLSetupHandler} instance.
291      * <p>
292      * Please note this value can be overridden by the {@link #setConnectionFactory(
293      *   org.apache.http.nio.NHttpConnectionFactory)} method.
294      */
295     public ServerBootstrap setSslSetupHandler(final SSLSetupHandler sslSetupHandler) {
296         this.sslSetupHandler = sslSetupHandler;
297         return this;
298     }
299 
300     /**
301      * Assigns {@link org.apache.http.ExceptionLogger} instance.
302      */
303     public final ServerBootstrap setExceptionLogger(final ExceptionLogger exceptionLogger) {
304         this.exceptionLogger = exceptionLogger;
305         return this;
306     }
307 
308     public HttpServer create() {
309 
310         HttpProcessor httpProcessorCopy = this.httpProcessor;
311         if (httpProcessorCopy == null) {
312 
313             final HttpProcessorBuilder b = HttpProcessorBuilder.create();
314             if (requestFirst != null) {
315                 for (final HttpRequestInterceptor i: requestFirst) {
316                     b.addFirst(i);
317                 }
318             }
319             if (responseFirst != null) {
320                 for (final HttpResponseInterceptor i: responseFirst) {
321                     b.addFirst(i);
322                 }
323             }
324 
325             String serverInfoCopy = this.serverInfo;
326             if (serverInfoCopy == null) {
327                 serverInfoCopy = "Apache-HttpCore-NIO/1.1";
328             }
329 
330             b.addAll(
331                     new ResponseDate(),
332                     new ResponseServer(serverInfoCopy),
333                     new ResponseContent(),
334                     new ResponseConnControl());
335             if (requestLast != null) {
336                 for (final HttpRequestInterceptor i: requestLast) {
337                     b.addLast(i);
338                 }
339             }
340             if (responseLast != null) {
341                 for (final HttpResponseInterceptor i: responseLast) {
342                     b.addLast(i);
343                 }
344             }
345             httpProcessorCopy = b.build();
346         }
347 
348         HttpAsyncRequestHandlerMapper handlerMapperCopy = this.handlerMapper;
349         if (handlerMapperCopy == null) {
350             final UriHttpAsyncRequestHandlerMapper reqistry = new UriHttpAsyncRequestHandlerMapper();
351             if (handlerMap != null) {
352                 for (Map.Entry<String, HttpAsyncRequestHandler<?>> entry: handlerMap.entrySet()) {
353                     reqistry.register(entry.getKey(), entry.getValue());
354                 }
355             }
356             handlerMapperCopy = reqistry;
357         }
358 
359         ConnectionReuseStrategy connStrategyCopy = this.connStrategy;
360         if (connStrategyCopy == null) {
361             connStrategyCopy = DefaultConnectionReuseStrategy.INSTANCE;
362         }
363 
364         HttpResponseFactory responseFactoryCopy = this.responseFactory;
365         if (responseFactoryCopy == null) {
366             responseFactoryCopy = DefaultHttpResponseFactory.INSTANCE;
367         }
368 
369         NHttpConnectionFactory<? extends DefaultNHttpServerConnection> connectionFactoryCopy = this.connectionFactory;
370         if (connectionFactoryCopy == null) {
371             if (this.sslContext != null) {
372                 connectionFactoryCopy = new SSLNHttpServerConnectionFactory(
373                         this.sslContext, this.sslSetupHandler, this.connectionConfig);
374             } else {
375                 connectionFactoryCopy = new DefaultNHttpServerConnectionFactory(this.connectionConfig);
376             }
377         }
378 
379         ExceptionLogger exceptionLoggerCopy = this.exceptionLogger;
380         if (exceptionLoggerCopy == null) {
381             exceptionLoggerCopy = ExceptionLogger.NO_OP;
382         }
383 
384         final HttpAsyncService httpService = new HttpAsyncService(
385                 httpProcessorCopy, connStrategyCopy, responseFactoryCopy, handlerMapperCopy,
386                 this.expectationVerifier, exceptionLoggerCopy);
387 
388         return new HttpServer(this.listenerPort, this.localAddress, this.ioReactorConfig,
389                 httpService, connectionFactoryCopy, exceptionLoggerCopy);
390 
391     }
392 
393 }