| /* |
| * HttpFactory.java |
| * |
| * ==================================================================== |
| * |
| * Copyright 2006 The Apache Software Foundation |
| * |
| * Licensed 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. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| * Created on May 25, 2006, 10:11 AM |
| * |
| */ |
| |
| package org.apache.axis2.transport.http.server; |
| |
| import edu.emory.mathcs.backport.java.util.concurrent.BlockingQueue; |
| import edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingQueue; |
| import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService; |
| import edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor; |
| import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit; |
| import java.io.IOException; |
| import javax.xml.namespace.QName; |
| 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.HttpServerConnection; |
| import org.apache.http.impl.DefaultHttpParams; |
| import org.apache.http.params.HttpConnectionParams; |
| import org.apache.http.params.HttpParams; |
| import org.apache.http.params.HttpProtocolParams; |
| |
| /** |
| * 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. |
| * |
| * @author Chuck Williams |
| */ |
| 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; |
| |
| private static final QName HTTP_NAME = new QName(Constants.TRANSPORT_HTTP); |
| |
| /** Create and configure a new HttpFactory */ |
| public HttpFactory(ConfigurationContext configurationContext) throws AxisFault { |
| this.configurationContext = configurationContext; |
| httpConfiguration = configurationContext.getAxisConfiguration().getTransportIn(HTTP_NAME); |
| 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, 25); |
| 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 new AxisFault(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() { |
| ListenerManager lm = configurationContext.getListenerManager(); |
| if (lm==null) { |
| lm = new ListenerManager(); |
| lm.init(configurationContext); |
| } |
| return lm; |
| } |
| |
| /** 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(HttpConnectionFactory factory, HttpConnectionManager manager, int port) throws IOException { |
| return new DefaultConnectionListener(port, factory, manager); |
| } |
| |
| /** Create a request connection */ |
| public HttpConnectionFactory newRequestConnectionFactory(HttpParams params) { |
| return new DefaultHttpConnectionFactory(params); |
| } |
| |
| /** Create and set the parameters applied to incoming request connections */ |
| public HttpParams newRequestConnectionParams() { |
| HttpParams params = new DefaultHttpParams(); |
| params |
| .setIntParameter(HttpConnectionParams.SO_TIMEOUT, requestSocketTimeout) |
| .setBooleanParameter(HttpConnectionParams.TCP_NODELAY, requestTcpNoDelay) |
| .setIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, 4000) |
| .setIntParameter(HttpConnectionParams.MAX_HEADER_COUNT, 500) |
| .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(); |
| } |
| |
| /** Create a request service processor to populate the response */ |
| public HttpServiceProcessor newRequestServiceProcessor( |
| final HttpServerConnection connection, |
| final SessionManager sessionManager, |
| final Worker worker, |
| final IOProcessorCallback callback) { |
| return new DefaultHttpServiceProcessor(connection, configurationContext, sessionManager, worker, callback); |
| } |
| |
| // ***** |
| // 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; |
| } |
| |
| } |