/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.server.cluster;
import javax.annotation.PostConstruct;
import com.caucho.cloud.network.ClusterServer;
import com.caucho.cloud.network.NetworkClusterSystem;
import com.caucho.cloud.network.NetworkListenSystem;
import com.caucho.cloud.topology.CloudServer;
import com.caucho.config.Config;
import com.caucho.config.ConfigException;
import com.caucho.config.Configurable;
import com.caucho.config.SchemaBean;
import com.caucho.config.program.ConfigProgram;
import com.caucho.config.types.Bytes;
import com.caucho.config.types.Period;
import com.caucho.env.service.ResinSystem;
import com.caucho.env.thread.ThreadPool;
import com.caucho.loader.EnvironmentBean;
import com.caucho.loader.EnvironmentClassLoader;
import com.caucho.network.listen.TcpSocketLinkListener;
import com.caucho.rewrite.DispatchRule;
import com.caucho.server.admin.Management;
import com.caucho.server.cache.AbstractProxyCache;
import com.caucho.server.distcache.PersistentStoreConfig;
import com.caucho.server.e_app.EarConfig;
import com.caucho.server.host.HostConfig;
import com.caucho.server.host.HostExpandDeployGenerator;
import com.caucho.server.log.AccessLog;
import com.caucho.server.resin.Resin;
import com.caucho.server.rewrite.RewriteDispatch;
import com.caucho.server.rewrite.RewriteRule;
import com.caucho.server.webapp.ErrorPage;
import com.caucho.server.webapp.WebAppConfig;
import com.caucho.util.L10N;
import com.caucho.vfs.Path;
import com.caucho.vfs.Vfs;
/**
* Configuration for the <cluster> and <server> tags.
*/
@Configurable
public class ServletContainerConfig implements EnvironmentBean, SchemaBean
{
private static final L10N L = new L10N(ServletContainerConfig.class);
private final ResinSystem _resinSystem;
private final Resin _resin;
private PersistentStoreConfig _persistentStoreConfig;
// <host> configuration
// <cluster> configuration
// backwards compat
private long _memoryFreeMin = 1024 * 1024;
private long _permGenFreeMin = 1024 * 1024;
private int _threadMax = 4096;
private int _threadExecutorTaskMax = -1;
private int _threadIdleMin = -1;
private int _threadIdleMax = -1;
private long _threadIdleTimeout = -1;
private CloudServer _selfServer;
private Server _servletContainer;
/**
* Creates a new servlet server.
*/
public ServletContainerConfig(Server servletContainer)
{
_servletContainer = servletContainer;
_resinSystem = servletContainer.getResinSystem();
_resin = servletContainer.getResin();
_selfServer = NetworkClusterSystem.getCurrentSelfServer();
Config.setProperty("server", new ServerVar(_selfServer), getClassLoader());
Config.setProperty("cluster", new ClusterVar(), getClassLoader());
}
public ResinSystem getResinSystem()
{
return _resinSystem;
}
/**
* Returns the classLoader
*/
@Override
public EnvironmentClassLoader getClassLoader()
{
return _resinSystem.getClassLoader();
}
/**
* Returns the relax schema.
*/
@Override
public String getSchema()
{
return "com/caucho/server/resin/cluster.rnc";
}
//
// <cluster> configuration
//
/**
* Development mode error pages.
*/
@Configurable
public void setDevelopmentModeErrorPage(boolean isEnable)
{
_servletContainer.setDevelopmentModeErrorPage(isEnable);
}
/**
* Creates a persistent store instance.
*/
@Configurable
public PersistentStoreConfig createPersistentStore()
{
if (_persistentStoreConfig == null) {
_persistentStoreConfig = new PersistentStoreConfig();
_servletContainer.setPersistentStore(_persistentStoreConfig);
}
return _persistentStoreConfig;
}
/**
* Creates a persistent store instance.
*/
public PersistentStoreConfig getPersistentStoreConfig()
{
return _persistentStoreConfig;
}
public void startPersistentStore()
{
}
@Configurable
public Object createJdbcStore()
throws ConfigException
{
return null;
}
/**
* Arguments on boot
*/
@Configurable
public void addJavaExe(String args)
{
}
/**
* Arguments on boot
*/
@Configurable
public void addJvmArg(String args)
{
}
/**
* Arguments on boot
*/
@Configurable
public void addJvmArgLine(String args)
{
}
/**
* Arguments on boot
*/
@Configurable
public void addJvmClasspath(String args)
{
}
/**
* Sets the stage id
*/
@Configurable
public void setStage(String stage)
{
if (stage == null || "".equals(stage))
stage = "production";
_servletContainer.setStage(stage);
}
/**
* The Resin system classloader
*/
@Configurable
public void setSystemClassLoader(String loader)
{
}
/**
* Arguments on boot
*/
@Configurable
public void addWatchdogArg(String args)
{
}
/**
* Arguments on boot
*/
@Configurable
public void addWatchdogJvmArg(String args)
{
}
/**
* Arguments on boot
*/
@Configurable
public void addWatchdogLog(ConfigProgram args)
{
}
/**
* Arguments on boot
*/
@Configurable
public void addWatchdogPassword(String args)
{
}
/**
* Arguments on boot
*/
@Configurable
public void addWatchdogPort(int port)
{
}
@Configurable
public void setDynamicServerEnable(boolean isEnable)
{
}
/**
* Sets the minimum free memory after a GC
*/
@Configurable
public void setMemoryFreeMin(Bytes min)
{
_memoryFreeMin = min.getBytes();
}
/**
* Sets the minimum free memory after a GC
*/
public long getMemoryFreeMin()
{
return _memoryFreeMin;
}
/**
* Sets the minimum free memory after a GC
*/
@Configurable
public void setPermGenFreeMin(Bytes min)
{
_permGenFreeMin = min.getBytes();
}
/**
* Sets the minimum free memory after a GC
*/
public long getPermGenFreeMin()
{
return _permGenFreeMin;
}
@Configurable
public Management createManagement()
{
if (_resin != null)
return _resin.createResinManagement();
else
return null;
/*
if (_management == null && _resin != null) {
_management = _resin.createResinManagement();
// _management.setCluster(getCluster());
}
return _management;
*/
}
/**
* Sets the redeploy mode
*/
@Configurable
public void setRedeployMode(String redeployMode)
{
}
/**
* Sets the max wait time for shutdown.
*/
@Configurable
public void setShutdownWaitMax(Period waitTime)
{
_servletContainer.setShutdownWaitMax(waitTime);
}
@Configurable
public void setInvocationCacheSize(int count)
{
_servletContainer.getInvocationServer().setInvocationCacheSize(count);
}
/**
* Sets the maximum thread-based keepalive
*/
@Configurable
public void setThreadMax(int max)
{
if (max < 0)
throw new ConfigException(L.l("<thread-max> ({0}) must be greater than zero.",
max));
_threadMax = max;
}
/**
* Sets the maximum executor (background) thread.
*/
@Configurable
public void setThreadExecutorTaskMax(int max)
{
_threadExecutorTaskMax = max;
}
/**
* Sets the minimum number of idle threads in the thread pool.
*/
@Configurable
public void setThreadIdleMin(int min)
{
_threadIdleMin = min;
}
/**
* Sets the maximum number of idle threads in the thread pool.
*/
@Configurable
public void setThreadIdleMax(int max)
{
_threadIdleMax = max;
}
@Configurable
public void setThreadIdleTimeout(Period timeout)
{
_threadIdleTimeout = timeout.getPeriod();
}
//
// Configuration from <cluster>
//
/**
* Sets the connection error page.
*/
@Configurable
public void setConnectionErrorPage(String errorPage)
{
_servletContainer.setConnectionErrorPage(errorPage);
}
/**
* Sets the root directory.
*/
@Configurable
public void setRootDirectory(Path path)
{
_servletContainer.setRootDirectory(path);
Vfs.setPwd(path, getClassLoader());
}
/**
* Sets the root directory.
*/
@Configurable
public void setRootDir(Path path)
{
setRootDirectory(path);
}
/**
* Sets the server header.
*/
@Configurable
public void setServerHeader(String serverHeader)
{
_servletContainer.setServerHeader(serverHeader);
}
/**
* Sets the url-length-max
*/
@Configurable
public void setUrlLengthMax(int max)
{
_servletContainer.setUrlLengthMax(max);
}
/**
* Sets the url-length-max
*/
@Configurable
public void setMaxUriLength(int max)
{
setUrlLengthMax(max);
}
@Configurable
public void setIgnoreClientDisconnect(boolean isIgnore)
{
_servletContainer.setIgnoreClientDisconnect(isIgnore);
}
/**
* Adds a WebAppDefault.
*/
@Configurable
public void addWebAppDefault(WebAppConfig webAppConfig)
{
_servletContainer.addWebAppDefault(webAppConfig);
}
/**
* Adds an EarDefault
*/
@Configurable
public void addEarDefault(EarConfig earConfig)
{
_servletContainer.addEarDefault(earConfig);
}
/**
* Adds a HostDefault.
*/
@Configurable
public void addHostDefault(HostConfig hostConfig)
{
_servletContainer.addHostDefault(hostConfig);
}
/**
* Adds a HostDeploy.
*/
@Configurable
public HostExpandDeployGenerator createHostDeploy()
{
return _servletContainer.createHostDeploy();
}
/**
* Adds a HostDeploy.
*/
@Configurable
public void addHostDeploy(HostExpandDeployGenerator deploy)
{
_servletContainer.addHostDeploy(deploy);
}
/**
* Adds the host.
*/
@Configurable
public void addHost(HostConfig host)
{
_servletContainer.addHost(host);
}
/**
* Adds rewrite-dispatch.
*/
@Configurable
public RewriteDispatch createRewriteDispatch()
{
return _servletContainer.createRewriteDispatch();
}
@Configurable
public void add(DispatchRule rewrite)
{
_servletContainer.add(rewrite);
}
/**
* Creates the proxy cache.
*/
@Configurable
public AbstractProxyCache createProxyCache()
throws ConfigException
{
return _servletContainer.createProxyCache();
}
/**
* backward compatibility for proxy cache
*/
@Configurable
public AbstractProxyCache createCache()
throws ConfigException
{
return createProxyCache();
}
/**
* Sets the access log.
*/
@Configurable
public void setAccessLog(AccessLog accessLog)
{
_servletContainer.setAccessLog(accessLog);
}
/**
* Sets the session cookie
*/
@Configurable
public void setSessionCookie(String sessionCookie)
{
_servletContainer.setSessionCookie(sessionCookie);
}
/**
* Sets the ssl session cookie
*/
@Configurable
public void setSSLSessionCookie(String cookie)
{
_servletContainer.setSSLSessionCookie(cookie);
}
/**
* Sets the session url prefix.
*/
@Configurable
public void setSessionUrlPrefix(String urlPrefix)
{
_servletContainer.setSessionURLPrefix(urlPrefix);
}
/**
* Sets the alternate session url prefix.
*/
@Configurable
public void setAlternateSessionUrlPrefix(String urlPrefix)
throws ConfigException
{
_servletContainer.setAlternateSessionURLPrefix(urlPrefix);
}
/**
* Sets URL encoding.
*/
@Configurable
public void setUrlCharacterEncoding(String encoding)
throws ConfigException
{
_servletContainer.setURLCharacterEncoding(encoding);
}
/**
* Creates the ping.
*/
public Object createPing()
throws ConfigException
{
return createManagement().createPing();
}
public void addSelectManager(SelectManagerCompat selectManager)
{
}
/**
* Adds an error page
*/
public void addErrorPage(ErrorPage errorPage)
{
_servletContainer.addErrorPage(errorPage);
}
public void addLoadBalanceWeight(ConfigProgram program)
{
}
public void setLoadBalanceWarmupTime(ConfigProgram program)
{
}
/**
* Initialization.
*/
@PostConstruct
public void init()
{
if (_threadIdleMax > 0
&& _threadMax > 0
&& _threadMax < _threadIdleMax)
throw new ConfigException(L.l("<thread-idle-max> ({0}) must be less than <thread-max> ({1})",
_threadIdleMax, _threadMax));
if (_threadIdleMin > 0
&& _threadIdleMax > 0
&& _threadIdleMax < _threadIdleMin)
throw new ConfigException(L.l("<thread-idle-min> ({0}) must be less than <thread-idle-max> ({1})",
_threadIdleMin, _threadIdleMax));
if (_threadMax > 0
&& _threadExecutorTaskMax > 0
&& _threadMax < _threadExecutorTaskMax)
throw new ConfigException(L.l("<thread-executor-task-max> ({0}) must be less than <thread-max> ({1})",
_threadExecutorTaskMax, _threadMax));
ThreadPool threadPool = ThreadPool.getThreadPool();
if (_threadMax > 0)
threadPool.setThreadMax(_threadMax);
if (_threadIdleMin > 0)
threadPool.setIdleMin(_threadIdleMin);
if (_threadIdleTimeout > 0)
threadPool.setIdleTimeout(_threadIdleTimeout);
threadPool.setExecutorTaskMax(_threadExecutorTaskMax);
/*
if (_keepaliveSelectEnable) {
try {
Class<?> cl = Class.forName("com.caucho.server.connection.JniSelectManager");
Method method = cl.getMethod("create", new Class[0]);
initSelectManager((AbstractSelectManager) method.invoke(null, null));
} catch (ClassNotFoundException e) {
log.warning(L.l("'select-manager' requires Resin Professional. See http://www.caucho.com for information and licensing."));
} catch (Throwable e) {
log.warning(L.l("Cannot enable select-manager {0}", e.toString()));
log.log(Level.FINER, e.toString());
}
if (getSelectManager() != null) {
if (_keepaliveSelectMax > 0)
getSelectManager().setSelectMax(_keepaliveSelectMax);
}
}
*/
}
/**
* EL variables
*/
public class ClusterVar {
/**
* Returns the resin.id
*/
public String getId()
{
return _selfServer.getCluster().getId();
}
/**
* Returns the root directory.
*
* @return root directory
*/
public Path getRoot()
{
return getRootDirectory();
}
/**
* Returns the root directory.
*
* @return root directory
*/
public Path getRootDir()
{
return getRootDirectory();
}
/**
* Returns the root directory.
*
* @return root directory
*/
public Path getRootDirectory()
{
return _servletContainer.getRootDirectory();
}
}
public class ServerVar {
private final ClusterServer _server;
public ServerVar(CloudServer server)
{
ClusterServer clusterServer = server.getData(ClusterServer.class);
if (clusterServer == null)
throw new NullPointerException();
_server = clusterServer;
}
public String getId()
{
return _server.getId();
}
private int getPort(TcpSocketLinkListener port)
{
if (port == null)
return 0;
return port.getPort();
}
private String getAddress(TcpSocketLinkListener port)
{
if (port == null)
return null;
String address = port.getAddress();
if (address == null || address.length() == 0)
address = "INADDR_ANY";
return address;
}
private TcpSocketLinkListener getFirstPort(String protocol, boolean isSSL)
{
ResinSystem resinSystem = getResinSystem();
NetworkListenSystem listenService
= resinSystem.getService(NetworkListenSystem.class);
for (TcpSocketLinkListener port : listenService.getListeners()) {
if (protocol.equals(port.getProtocolName()) && (port.isSSL() == isSSL))
return port;
}
return null;
}
public String getAddress()
{
return _selfServer.getAddress();
}
public int getPort()
{
return _selfServer.getPort();
}
public String getHttpAddress()
{
return getAddress(getFirstPort("http", false));
}
public int getHttpPort()
{
return getPort(getFirstPort("http", false));
}
public String getHttpsAddress()
{
return getAddress(getFirstPort("http", true));
}
public int getHttpsPort()
{
return getPort(getFirstPort("http", true));
}
/**
* @deprecated backwards compat.
*/
public Path getRoot()
{
Resin resin = Resin.getLocal();
return resin == null ? Vfs.getPwd() : resin.getRootDirectory();
}
}
public static class SelectManagerCompat {
private boolean _isEnable = true;
public void setEnable(boolean isEnable)
{
_isEnable = isEnable;
}
public boolean isEnable()
{
return _isEnable;
}
}
}