/*
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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.synapse.transport.passthru.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.transport.passthru.PassThroughConstants;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* This class encapsulates pass-through http transport tuning configurations specified via a
* configurations file or system properties.
*/
public class PassThroughConfiguration {
/**
* Default tuning parameter values
*/
private static final int DEFAULT_WORKER_POOL_SIZE_CORE = 40;
private static final int DEFAULT_WORKER_POOL_SIZE_MAX = 200;
private static final int DEFAULT_WORKER_THREAD_KEEPALIVE_SEC = 60;
private static final int DEFAULT_WORKER_POOL_QUEUE_LENGTH = -1;
private static final int DEFAULT_IO_BUFFER_SIZE = 8 * 1024;
private static final int DEFAULT_IO_THREADS_PER_REACTOR =
Runtime.getRuntime().availableProcessors();
private static final int DEFAULT_MAX_ACTIVE_CON = -1;
private static final int DEFAULT_LISTENER_SHUTDOWN_WAIT_TIME = 0;
//additional rest dispatch handlers
private static final String REST_DISPATCHER_SERVICE="rest.dispatcher.service";
// URI configurations that determine if it requires custom rest dispatcher
private static final String REST_URI_API_REGEX = "rest_uri_api_regex";
private static final String REST_URI_PROXY_REGEX = "rest_uri_proxy_regex";
private static final Log log = LogFactory.getLog(PassThroughConfiguration.class);
private static PassThroughConfiguration _instance = new PassThroughConfiguration();
private Properties props;
private PassThroughConfiguration() {
try {
props = loadProperties("passthru-http.properties");
} catch (Exception ignored) {}
}
public static PassThroughConfiguration getInstance() {
return _instance;
}
public int getWorkerPoolCoreSize() {
return getIntProperty(PassThroughConfigPNames.WORKER_POOL_SIZE_CORE,
DEFAULT_WORKER_POOL_SIZE_CORE);
}
public int getWorkerPoolMaxSize() {
return getIntProperty(PassThroughConfigPNames.WORKER_POOL_SIZE_MAX,
DEFAULT_WORKER_POOL_SIZE_MAX);
}
public int getWorkerThreadKeepaliveSec() {
return getIntProperty(PassThroughConfigPNames.WORKER_THREAD_KEEP_ALIVE_SEC,
DEFAULT_WORKER_THREAD_KEEPALIVE_SEC);
}
public int getWorkerPoolQueueLen() {
return getIntProperty(PassThroughConfigPNames.WORKER_POOL_QUEUE_LENGTH,
DEFAULT_WORKER_POOL_QUEUE_LENGTH);
}
public int getIOThreadsPerReactor() {
return getIntProperty(PassThroughConfigPNames.IO_THREADS_PER_REACTOR,
DEFAULT_IO_THREADS_PER_REACTOR);
}
public int getIOBufferSize() {
return getIntProperty(PassThroughConfigPNames.IO_BUFFER_SIZE,
DEFAULT_IO_BUFFER_SIZE);
}
public boolean isKeepAliveDisabled() {
return getBooleanProperty(PassThroughConfigPNames.DISABLE_KEEPALIVE, false);
}
public int getMaxActiveConnections() {
return getIntProperty(PassThroughConfigPNames.C_MAX_ACTIVE, DEFAULT_MAX_ACTIVE_CON);
}
public int getListenerShutdownWaitTime() {
return getIntProperty(PassThroughConfigPNames.TRANSPORT_LISTENER_SHUTDOWN_WAIT_TIME_SEC,
DEFAULT_LISTENER_SHUTDOWN_WAIT_TIME)*1000;
}
public boolean isPreserveUserAgentHeader() {
return getBooleanProperty(PassThroughConfigPNames.USER_AGENT_HEADER_PRESERVE, false);
}
public boolean isPreserveServerHeader() {
return getBooleanProperty(PassThroughConfigPNames.SERVER_HEADER_PRESERVE, false);
}
public String getPreserveHttpHeaders() {
return getStringProperty(PassThroughConfigPNames.HTTP_HEADERS_PRESERVE, "");
}
/**
* Loads the properties from a given property file path
*
* @param filePath Path of the property file
* @return Properties loaded from given file
*/
private static Properties loadProperties(String filePath) {
Properties properties = new Properties();
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (log.isDebugEnabled()) {
log.debug("Loading the file '" + filePath + "' from classpath");
}
InputStream in = null;
//if we reach to this assume that the we may have to looking to the customer provided external location for the
//given properties
if (System.getProperty(PassThroughConstants.CONF_LOCATION) != null) {
try {
in = new FileInputStream(System.getProperty(PassThroughConstants.CONF_LOCATION) + File.separator + filePath);
} catch (FileNotFoundException e) {
String msg = "Error loading properties from a file at from the System defined location: " + filePath;
log.warn(msg);
}
}
if (in == null) {
in = cl.getResourceAsStream(filePath);
if (log.isDebugEnabled()) {
log.debug("Unable to load file '" + filePath + "'");
}
filePath = "conf" + File.separatorChar + filePath;
if (log.isDebugEnabled()) {
log.debug("Loading the file '" + filePath + "'");
}
in = cl.getResourceAsStream(filePath);
if (in == null) {
if (log.isDebugEnabled()) {
log.debug("Unable to load file '" + filePath + "'");
}
}
}
if (in != null) {
try {
properties.load(in);
} catch (IOException e) {
String msg = "Error loading properties from a file at : " + filePath;
log.error(msg, e);
}
}
return properties;
}
/**
* Get an int property that tunes pass-through http transport. Prefer system properties
*
* @param name name of the system/config property
* @param def default value to return if the property is not set
* @return the value of the property to be used
*/
public Integer getIntProperty(String name, Integer def) {
String val = System.getProperty(name);
if (val == null) {
val = props.getProperty(name);
}
if (val != null) {
int intVal;
try {
intVal = Integer.valueOf(val);
} catch (NumberFormatException e) {
log.warn("Invalid pass-through http tuning property value. " + name +
" must be an integer");
return def;
}
if (log.isDebugEnabled()) {
log.debug("Using pass-through http tuning parameter : " + name + " = " + val);
}
return intVal;
}
return def;
}
/**
* Get an int property that tunes pass-through http transport. Prefer system properties
*
* @param name name of the system/config property
* @return the value of the property, null if the property is not found
*/
public Integer getIntProperty(String name) {
return getIntProperty(name, null);
}
/**
* Get a boolean property that tunes pass-through http transport. Prefer system properties
*
* @param name name of the system/config property
* @param def default value to return if the property is not set
* @return the value of the property to be used
*/
public Boolean getBooleanProperty(String name, Boolean def) {
String val = System.getProperty(name);
if (val == null) {
val = props.getProperty(name);
}
if (val != null) {
if (log.isDebugEnabled()) {
log.debug("Using pass-through http tuning parameter : " + name + " = " + val);
}
return Boolean.valueOf(val);
}
return def;
}
/**
* Get a Boolean property that tunes pass-through http transport. Prefer system properties
*
* @param name name of the system/config property
* @return the value of the property, null if the property is not found
*/
public Boolean getBooleanProperty(String name) {
return getBooleanProperty(name, null);
}
/**
* Get a String property that tunes pass-through http transport. Prefer system properties
*
* @param name name of the system/config property
* @param def default value to return if the property is not set
* @return the value of the property to be used
*/
public String getStringProperty(String name, String def) {
String val = System.getProperty(name);
if (val == null) {
val = props.getProperty(name);
}
return val == null ? def : val;
}
public String getRESTDispatchService() {
return getStringProperty(REST_DISPATCHER_SERVICE,"");
}
public String getRestUriApiRegex() {
return getStringProperty(REST_URI_API_REGEX, "");
}
public String getRestUriProxyRegex() {
return getStringProperty(REST_URI_PROXY_REGEX, "");
}
public boolean isListeningIOReactorShared(){
return getBooleanProperty(PassThroughConfigPNames.HTTP_LISTENING_IO_REACTOR_SHARING_ENABLE, false);
}
}