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}