001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027package org.apache.http.impl.bootstrap;
028
029import java.net.InetAddress;
030import java.util.HashMap;
031import java.util.LinkedList;
032import java.util.Map;
033
034import javax.net.ServerSocketFactory;
035import javax.net.ssl.SSLContext;
036
037import org.apache.http.ConnectionReuseStrategy;
038import org.apache.http.ExceptionLogger;
039import org.apache.http.HttpConnectionFactory;
040import org.apache.http.HttpRequestInterceptor;
041import org.apache.http.HttpResponseFactory;
042import org.apache.http.HttpResponseInterceptor;
043import org.apache.http.config.ConnectionConfig;
044import org.apache.http.config.SocketConfig;
045import org.apache.http.impl.DefaultBHttpServerConnection;
046import org.apache.http.impl.DefaultBHttpServerConnectionFactory;
047import org.apache.http.impl.DefaultConnectionReuseStrategy;
048import org.apache.http.impl.DefaultHttpResponseFactory;
049import org.apache.http.protocol.HttpExpectationVerifier;
050import org.apache.http.protocol.HttpProcessor;
051import org.apache.http.protocol.HttpProcessorBuilder;
052import org.apache.http.protocol.HttpRequestHandler;
053import org.apache.http.protocol.HttpRequestHandlerMapper;
054import org.apache.http.protocol.HttpService;
055import org.apache.http.protocol.ResponseConnControl;
056import org.apache.http.protocol.ResponseContent;
057import org.apache.http.protocol.ResponseDate;
058import org.apache.http.protocol.ResponseServer;
059import org.apache.http.protocol.UriHttpRequestHandlerMapper;
060
061/**
062 * @since 4.4
063 */
064public class ServerBootstrap {
065
066    private int listenerPort;
067    private InetAddress localAddress;
068    private SocketConfig socketConfig;
069    private ConnectionConfig connectionConfig;
070    private LinkedList<HttpRequestInterceptor> requestFirst;
071    private LinkedList<HttpRequestInterceptor> requestLast;
072    private LinkedList<HttpResponseInterceptor> responseFirst;
073    private LinkedList<HttpResponseInterceptor> responseLast;
074    private String serverInfo;
075    private HttpProcessor httpProcessor;
076    private ConnectionReuseStrategy connStrategy;
077    private HttpResponseFactory responseFactory;
078    private HttpRequestHandlerMapper handlerMapper;
079    private Map<String, HttpRequestHandler> handlerMap;
080    private HttpExpectationVerifier expectationVerifier;
081    private ServerSocketFactory serverSocketFactory;
082    private SSLContext sslContext;
083    private SSLServerSetupHandler sslSetupHandler;
084    private HttpConnectionFactory<? extends DefaultBHttpServerConnection> connectionFactory;
085    private ExceptionLogger exceptionLogger;
086
087    private ServerBootstrap() {
088    }
089
090    public static ServerBootstrap bootstrap() {
091        return new ServerBootstrap();
092    }
093
094    /**
095     * Sets listener port number.
096     */
097    public final ServerBootstrap setListenerPort(final int listenerPort) {
098        this.listenerPort = listenerPort;
099        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 socket configuration.
112     */
113    public final ServerBootstrap setSocketConfig(final SocketConfig socketConfig) {
114        this.socketConfig = socketConfig;
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.HttpConnectionFactory)} method.
123     */
124    public final ServerBootstrap setConnectionConfig(final ConnectionConfig connectionConfig) {
125        this.connectionConfig = connectionConfig;
126        return this;
127    }
128
129    /**
130     * Assigns {@link 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 ConnectionReuseStrategy} instance.
218     */
219    public final ServerBootstrap setConnectionReuseStrategy(final ConnectionReuseStrategy connStrategy) {
220        this.connStrategy = connStrategy;
221        return this;
222    }
223
224    /**
225     * Assigns {@link HttpResponseFactory} instance.
226     */
227    public final ServerBootstrap setResponseFactory(final HttpResponseFactory responseFactory) {
228        this.responseFactory = responseFactory;
229        return this;
230    }
231
232    /**
233     * Assigns {@link HttpRequestHandlerMapper} instance.
234     */
235    public final ServerBootstrap setHandlerMapper(final HttpRequestHandlerMapper handlerMapper) {
236        this.handlerMapper = handlerMapper;
237        return this;
238    }
239
240    /**
241     * Registers the given {@link HttpRequestHandler} as a handler for URIs
242     * matching the given pattern.
243     * <p>
244     * Please note this value can be overridden by the {@link #setHandlerMapper(
245     *   org.apache.http.protocol.HttpRequestHandlerMapper)} 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 HttpRequestHandler handler) {
251        if (pattern == null || handler == null) {
252            return this;
253        }
254        if (handlerMap == null) {
255            handlerMap = new HashMap<String, HttpRequestHandler>();
256        }
257        handlerMap.put(pattern, handler);
258        return this;
259    }
260
261    /**
262     * Assigns {@link HttpExpectationVerifier} instance.
263     */
264    public final ServerBootstrap setExpectationVerifier(final HttpExpectationVerifier expectationVerifier) {
265        this.expectationVerifier = expectationVerifier;
266        return this;
267    }
268
269    /**
270     * Assigns {@link HttpConnectionFactory} instance.
271     */
272    public final ServerBootstrap setConnectionFactory(
273            final HttpConnectionFactory<? extends DefaultBHttpServerConnection> connectionFactory) {
274        this.connectionFactory = connectionFactory;
275        return this;
276    }
277
278    /**
279     * Assigns {@link org.apache.http.impl.bootstrap.SSLServerSetupHandler} instance.
280     */
281    public final ServerBootstrap setSslSetupHandler(final SSLServerSetupHandler sslSetupHandler) {
282        this.sslSetupHandler = sslSetupHandler;
283        return this;
284    }
285
286    /**
287     * Assigns {@link javax.net.ServerSocketFactory} instance.
288     */
289    public final ServerBootstrap setServerSocketFactory(final ServerSocketFactory serverSocketFactory) {
290        this.serverSocketFactory = serverSocketFactory;
291        return this;
292    }
293
294    /**
295     * Assigns {@link javax.net.ssl.SSLContext} instance.
296     * <p>
297     * Please note this value can be overridden by the {@link #setServerSocketFactory(
298     *   javax.net.ServerSocketFactory)} method.
299     */
300    public final ServerBootstrap setSslContext(final SSLContext sslContext) {
301        this.sslContext = sslContext;
302        return this;
303    }
304
305    /**
306     * Assigns {@link org.apache.http.ExceptionLogger} instance.
307     */
308    public final ServerBootstrap setExceptionLogger(final ExceptionLogger exceptionLogger) {
309        this.exceptionLogger = exceptionLogger;
310        return this;
311    }
312
313    public HttpServer create() {
314
315        HttpProcessor httpProcessorCopy = this.httpProcessor;
316        if (httpProcessorCopy == null) {
317
318            final HttpProcessorBuilder b = HttpProcessorBuilder.create();
319            if (requestFirst != null) {
320                for (final HttpRequestInterceptor i: requestFirst) {
321                    b.addFirst(i);
322                }
323            }
324            if (responseFirst != null) {
325                for (final HttpResponseInterceptor i: responseFirst) {
326                    b.addFirst(i);
327                }
328            }
329
330            String serverInfoCopy = this.serverInfo;
331            if (serverInfoCopy == null) {
332                serverInfoCopy = "Apache-HttpCore/1.1";
333            }
334
335            b.addAll(
336                    new ResponseDate(),
337                    new ResponseServer(serverInfoCopy),
338                    new ResponseContent(),
339                    new ResponseConnControl());
340            if (requestLast != null) {
341                for (final HttpRequestInterceptor i: requestLast) {
342                    b.addLast(i);
343                }
344            }
345            if (responseLast != null) {
346                for (final HttpResponseInterceptor i: responseLast) {
347                    b.addLast(i);
348                }
349            }
350            httpProcessorCopy = b.build();
351        }
352
353        HttpRequestHandlerMapper handlerMapperCopy = this.handlerMapper;
354        if (handlerMapperCopy == null) {
355            final UriHttpRequestHandlerMapper reqistry = new UriHttpRequestHandlerMapper();
356            if (handlerMap != null) {
357                for (final Map.Entry<String, HttpRequestHandler> entry: handlerMap.entrySet()) {
358                    reqistry.register(entry.getKey(), entry.getValue());
359                }
360            }
361            handlerMapperCopy = reqistry;
362        }
363
364        ConnectionReuseStrategy connStrategyCopy = this.connStrategy;
365        if (connStrategyCopy == null) {
366            connStrategyCopy = DefaultConnectionReuseStrategy.INSTANCE;
367        }
368
369        HttpResponseFactory responseFactoryCopy = this.responseFactory;
370        if (responseFactoryCopy == null) {
371            responseFactoryCopy = DefaultHttpResponseFactory.INSTANCE;
372        }
373
374        final HttpService httpService = new HttpService(
375                httpProcessorCopy, connStrategyCopy, responseFactoryCopy, handlerMapperCopy,
376                this.expectationVerifier);
377
378        ServerSocketFactory serverSocketFactoryCopy = this.serverSocketFactory;
379        if (serverSocketFactoryCopy == null) {
380            if (this.sslContext != null) {
381                serverSocketFactoryCopy = this.sslContext.getServerSocketFactory();
382            } else {
383                serverSocketFactoryCopy = ServerSocketFactory.getDefault();
384            }
385        }
386
387        HttpConnectionFactory<? extends DefaultBHttpServerConnection> connectionFactoryCopy = this.connectionFactory;
388        if (connectionFactoryCopy == null) {
389            if (this.connectionConfig != null) {
390                connectionFactoryCopy = new DefaultBHttpServerConnectionFactory(this.connectionConfig);
391            } else {
392                connectionFactoryCopy = DefaultBHttpServerConnectionFactory.INSTANCE;
393            }
394        }
395
396        ExceptionLogger exceptionLoggerCopy = this.exceptionLogger;
397        if (exceptionLoggerCopy == null) {
398            exceptionLoggerCopy = ExceptionLogger.NO_OP;
399        }
400
401        return new HttpServer(
402                this.listenerPort > 0 ? this.listenerPort : 0,
403                this.localAddress,
404                this.socketConfig != null ? this.socketConfig : SocketConfig.DEFAULT,
405                serverSocketFactoryCopy,
406                httpService,
407                connectionFactoryCopy,
408                this.sslSetupHandler,
409                exceptionLoggerCopy);
410    }
411
412}