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.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.ServerSocketFactory;
35  import javax.net.ssl.SSLContext;
36  
37  import org.apache.http.ConnectionReuseStrategy;
38  import org.apache.http.ExceptionLogger;
39  import org.apache.http.HttpConnectionFactory;
40  import org.apache.http.HttpRequestInterceptor;
41  import org.apache.http.HttpResponseFactory;
42  import org.apache.http.HttpResponseInterceptor;
43  import org.apache.http.config.ConnectionConfig;
44  import org.apache.http.config.SocketConfig;
45  import org.apache.http.impl.DefaultBHttpServerConnection;
46  import org.apache.http.impl.DefaultBHttpServerConnectionFactory;
47  import org.apache.http.impl.DefaultConnectionReuseStrategy;
48  import org.apache.http.impl.DefaultHttpResponseFactory;
49  import org.apache.http.protocol.HttpExpectationVerifier;
50  import org.apache.http.protocol.HttpProcessor;
51  import org.apache.http.protocol.HttpProcessorBuilder;
52  import org.apache.http.protocol.HttpRequestHandler;
53  import org.apache.http.protocol.HttpRequestHandlerMapper;
54  import org.apache.http.protocol.HttpService;
55  import org.apache.http.protocol.ResponseConnControl;
56  import org.apache.http.protocol.ResponseContent;
57  import org.apache.http.protocol.ResponseDate;
58  import org.apache.http.protocol.ResponseServer;
59  import org.apache.http.protocol.UriHttpRequestHandlerMapper;
60  
61  /**
62   * @since 4.4
63   */
64  public class ServerBootstrap {
65  
66      private int listenerPort;
67      private InetAddress localAddress;
68      private SocketConfig socketConfig;
69      private ConnectionConfig connectionConfig;
70      private LinkedList<HttpRequestInterceptor> requestFirst;
71      private LinkedList<HttpRequestInterceptor> requestLast;
72      private LinkedList<HttpResponseInterceptor> responseFirst;
73      private LinkedList<HttpResponseInterceptor> responseLast;
74      private String serverInfo;
75      private HttpProcessor httpProcessor;
76      private ConnectionReuseStrategy connStrategy;
77      private HttpResponseFactory responseFactory;
78      private HttpRequestHandlerMapper handlerMapper;
79      private Map<String, HttpRequestHandler> handlerMap;
80      private HttpExpectationVerifier expectationVerifier;
81      private ServerSocketFactory serverSocketFactory;
82      private SSLContext sslContext;
83      private SSLServerSetupHandler sslSetupHandler;
84      private HttpConnectionFactory<? extends DefaultBHttpServerConnection> 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       * @return this
98       */
99      public final ServerBootstrap setListenerPort(final int listenerPort) {
100         this.listenerPort = listenerPort;
101         return this;
102     }
103 
104     /**
105      * Assigns local interface for the listener.
106      *
107      * @return this
108      */
109     public final ServerBootstrap setLocalAddress(final InetAddress localAddress) {
110         this.localAddress = localAddress;
111         return this;
112     }
113 
114     /**
115      * Sets socket configuration.
116      *
117      * @return this
118      */
119     public final ServerBootstrap setSocketConfig(final SocketConfig socketConfig) {
120         this.socketConfig = socketConfig;
121         return this;
122     }
123 
124     /**
125      * Sets connection configuration.
126      * <p>
127      * Please note this value can be overridden by the {@link #setConnectionFactory(
128      * org.apache.http.HttpConnectionFactory)} method.
129      * </p>
130      *
131      * @return this
132      */
133     public final ServerBootstrap setConnectionConfig(final ConnectionConfig connectionConfig) {
134         this.connectionConfig = connectionConfig;
135         return this;
136     }
137 
138     /**
139      * Assigns {@link HttpProcessor} instance.
140      *
141      * @return this
142      */
143     public final ServerBootstrap setHttpProcessor(final HttpProcessor httpProcessor) {
144         this.httpProcessor = httpProcessor;
145         return this;
146     }
147 
148     /**
149      * Adds this protocol interceptor to the head of the protocol processing list.
150      * <p>
151      * Please note this value can be overridden by the {@link #setHttpProcessor(
152      * org.apache.http.protocol.HttpProcessor)} method.
153      * </p>
154      *
155      * @return this
156      */
157     public final ServerBootstrap addInterceptorFirst(final HttpResponseInterceptor itcp) {
158         if (itcp == null) {
159             return this;
160         }
161         if (responseFirst == null) {
162             responseFirst = new LinkedList<HttpResponseInterceptor>();
163         }
164         responseFirst.addFirst(itcp);
165         return this;
166     }
167 
168     /**
169      * Adds this protocol interceptor to the tail of the protocol processing list.
170      * <p>
171      * Please note this value can be overridden by the {@link #setHttpProcessor(
172      * org.apache.http.protocol.HttpProcessor)} method.
173      * </p>
174      *
175      * @return this
176      */
177     public final ServerBootstrap addInterceptorLast(final HttpResponseInterceptor itcp) {
178         if (itcp == null) {
179             return this;
180         }
181         if (responseLast == null) {
182             responseLast = new LinkedList<HttpResponseInterceptor>();
183         }
184         responseLast.addLast(itcp);
185         return this;
186     }
187 
188     /**
189      * Adds this protocol interceptor to the head 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      * </p>
194      *
195      * @return this
196      */
197     public final ServerBootstrap addInterceptorFirst(final HttpRequestInterceptor itcp) {
198         if (itcp == null) {
199             return this;
200         }
201         if (requestFirst == null) {
202             requestFirst = new LinkedList<HttpRequestInterceptor>();
203         }
204         requestFirst.addFirst(itcp);
205         return this;
206     }
207 
208     /**
209      * Adds this protocol interceptor to the tail of the protocol processing list.
210      * <p>
211      * Please note this value can be overridden by the {@link #setHttpProcessor(
212      * org.apache.http.protocol.HttpProcessor)} method.
213      * </p>
214      *
215      * @return this
216      */
217     public final ServerBootstrap addInterceptorLast(final HttpRequestInterceptor itcp) {
218         if (itcp == null) {
219             return this;
220         }
221         if (requestLast == null) {
222             requestLast = new LinkedList<HttpRequestInterceptor>();
223         }
224         requestLast.addLast(itcp);
225         return this;
226     }
227 
228     /**
229      * Assigns {@code Server} response header value.
230      * <p>
231      * Please note this value can be overridden by the {@link #setHttpProcessor(
232      * org.apache.http.protocol.HttpProcessor)} method.
233      * </p>
234      *
235      * @return this
236      */
237     public final ServerBootstrap setServerInfo(final String serverInfo) {
238         this.serverInfo = serverInfo;
239         return this;
240     }
241 
242     /**
243      * Assigns {@link ConnectionReuseStrategy} instance.
244      *
245      * @return this
246      */
247     public final ServerBootstrap setConnectionReuseStrategy(final ConnectionReuseStrategy connStrategy) {
248         this.connStrategy = connStrategy;
249         return this;
250     }
251 
252     /**
253      * Assigns {@link HttpResponseFactory} instance.
254      *
255      * @return this
256      */
257     public final ServerBootstrap setResponseFactory(final HttpResponseFactory responseFactory) {
258         this.responseFactory = responseFactory;
259         return this;
260     }
261 
262     /**
263      * Assigns {@link HttpRequestHandlerMapper} instance.
264      *
265      * @return this
266      */
267     public final ServerBootstrap setHandlerMapper(final HttpRequestHandlerMapper handlerMapper) {
268         this.handlerMapper = handlerMapper;
269         return this;
270     }
271 
272     /**
273      * Registers the given {@link HttpRequestHandler} as a handler for URIs
274      * matching the given pattern.
275      * <p>
276      * Please note this value can be overridden by the {@link #setHandlerMapper(
277      *   org.apache.http.protocol.HttpRequestHandlerMapper)} method.
278      * </p>
279      *
280      * @param pattern the pattern to register the handler for.
281      * @param handler the handler.
282      * @return this
283      */
284     public final ServerBootstrap registerHandler(final String pattern, final HttpRequestHandler handler) {
285         if (pattern == null || handler == null) {
286             return this;
287         }
288         if (handlerMap == null) {
289             handlerMap = new HashMap<String, HttpRequestHandler>();
290         }
291         handlerMap.put(pattern, handler);
292         return this;
293     }
294 
295     /**
296      * Assigns {@link HttpExpectationVerifier} instance.
297      *
298      * @return this
299      */
300     public final ServerBootstrap setExpectationVerifier(final HttpExpectationVerifier expectationVerifier) {
301         this.expectationVerifier = expectationVerifier;
302         return this;
303     }
304 
305     /**
306      * Assigns {@link HttpConnectionFactory} instance.
307      *
308      * @return this
309      */
310     public final ServerBootstrap setConnectionFactory(
311             final HttpConnectionFactory<? extends DefaultBHttpServerConnection> connectionFactory) {
312         this.connectionFactory = connectionFactory;
313         return this;
314     }
315 
316     /**
317      * Assigns {@link org.apache.http.impl.bootstrap.SSLServerSetupHandler} instance.
318      *
319      * @return this
320      */
321     public final ServerBootstrap setSslSetupHandler(final SSLServerSetupHandler sslSetupHandler) {
322         this.sslSetupHandler = sslSetupHandler;
323         return this;
324     }
325 
326     /**
327      * Assigns {@link javax.net.ServerSocketFactory} instance.
328      *
329      * @return this
330      */
331     public final ServerBootstrap setServerSocketFactory(final ServerSocketFactory serverSocketFactory) {
332         this.serverSocketFactory = serverSocketFactory;
333         return this;
334     }
335 
336     /**
337      * Assigns {@link javax.net.ssl.SSLContext} instance.
338      * <p>
339      * Please note this value can be overridden by the {@link #setServerSocketFactory(
340      *   javax.net.ServerSocketFactory)} method.
341      * </p>
342      *
343      * @return this
344      */
345     public final ServerBootstrap setSslContext(final SSLContext sslContext) {
346         this.sslContext = sslContext;
347         return this;
348     }
349 
350     /**
351      * Assigns {@link org.apache.http.ExceptionLogger} instance.
352      *
353      * @return this
354      */
355     public final ServerBootstrap setExceptionLogger(final ExceptionLogger exceptionLogger) {
356         this.exceptionLogger = exceptionLogger;
357         return this;
358     }
359 
360     public HttpServer create() {
361 
362         HttpProcessor httpProcessorCopy = this.httpProcessor;
363         if (httpProcessorCopy == null) {
364 
365             final HttpProcessorBuilder b = HttpProcessorBuilder.create();
366             if (requestFirst != null) {
367                 for (final HttpRequestInterceptor i: requestFirst) {
368                     b.addFirst(i);
369                 }
370             }
371             if (responseFirst != null) {
372                 for (final HttpResponseInterceptor i: responseFirst) {
373                     b.addFirst(i);
374                 }
375             }
376 
377             String serverInfoCopy = this.serverInfo;
378             if (serverInfoCopy == null) {
379                 serverInfoCopy = "Apache-HttpCore/1.1";
380             }
381 
382             b.addAll(
383                     new ResponseDate(),
384                     new ResponseServer(serverInfoCopy),
385                     new ResponseContent(),
386                     new ResponseConnControl());
387             if (requestLast != null) {
388                 for (final HttpRequestInterceptor i: requestLast) {
389                     b.addLast(i);
390                 }
391             }
392             if (responseLast != null) {
393                 for (final HttpResponseInterceptor i: responseLast) {
394                     b.addLast(i);
395                 }
396             }
397             httpProcessorCopy = b.build();
398         }
399 
400         HttpRequestHandlerMapper handlerMapperCopy = this.handlerMapper;
401         if (handlerMapperCopy == null) {
402             final UriHttpRequestHandlerMapper reqistry = new UriHttpRequestHandlerMapper();
403             if (handlerMap != null) {
404                 for (final Map.Entry<String, HttpRequestHandler> entry: handlerMap.entrySet()) {
405                     reqistry.register(entry.getKey(), entry.getValue());
406                 }
407             }
408             handlerMapperCopy = reqistry;
409         }
410 
411         ConnectionReuseStrategy connStrategyCopy = this.connStrategy;
412         if (connStrategyCopy == null) {
413             connStrategyCopy = DefaultConnectionReuseStrategy.INSTANCE;
414         }
415 
416         HttpResponseFactory responseFactoryCopy = this.responseFactory;
417         if (responseFactoryCopy == null) {
418             responseFactoryCopy = DefaultHttpResponseFactory.INSTANCE;
419         }
420 
421         final HttpService httpService = new HttpService(
422                 httpProcessorCopy, connStrategyCopy, responseFactoryCopy, handlerMapperCopy,
423                 this.expectationVerifier);
424 
425         ServerSocketFactory serverSocketFactoryCopy = this.serverSocketFactory;
426         if (serverSocketFactoryCopy == null) {
427             if (this.sslContext != null) {
428                 serverSocketFactoryCopy = this.sslContext.getServerSocketFactory();
429             } else {
430                 serverSocketFactoryCopy = ServerSocketFactory.getDefault();
431             }
432         }
433 
434         HttpConnectionFactory<? extends DefaultBHttpServerConnection> connectionFactoryCopy = this.connectionFactory;
435         if (connectionFactoryCopy == null) {
436             if (this.connectionConfig != null) {
437                 connectionFactoryCopy = new DefaultBHttpServerConnectionFactory(this.connectionConfig);
438             } else {
439                 connectionFactoryCopy = DefaultBHttpServerConnectionFactory.INSTANCE;
440             }
441         }
442 
443         ExceptionLogger exceptionLoggerCopy = this.exceptionLogger;
444         if (exceptionLoggerCopy == null) {
445             exceptionLoggerCopy = ExceptionLogger.NO_OP;
446         }
447 
448         return new HttpServer(
449                 this.listenerPort > 0 ? this.listenerPort : 0,
450                 this.localAddress,
451                 this.socketConfig != null ? this.socketConfig : SocketConfig.DEFAULT,
452                 serverSocketFactoryCopy,
453                 httpService,
454                 connectionFactoryCopy,
455                 this.sslSetupHandler,
456                 exceptionLoggerCopy);
457     }
458 
459 }