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.nio.bootstrap; 028 029import java.net.InetAddress; 030import java.util.HashMap; 031import java.util.LinkedList; 032import java.util.Map; 033 034import javax.net.ssl.SSLContext; 035 036import org.apache.http.ConnectionReuseStrategy; 037import org.apache.http.ExceptionLogger; 038import org.apache.http.HttpRequestInterceptor; 039import org.apache.http.HttpResponseFactory; 040import org.apache.http.HttpResponseInterceptor; 041import org.apache.http.config.ConnectionConfig; 042import org.apache.http.impl.DefaultConnectionReuseStrategy; 043import org.apache.http.impl.DefaultHttpResponseFactory; 044import org.apache.http.impl.nio.DefaultNHttpServerConnection; 045import org.apache.http.impl.nio.DefaultNHttpServerConnectionFactory; 046import org.apache.http.impl.nio.SSLNHttpServerConnectionFactory; 047import org.apache.http.impl.nio.reactor.IOReactorConfig; 048import org.apache.http.nio.NHttpConnectionFactory; 049import org.apache.http.nio.protocol.HttpAsyncExpectationVerifier; 050import org.apache.http.nio.protocol.HttpAsyncRequestHandler; 051import org.apache.http.nio.protocol.HttpAsyncRequestHandlerMapper; 052import org.apache.http.nio.protocol.HttpAsyncService; 053import org.apache.http.nio.protocol.UriHttpAsyncRequestHandlerMapper; 054import org.apache.http.nio.reactor.ssl.SSLSetupHandler; 055import org.apache.http.protocol.HttpProcessor; 056import org.apache.http.protocol.HttpProcessorBuilder; 057import org.apache.http.protocol.ResponseConnControl; 058import org.apache.http.protocol.ResponseContent; 059import org.apache.http.protocol.ResponseDate; 060import org.apache.http.protocol.ResponseServer; 061 062/** 063 * @since 4.4 064 */ 065public class ServerBootstrap { 066 067 private int listenerPort; 068 private InetAddress localAddress; 069 private IOReactorConfig ioReactorConfig; 070 private ConnectionConfig connectionConfig; 071 private LinkedList<HttpRequestInterceptor> requestFirst; 072 private LinkedList<HttpRequestInterceptor> requestLast; 073 private LinkedList<HttpResponseInterceptor> responseFirst; 074 private LinkedList<HttpResponseInterceptor> responseLast; 075 private String serverInfo; 076 private HttpProcessor httpProcessor; 077 private ConnectionReuseStrategy connStrategy; 078 private HttpResponseFactory responseFactory; 079 private HttpAsyncRequestHandlerMapper handlerMapper; 080 private Map<String, HttpAsyncRequestHandler<?>> handlerMap; 081 private HttpAsyncExpectationVerifier expectationVerifier; 082 private SSLContext sslContext; 083 private SSLSetupHandler sslSetupHandler; 084 private NHttpConnectionFactory<? extends DefaultNHttpServerConnection> 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 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 (final 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}