blob: 4055422820d8bdf0d8040f1422ccb824b0d80f89 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.axis2.transport.http.server;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.TransportInDescription;
import org.apache.axis2.engine.ListenerManager;
import org.apache.axis2.transport.http.HTTPWorkerFactory;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpResponseFactory;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Factory used to configure and create the various instances required in http transports.
* Either configure this class in axis2.xml, or in code via the setters, or subclass it and specialize some factory methods to gain more control.
*/
public class HttpFactory {
/**
* Name of axis2.xml port parameter for SimpleHTTPServer configuration
*/
public static final String PARAMETER_PORT = "port";
/**
* Name of axis2.xml hostname parameter for SimpleHTTPServer configuration
*/
public static final String PARAMETER_HOST_ADDRESS = "hostname";
/**
* Name of axis2.xml originServer parameter for SimpleHTTPServer configuration
*/
public static final String PARAMETER_ORIGIN_SERVER = "originServer";
/**
* Name of axis2.xml requestTimeout parameter for SimpleHTTPServer configuration
*/
public static final String PARAMETER_REQUEST_SOCKET_TIMEOUT = "requestTimeout";
/**
* Name of axis2.xml requestTcpNoDelay parameter for SimpleHTTPServer configuration
*/
public static final String PARAMETER_REQUEST_TCP_NO_DELAY = "requestTcpNoDelay";
/**
* Name of axis2.xml requestCoreThreadPoolSize parameter for SimpleHTTPServer configuration
*/
public static final String PARAMETER_REQUEST_CORE_THREAD_POOL_SIZE =
"requestCoreThreadPoolSize";
/**
* Name of axis2.xml requestMaxThreadPoolSize parameter for SimpleHTTPServer configuration
*/
public static final String PARAMETER_REQUEST_MAX_THREAD_POOL_SIZE = "requestMaxThreadPoolSize";
/**
* Name of axis2.xml threadKeepAliveTime parameter for SimpleHTTPServer configuration
*/
public static final String PARAMETER_THREAD_KEEP_ALIVE_TIME = "threadKeepAliveTime";
/**
* Name of axis2.xml threadKeepAliveTimeUnit parameter for SimpleHTTPServer configuration
*/
public static final String PARAMETER_THREAD_KEEP_ALIVE_TIME_UNIT = "threadKeepAliveTimeUnit";
private ConfigurationContext configurationContext;
private TransportInDescription httpConfiguration;
private int port;
private String hostAddress;
private String originServer;
private int requestSocketTimeout;
private boolean requestTcpNoDelay;
private int requestCoreThreadPoolSize;
private int requestMaxThreadPoolSize;
private long threadKeepAliveTime;
private TimeUnit threadKeepAliveTimeUnit;
private WorkerFactory requestWorkerFactory = null;
/**
* Create and configure a new HttpFactory
*/
public HttpFactory(ConfigurationContext configurationContext) throws AxisFault {
this.configurationContext = configurationContext;
httpConfiguration = configurationContext.getAxisConfiguration().getTransportIn(Constants.TRANSPORT_HTTP);
port = getIntParam(PARAMETER_PORT, 6060);
hostAddress = getStringParam(PARAMETER_HOST_ADDRESS, null);
originServer = getStringParam(PARAMETER_ORIGIN_SERVER, "Simple-Server/1.1");
requestSocketTimeout = getIntParam(PARAMETER_REQUEST_SOCKET_TIMEOUT, 20000);
requestTcpNoDelay = getBooleanParam(PARAMETER_REQUEST_TCP_NO_DELAY, true);
requestCoreThreadPoolSize = getIntParam(PARAMETER_REQUEST_CORE_THREAD_POOL_SIZE, 100);
requestMaxThreadPoolSize = getIntParam(PARAMETER_REQUEST_MAX_THREAD_POOL_SIZE, 150);
threadKeepAliveTime = getLongParam(PARAMETER_THREAD_KEEP_ALIVE_TIME, 180L);
threadKeepAliveTimeUnit =
getTimeUnitParam(PARAMETER_THREAD_KEEP_ALIVE_TIME_UNIT, TimeUnit.SECONDS);
}
/**
* Create and configure a new HttpFactory
*/
public HttpFactory(ConfigurationContext configurationContext, int port) throws AxisFault {
this(configurationContext);
this.port = port;
}
/**
* Create and configure a new HttpFactory
*/
public HttpFactory(ConfigurationContext configurationContext, int port,
WorkerFactory requestWorkerFactory) throws AxisFault {
this(configurationContext, port);
this.requestWorkerFactory = requestWorkerFactory;
}
private int getIntParam(String name, int def) {
String config = getStringParam(name, null);
if (config != null) {
return Integer.parseInt(config);
} else {
return def;
}
}
private long getLongParam(String name, long def) {
String config = getStringParam(name, null);
if (config != null) {
return Long.parseLong(config);
} else {
return def;
}
}
private boolean getBooleanParam(String name, boolean def) throws AxisFault {
String config = getStringParam(name, null);
if (config != null) {
if (config.equals("yes") || config.equals("true")) {
return true;
} else if (config.equals("no") || config.equals("false")) {
return false;
} else {
throw new AxisFault("Boolean value must be yes, true, no or false for parameter " +
name + ": " + config);
}
}
return def;
}
private TimeUnit getTimeUnitParam(String name, TimeUnit def) throws AxisFault {
String config = getStringParam(name, null);
if (config != null) {
try {
return (TimeUnit) TimeUnit.class.getField(config).get(null);
} catch (Exception e) {
throw AxisFault.makeFault(e);
}
}
return def;
}
private String getStringParam(String name, String def) {
Parameter param = httpConfiguration.getParameter(name);
if (param != null) {
// assert param.getParameterType() == Parameter.TEXT_PARAMETER;
String config = (String) param.getValue();
if (config != null) {
return config;
}
}
return def;
}
/**
* Return the configured listener manager or create and configure one with configurationContext
*/
public ListenerManager getListenerManager() {
return configurationContext.getListenerManager();
}
/**
* Create the executor used to launch the single requestConnectionListener
*/
public ExecutorService newListenerExecutor(int port) {
return new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(),
new DefaultThreadFactory(
new ThreadGroup("Listener thread group"),
"HttpListener-" + this.port));
}
/**
* Create the listener for request connections
*/
public IOProcessor newRequestConnectionListener(
int port,
final HttpConnectionManager manager,
final HttpParams params) throws IOException {
return new DefaultConnectionListener(
port,
manager,
new DefaultConnectionListenerFailureHandler(),
params);
}
/**
* Create and set the parameters applied to incoming request connections
*/
public HttpParams newRequestConnectionParams() {
HttpParams params = new BasicHttpParams();
params
.setIntParameter(HttpConnectionParams.SO_TIMEOUT, requestSocketTimeout)
.setBooleanParameter(HttpConnectionParams.TCP_NODELAY, requestTcpNoDelay)
.setIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, 4000)
.setIntParameter(HttpConnectionParams.MAX_HEADER_COUNT, 500)
.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8 * 1024)
.setParameter(HttpProtocolParams.ORIGIN_SERVER, originServer);
return params;
}
/**
* Create the connection manager used to launch request threads
*/
public HttpConnectionManager newRequestConnectionManager(ExecutorService requestExecutor,
WorkerFactory workerFactory,
HttpParams params) {
return new DefaultHttpConnectionManager(configurationContext, requestExecutor,
workerFactory, params);
}
/**
* Create the executor use the manage request processing threads
*/
public ExecutorService newRequestExecutor(int port) {
return new ThreadPoolExecutor(requestCoreThreadPoolSize, requestMaxThreadPoolSize,
threadKeepAliveTime, threadKeepAliveTimeUnit,
newRequestBlockingQueue(),
new DefaultThreadFactory(
new ThreadGroup("Connection thread group"),
"HttpConnection-" + port));
}
/**
* Create the queue used to hold incoming requests when requestCoreThreadPoolSize threads are busy.
* Default is an unbounded queue.
*/
public BlockingQueue newRequestBlockingQueue() {
return new LinkedBlockingQueue();
}
/**
* Create the factory for request workers
*/
public WorkerFactory newRequestWorkerFactory() {
if (requestWorkerFactory != null) {
return requestWorkerFactory;
} else {
return new HTTPWorkerFactory();
}
}
public HttpProcessor newHttpProcessor() {
BasicHttpProcessor httpProcessor = new BasicHttpProcessor();
httpProcessor.addInterceptor(new RequestSessionCookie());
httpProcessor.addInterceptor(new ResponseDate());
httpProcessor.addInterceptor(new ResponseServer());
httpProcessor.addInterceptor(new ResponseContent());
httpProcessor.addInterceptor(new ResponseConnControl());
httpProcessor.addInterceptor(new ResponseSessionCookie());
return httpProcessor;
}
public ConnectionReuseStrategy newConnStrategy() {
return new DefaultConnectionReuseStrategy();
}
public HttpResponseFactory newResponseFactory() {
return new DefaultHttpResponseFactory();
}
// *****
// Getters and Setters
// *****
/**
* Getter for configurationContext
*/
public ConfigurationContext getConfigurationContext() {
return configurationContext;
}
/**
* Getter for httpConfiguration
*/
public TransportInDescription getHttpConfiguration() {
return httpConfiguration;
}
/**
* Getter for port
* return the port on which to listen for http connections (default = 6060)
*/
public int getPort() {
return port;
}
/**
* Setter for port
*/
public void setPort(int port) {
this.port = port;
}
/**
* Getter for hostAddress
*
* @return the host address (or name) to be use in reply-to endpoint references, or null if not specified (default = null)
*/
public String getHostAddress() {
return hostAddress;
}
/**
* Setter for hostAddress
*/
public void setHostAddress(String hostAddress) {
this.hostAddress = hostAddress;
}
/**
* Getter for originServer
*
* @return the Server header string for outgoing messages (default "Simple-Server/1.1")
*/
public String getOriginServer() {
return originServer;
}
/**
* Setter for originServer
*/
public void setOriginServer(String originServer) {
this.originServer = originServer;
}
/**
* Getter for requestSocketTimeout
*
* @return the maximum time in millis to wait for data on a request socket (default 20000)
*/
public int getRequestSocketTimeout() {
return requestSocketTimeout;
}
/**
* Setter for requestSocketTimeout
*/
public void setRequestSocketTimeout(int requestSocketTimeout) {
this.requestSocketTimeout = requestSocketTimeout;
}
/**
* Getter for requestTcpNoDelay
* return false iff Nagle's algorithm should be used to conserve bandwidth by minimizing segments
* at the cost of latency and performance (default true, i.e. maximize performance at
* the cost of bandwidth)
*/
public boolean getRequestTcpNoDelay() {
return requestTcpNoDelay;
}
/**
* Setter for requestTcpNoDelay
*/
public void setRequestTcpNoDelay(boolean requestTcpNoDelay) {
this.requestTcpNoDelay = requestTcpNoDelay;
}
/**
* Getter for RequestCoreThreadPoolSize
*
* @return the size of the thread pool use to process requests assuming there is adequate queue space (default 25)
*/
public int getRequestCoreThreadPoolSize() {
return requestCoreThreadPoolSize;
}
/**
* Setter for RequestCoreThreadPoolSize
*/
public void setRequestCoreThreadPoolSize(int requestCoreThreadPoolSize) {
this.requestCoreThreadPoolSize = requestCoreThreadPoolSize;
}
/**
* Getter for requestMaxThreadPoolSize
*
* @return the maximum size of the thread pool used to process requests if the queue fills up (default 150).
* Since the default queue is unbounded this parameter is meaningless unless you override newRequestBlockingQueue()
*/
public int getRequestMaxThreadPoolSize() {
return requestMaxThreadPoolSize;
}
/**
* Setter for requestMaxThreadPoolSize
*/
public void setRequestMaxThreadPoolSize(int requestMaxThreadPoolSize) {
this.requestMaxThreadPoolSize = requestMaxThreadPoolSize;
}
/**
* Getter for threadKeepAliveTime
*
* @return how long a request processing thread in excess of the core pool size will be kept alive it if is inactive
* (default with threadKeepAliveTimeUnit to 180 seconds)
*/
public long getThreadKeepAliveTime() {
return threadKeepAliveTime;
}
/**
* Setter for threadKeepAliveTime
*/
public void setThreadKeepAliveTime(long threadKeepAliveTime) {
this.threadKeepAliveTime = threadKeepAliveTime;
}
/**
* Getter for threadKeepAliveTimeUnit
* return the time unit for threadKeepAliveTime (default SECONDS)
*/
public TimeUnit getThreadKeepAliveTimeUnit() {
return threadKeepAliveTimeUnit;
}
/**
* Setter for threadKeepAliveTimeUnit
*/
public void setThreadKeepAliveTimeUnit(TimeUnit threadKeepAliveTimeUnit) {
this.threadKeepAliveTimeUnit = threadKeepAliveTimeUnit;
}
}