/* * 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 java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletResponse; import com.caucho.VersionFactory; import com.caucho.bam.actor.ActorSender; import com.caucho.bam.broker.Broker; import com.caucho.bam.broker.ManagedBroker; import com.caucho.bam.manager.BamManager; import com.caucho.bam.stream.MessageStream; import com.caucho.cloud.bam.BamSystem; import com.caucho.cloud.network.ClusterServer; import com.caucho.cloud.network.NetworkClusterSystem; import com.caucho.cloud.topology.CloudCluster; import com.caucho.cloud.topology.CloudPod; import com.caucho.config.ConfigException; import com.caucho.config.inject.InjectManager; import com.caucho.config.types.Period; import com.caucho.distcache.ClusterCache; import com.caucho.env.service.ResinSystem; import com.caucho.env.shutdown.ExitCode; import com.caucho.env.shutdown.ShutdownSystem; import com.caucho.env.thread.ThreadPool; import com.caucho.hemp.broker.HempBrokerManager; import com.caucho.hemp.servlet.ServerAuthManager; import com.caucho.lifecycle.Lifecycle; import com.caucho.loader.ClassLoaderListener; import com.caucho.loader.DynamicClassLoader; import com.caucho.loader.Environment; import com.caucho.loader.EnvironmentClassLoader; import com.caucho.loader.EnvironmentLocal; import com.caucho.make.AlwaysModified; import com.caucho.management.server.EnvironmentMXBean; import com.caucho.management.server.ServerMXBean; import com.caucho.rewrite.DispatchRule; import com.caucho.security.AdminAuthenticator; import com.caucho.security.PermissionManager; import com.caucho.server.cache.AbstractProxyCache; import com.caucho.server.dispatch.ErrorFilterChain; import com.caucho.server.dispatch.ExceptionFilterChain; import com.caucho.server.dispatch.Invocation; import com.caucho.server.dispatch.InvocationBuilder; import com.caucho.server.dispatch.InvocationDecoder; import com.caucho.server.dispatch.InvocationMatcher; import com.caucho.server.dispatch.InvocationServer; import com.caucho.server.distcache.CacheConfig; import com.caucho.server.distcache.PersistentStoreConfig; import com.caucho.server.e_app.EarConfig; import com.caucho.server.host.Host; import com.caucho.server.host.HostConfig; import com.caucho.server.host.HostContainer; import com.caucho.server.host.HostController; import com.caucho.server.host.HostExpandDeployGenerator; import com.caucho.server.http.HttpBufferStore; import com.caucho.server.log.AccessLog; import com.caucho.server.resin.Resin; import com.caucho.server.rewrite.RewriteDispatch; import com.caucho.server.webapp.ErrorPage; import com.caucho.server.webapp.ErrorPageManager; import com.caucho.server.webapp.WebApp; import com.caucho.server.webapp.WebAppConfig; import com.caucho.util.Alarm; import com.caucho.util.AlarmListener; import com.caucho.util.FreeList; import com.caucho.util.L10N; import com.caucho.vfs.Dependency; import com.caucho.vfs.Path; import com.caucho.vfs.Vfs; public class Server implements AlarmListener, ClassLoaderListener, InvocationBuilder, Dependency { private static final L10N L = new L10N(Server.class); private static final Logger log = Logger.getLogger(Server.class.getName()); private static final long ALARM_INTERVAL = 60000; private static final EnvironmentLocal<String> _serverIdLocal = new EnvironmentLocal<String>("caucho.server-id"); private static final EnvironmentLocal<Server> _serverLocal = new EnvironmentLocal<Server>(); private final Resin _resin; private final ResinSystem _resinSystem; private final NetworkClusterSystem _clusterService; private final ClusterServer _selfServer; private Throwable _configException; private ServerAuthManager _authManager; private AdminAuthenticator _adminAuth; private InjectManager _cdiManager; private BamSystem _bamService; private InvocationServer _invocationServer; private HostContainer _hostContainer; private ErrorPageManager _errorPageManager = new ErrorPageManager(this); private String _stage = "production"; private boolean _isPreview; private String _serverHeader; private int _urlLengthMax = 8192; private long _waitForActiveTime = 10000L; private boolean _isDevelopmentModeErrorPage; private long _shutdownWaitMax = 60 * 1000; private boolean _isIgnoreClientDisconnect = true; // <cluster> configuration private String _connectionErrorPage; private ServerAdmin _admin; private Alarm _alarm; private AbstractProxyCache _proxyCache; private PersistentStoreConfig _persistentStoreConfig; private final FreeList<HttpBufferStore> _httpBufferFreeList = new FreeList<HttpBufferStore>(256); // // internal databases // // reliable system store private ClusterCache _systemStore; // private GlobalCache _globalStore; // stats private long _startTime; private final Lifecycle _lifecycle; /** * Creates a new servlet server. */ public Server(Resin resin, ResinSystem resinSystem, NetworkClusterSystem clusterService) { if (resin == null) throw new NullPointerException(); if (resinSystem == null) throw new NullPointerException(); if (clusterService == null) throw new NullPointerException(); _resin = resin; _resinSystem = resinSystem; _clusterService = clusterService; _invocationServer = new InvocationServer(this); _selfServer = _clusterService.getSelfServer().getData(ClusterServer.class); // pod id can't include the server since it's used as part of // cache ids //String podId // = (cluster.getId() + ":" + _selfServer.getClusterPod().getId()); String id = _selfServer.getId(); if ("".equals(id)) throw new IllegalStateException(); // cannot set the based on server-id because of distributed cache // _classLoader.setId("server:" + id); _serverLocal.set(this, getClassLoader()); if (! Alarm.isTest()) _serverHeader = "Resin/" + VersionFactory.getVersion(); else _serverHeader = "Resin/1.1"; try { Thread thread = Thread.currentThread(); Environment.addClassLoaderListener(this, getClassLoader()); PermissionManager permissionManager = new PermissionManager(); PermissionManager.setPermissionManager(permissionManager); ClassLoader oldLoader = thread.getContextClassLoader(); try { thread.setContextClassLoader(getClassLoader()); _serverIdLocal.set(_selfServer.getId()); _lifecycle = new Lifecycle(log, toString(), Level.INFO); preInit(); } finally { thread.setContextClassLoader(oldLoader); } } catch (Exception e) { log.log(Level.WARNING, e.toString(), e); // exceptions here must throw to the top because they're non-recoverable throw ConfigException.create(e); } } protected void preInit() { _cdiManager = InjectManager.create(); _hostContainer = new HostContainer(this); _alarm = new Alarm(this); _bamService = BamSystem.getCurrent(); _authManager = new ServerAuthManager(); // XXX: _authManager.setAuthenticationRequired(false); _bamService.setLinkManager(_authManager); // _resinSystem.addService(new DeployUpdateService()); // _selfServer.getServerProgram().configure(this); } /** * Returns the current server */ public static Server getCurrent() { return _serverLocal.get(); } public ResinSystem getResinSystem() { return _resinSystem; } public boolean isResinServer() { if (_resin != null) return _resin.isResinServer(); else return false; } public String getUniqueServerName() { return _resin.getUniqueServerName(); } /** * Returns the classLoader */ public EnvironmentClassLoader getClassLoader() { return _resinSystem.getClassLoader(); } /** * Returns the configuration exception */ public Throwable getConfigException() { return _configException; } /** * Returns the configuration instance. */ public void setConfigException(Throwable exn) { _configException = exn; } /** * Returns the resin server */ public Resin getResin() { return _resin; } /** * Returns true for the watchdog server. */ public boolean isWatchdog() { return getResin().isWatchdog(); } /** * Returns the cluster */ public CloudCluster getCluster() { return _selfServer.getCluster(); } /** * Returns all the clusters */ public CloudCluster []getClusterList() { return _selfServer.getCluster().getSystem().getClusterList(); } public NetworkClusterSystem getClusterService() { return _clusterService; } /** * Returns the admin path */ public Path getResinDataDirectory() { return _resin.getResinDataDirectory(); } /** * Creates the bam broker manager */ protected HempBrokerManager createBrokerManager() { return new HempBrokerManager(_resinSystem); } /** * Returns the cluster server */ protected ClusterServer getClusterServer() { return getSelfServer(); } /** * Returns the self server */ public ClusterServer getSelfServer() { return _selfServer; } /** * Returns the self server's pod */ public CloudPod getPod() { return _selfServer.getCloudServer().getPod(); } /** * Returns the bam broker. */ public ManagedBroker getBamBroker() { return _bamService.getBroker(); } /** * Returns the bam broker. */ public ManagedBroker getAdminBroker() { return getBamBroker(); } /** * Returns the bam broker. */ public BamManager getAdminBrokerManager() { return _bamService.getBrokerManager(); } /** * Creates a bam client to the admin. */ public ActorSender createAdminClient(String uid) { return createAdminClient(uid, null); } /** * Creates a bam client to the admin. */ public ActorSender createAdminClient(String uid, String resource) { return getAdminBrokerManager().createClient(uid, resource); } /** * Returns the bam name. */ public String getBamAdminName() { return getClusterServer().getBamAdminName(); } /** * Returns the admin broker. */ public Broker getBroker() { return _bamService.getBroker(); } public AdminAuthenticator getAdminAuthenticator() { if (_adminAuth == null) { Thread thread = Thread.currentThread(); ClassLoader oldLoader = thread.getContextClassLoader(); try { thread.setContextClassLoader(getClassLoader()); _adminAuth = _cdiManager.getReference(AdminAuthenticator.class); } catch (Exception e) { if (log.isLoggable(Level.FINEST)) log.log(Level.FINEST, e.toString(), e); else log.finer(e.toString()); _adminAuth = new AdminAuthenticator(); } finally { thread.setContextClassLoader(oldLoader); } } return _adminAuth; } // // <cluster> // /** * Development mode error pages. */ public boolean isDevelopmentModeErrorPage() { return _isDevelopmentModeErrorPage; } /** * Development mode error pages. */ public void setDevelopmentModeErrorPage(boolean isEnable) { _isDevelopmentModeErrorPage = isEnable; } /** * Sets the stage id */ public void setStage(String stage) { if (stage == null || "".equals(stage)) _stage = "production"; else _stage = stage; _isPreview = "preview".equals(_stage); } /** * Returns the stage id */ public String getStage() { return _stage; } /** * Returns true in preview mode */ public boolean isPreview() { return _isPreview; } /** * Sets the max wait time for shutdown. */ public void setShutdownWaitMax(Period waitTime) { _shutdownWaitMax = waitTime.getPeriod(); } /** * Gets the max wait time for a shutdown. */ public long getShutdownWaitMax() { return _shutdownWaitMax; } // // Configuration from <cluster> // /** * Sets the connection error page. */ public void setConnectionErrorPage(String errorPage) { _connectionErrorPage = errorPage; } /** * Gets the connection error page. */ public String getConnectionErrorPage() { return _connectionErrorPage; } /** * Return true if idle. */ public boolean isDeployError() { return _configException != null; } /** * True if client disconnects should be invisible to servlets. */ public boolean isIgnoreClientDisconnect() { return _isIgnoreClientDisconnect; } /** * True if client disconnections should be invisible to servlets. */ public void setIgnoreClientDisconnect(boolean isIgnore) { _isIgnoreClientDisconnect = isIgnore; } /** * Returns the id. */ public String getServerId() { return _selfServer.getId(); } /** * Sets the root directory. */ public void setRootDirectory(Path path) { _hostContainer.setRootDirectory(path); Vfs.setPwd(path, getClassLoader()); } /** * Sets the root directory. */ public Path getRootDirectory() { return _hostContainer.getRootDirectory(); } /** * Sets the server header. */ public void setServerHeader(String server) { _serverHeader = server; } /** * Gets the server header. */ public String getServerHeader() { return _serverHeader; } /** * Sets the url-length-max */ public void setUrlLengthMax(int length) { _urlLengthMax = length; getInvocationDecoder().setMaxURILength(length); } /** * Gets the url-length-max */ public int getUrlLengthMax() { return _urlLengthMax; } /** * Adds a WebAppDefault. */ public void addWebAppDefault(WebAppConfig init) { _hostContainer.addWebAppDefault(init); } /** * Adds an EarDefault */ public void addEarDefault(EarConfig config) { _hostContainer.addEarDefault(config); } /** * Adds a HostDefault. */ public void addHostDefault(HostConfig init) { _hostContainer.addHostDefault(init); } /** * Adds a HostDeploy. */ public HostExpandDeployGenerator createHostDeploy() { return _hostContainer.createHostDeploy(); } /** * Adds a HostDeploy. */ public void addHostDeploy(HostExpandDeployGenerator deploy) { _hostContainer.addHostDeploy(deploy); } /** * Adds the host. */ public void addHost(HostConfig host) { _hostContainer.addHost(host); } /** * Adds rewrite-dispatch. */ public RewriteDispatch createRewriteDispatch() { return _hostContainer.createRewriteDispatch(); } public void add(DispatchRule rewriteRule) { createRewriteDispatch().addRule(rewriteRule); } public AbstractProxyCache getProxyCache() { return _proxyCache; } /** * Creates the proxy cache. */ public AbstractProxyCache createProxyCache() throws ConfigException { if (_proxyCache == null) _proxyCache = instantiateProxyCache(); return _proxyCache; } protected AbstractProxyCache instantiateProxyCache() { log.warning(L.l("<proxy-cache> requires Resin Professional. Please see http://www.caucho.com for Resin Professional information and licensing.")); return new AbstractProxyCache(); } /** * Sets the access log. */ public void setAccessLog(AccessLog log) { Environment.setAttribute("caucho.server.access-log", log); } /** * Returns the dependency check interval. */ public long getDependencyCheckInterval() { return Environment.getDependencyCheckInterval(getClassLoader()); } /** * Sets the session cookie */ public void setSessionCookie(String cookie) { getInvocationDecoder().setSessionCookie(cookie); } /** * Gets the session cookie */ public String getSessionCookie() { return getInvocationDecoder().getSessionCookie(); } /** * Sets the ssl session cookie */ public void setSSLSessionCookie(String cookie) { getInvocationDecoder().setSSLSessionCookie(cookie); } /** * Gets the ssl session cookie */ public String getSSLSessionCookie() { return getInvocationDecoder().getSSLSessionCookie(); } /** * Sets the session url prefix. */ public void setSessionURLPrefix(String urlPrefix) { getInvocationDecoder().setSessionURLPrefix(urlPrefix); } /** * Gets the session url prefix. */ public String getSessionURLPrefix() { return getInvocationDecoder().getSessionURLPrefix(); } /** * Sets the alternate session url prefix. */ public void setAlternateSessionURLPrefix(String urlPrefix) throws ConfigException { getInvocationDecoder().setAlternateSessionURLPrefix(urlPrefix); } /** * Gets the alternate session url prefix. */ public String getAlternateSessionURLPrefix() { return getInvocationDecoder().getAlternateSessionURLPrefix(); } /** * Sets URL encoding. */ public void setURLCharacterEncoding(String encoding) throws ConfigException { getInvocationDecoder().setEncoding(encoding); } public String getURLCharacterEncoding() { return getInvocationDecoder().getEncoding(); } public InvocationDecoder getInvocationDecoder() { return getInvocationServer().getInvocationDecoder(); } public InvocationServer getInvocationServer() { return _invocationServer; } /** * Adds an error page */ public void addErrorPage(ErrorPage errorPage) { WebApp webApp = getErrorWebApp(); if (webApp != null) webApp.addErrorPage(errorPage); } public void setPersistentStore(PersistentStoreConfig config) { _persistentStoreConfig = config; } public PersistentStoreConfig getPersistentStore() { return _persistentStoreConfig; } // // cluster server information // public int getServerIndex() { return _selfServer.getIndex(); } // // statistics // /** * Returns the time the server started in ms. */ public long getStartTime() { return _startTime; } /** * Returns the lifecycle state */ public String getState() { return _lifecycle.getStateName(); } public double getCpuLoad() { return 0; } // // runtime operations // /** * Sets the invocation */ @Override public Invocation buildInvocation(Invocation invocation) throws ConfigException { if (_configException != null) { invocation.setFilterChain(new ExceptionFilterChain(_configException)); invocation.setWebApp(getErrorWebApp()); invocation.setDependency(AlwaysModified.create()); return invocation; } else if (_lifecycle.waitForActive(_waitForActiveTime)) { return _hostContainer.buildInvocation(invocation); } else { int code = HttpServletResponse.SC_SERVICE_UNAVAILABLE; invocation.setFilterChain(new ErrorFilterChain(code)); invocation.setWebApp(getErrorWebApp()); invocation.setDependency(AlwaysModified.create()); return invocation; } } /** * Returns the admin. */ public ServerMXBean getAdmin() { return _admin; } /** * Returns the admin for the current environment. */ public EnvironmentMXBean getEnvironmentAdmin() { return getClassLoader().getAdmin(); } /** * Returns the default web-app or error web-app for top-level errors */ public WebApp getDefaultWebApp() { WebApp webApp = getWebApp("", 80, ""); if (webApp != null) return webApp; else return getErrorWebApp(); } /** * Returns the matching web-app for a URL. */ public WebApp getWebApp(String hostName, int port, String url) { try { HostContainer hostContainer = _hostContainer; if (hostContainer == null) return null; Host host = hostContainer.getHost(hostName, port); if (host == null) return null; return host.getWebAppContainer().findWebAppByURI(url); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); return null; } } /** * Returns the error webApp during startup. */ public WebApp getErrorWebApp() { if (isActive()) return _hostContainer.getErrorWebApp(); else return null; } public ErrorPageManager getErrorPageManager() { WebApp errorWebApp = getErrorWebApp(); if (errorWebApp != null) return errorWebApp.getErrorPageManager(); else return _errorPageManager; } /** * Returns the host controllers. */ public HostController []getHostControllers() { HostContainer hostContainer = _hostContainer; if (hostContainer == null) return new HostController[0]; return hostContainer.getHostList(); } /** * Returns the matching servlet pattern for a URL. */ public Host getHost(String hostName, int port) { try { return _hostContainer.getHost(hostName, port); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); return null; } } /** * Returns the matching servlet pattern for a URL. */ public HostController getHostController(String hostName, int port) { try { return _hostContainer.getHostController(hostName, port); } catch (Exception e) { log.log(Level.WARNING, e.toString(), e); return null; } } /** * Returns the reliable system store */ public ClusterCache getSystemStore() { synchronized (this) { if (_systemStore == null) { _systemStore = new ClusterCache(); _systemStore.setName("resin:system"); _systemStore.setManagerName("resin"); _systemStore.setModifiedExpireTimeoutMillis(CacheConfig.TIME_INFINITY); _systemStore.setAccessedExpireTimeoutMillis(CacheConfig.TIME_INFINITY); // XXX: need to set reliability values } } _systemStore.init(); return _systemStore; } public HttpBufferStore allocateHttpBuffer() { HttpBufferStore buffer = _httpBufferFreeList.allocate(); if (buffer == null) buffer = new HttpBufferStore(getUrlLengthMax()); return buffer; } public void freeHttpBuffer(HttpBufferStore buffer) { _httpBufferFreeList.free(buffer); } /** * Returns the reliable system store */ /* public GlobalCache getGlobalStore() { synchronized (this) { if (_globalStore == null) { _globalStore = new GlobalCache(); _globalStore.setName("resin:global"); _globalStore.setGuid("resin:global"); _globalStore.setLocalReadTimeoutMillis(60000); // XXX: need to set reliability values } } _globalStore.init(); return _globalStore; } */ /** * Handles the case where a class loader is activated. */ public void classLoaderInit(DynamicClassLoader loader) { try { //Jmx.register(_controller.getThreadPool(), "resin:type=ThreadPool"); } catch (Exception e) { log.log(Level.WARNING, e.toString(), e); } } /** * Handles the case where a class loader is dropped. */ public void classLoaderDestroy(DynamicClassLoader loader) { /* try { Jmx.unregister("resin:name=default,type=Server"); Jmx.unregister("resin:type=ThreadPool"); } catch (Throwable e) { log.log(Level.FINEST, e.toString(), e); } */ } /** * Initialization. */ @PostConstruct public void init() { if (! _lifecycle.toInit()) return; // _classLoader.init(); _invocationServer.init(); _admin = createAdmin(); /* if (_resin != null) { createManagement().setCluster(getCluster()); createManagement().setServer(this); createManagement().init(); } */ if (_selfServer.getStage() != null) setStage(_selfServer.getStage()); } protected ServerAdmin createAdmin() { return new ServerAdmin(this); } /** * Start the server. */ public void start() { Thread thread = Thread.currentThread(); ClassLoader oldLoader = thread.getContextClassLoader(); try { thread.setContextClassLoader(getClassLoader()); if (! _lifecycle.toStarting()) return; _startTime = Alarm.getCurrentTime(); if (! Alarm.isTest()) { /* log.info(""); log.info(System.getProperty("os.name") + " " + System.getProperty("os.version") + " " + System.getProperty("os.arch")); log.info(System.getProperty("java.runtime.name") + " " + System.getProperty("java.runtime.version") + ", " + System.getProperty("file.encoding") + ", " + System.getProperty("user.language")); log.info(System.getProperty("java.vm.name") + " " + System.getProperty("java.vm.version") + ", " + System.getProperty("sun.arch.data.model") + ", " + System.getProperty("java.vm.info") + ", " + System.getProperty("java.vm.vendor")); */ log.info(""); Resin resin = Resin.getCurrent(); if (resin != null) { log.info("resin.home = " + resin.getResinHome().getNativePath()); log.info("resin.root = " + resin.getRootDirectory().getNativePath()); if (resin.getResinConf() != null) log.info("resin.conf = " + resin.getResinConf().getNativePath()); log.info(""); String serverType; if (resin.isWatchdog()) serverType = "watchdog"; else serverType = "server"; log.info(serverType + " = " + _selfServer.getAddress() + ":" + _selfServer.getPort() + " (" + getCluster().getId() + ":" + getServerId() + ")"); } else { log.info("resin.home = " + System.getProperty("resin.home")); } // log.info("user.name = " + System.getProperty("user.name")); log.info("stage = " + _stage); } _lifecycle.toStarting(); // initialize the system distributed store if (isResinServer()) getSystemStore(); _hostContainer.start(); // getCluster().startRemote(); _alarm.queue(ALARM_INTERVAL); _lifecycle.toActive(); logModules(); AdminAuthenticator adminAuth = getAdminAuthenticator(); if (adminAuth != null) adminAuth.initStore(); } catch (RuntimeException e) { log.log(Level.WARNING, e.toString(), e); _lifecycle.toError(); throw e; } catch (Exception e) { log.log(Level.WARNING, e.toString(), e); _lifecycle.toError(); // if the server can't start, it needs to completely fail, especially // for the watchdog throw new RuntimeException(e); // log.log(Level.WARNING, e.toString(), e); // _configException = e; } finally { thread.setContextClassLoader(oldLoader); } } protected void startImpl() { } /** * Display activated modules */ protected void logModules() { } /** * Handles the alarm. */ @Override public void handleAlarm(Alarm alarm) { if (! _lifecycle.isActive()) return; try { if (isModified()) { // XXX: message slightly wrong String msg = L.l("Resin restarting due to configuration change"); ShutdownSystem.getCurrent().shutdown(ExitCode.MODIFIED, msg); return; } } finally { if (_lifecycle.isActive()) { alarm.queue(ALARM_INTERVAL); } } } /** * Returns true if the server has been modified and needs restarting. */ @Override public boolean isModified() { DynamicClassLoader classLoader = getClassLoader(); if (classLoader != null) return classLoader.isModified(); else return true; } @Override public boolean logModified(Logger log) { DynamicClassLoader classLoader = getClassLoader(); if (classLoader != null) return classLoader.logModified(log); else { log.info(this + " is closed"); return true; } } /** * Returns true if the server has been modified and needs restarting. */ public boolean isModifiedNow() { DynamicClassLoader classLoader = getClassLoader(); if (classLoader != null) return classLoader.isModifiedNow(); else return true; } /** * Returns true if the server is starting or active */ public boolean isAfterStarting() { return _lifecycle.getState().isAfterStarting(); } /** * Returns true if the server is stopped. */ public boolean isStopping() { return _lifecycle.isStopping(); } /** * Returns true if the server is stopped. */ public boolean isStopped() { return _lifecycle.isStopped(); } /** * Returns true if the server is closed. */ public boolean isDestroyed() { return _lifecycle.isDestroyed(); } /** * Returns true if the server is closed. */ public boolean isDestroying() { return _lifecycle.isDestroying(); } /** * Returns true if the server is currently active and accepting requests */ public boolean isActive() { return _lifecycle.isActive(); } /** * Clears the catch by matching the invocation. */ public void clearCacheByPattern(String hostPattern, String uriPattern) { final Matcher hostMatcher; if (hostPattern != null) hostMatcher = Pattern.compile(hostPattern).matcher(""); else hostMatcher = null; final Matcher uriMatcher; if (uriPattern != null) uriMatcher = Pattern.compile(uriPattern).matcher(""); else uriMatcher = null; InvocationMatcher matcher = new InvocationMatcher() { public boolean isMatch(Invocation invocation) { if (hostMatcher != null) { hostMatcher.reset(invocation.getHost()); if (! hostMatcher.find()) { return false; } } if (uriMatcher != null) { uriMatcher.reset(invocation.getURI()); if (! uriMatcher.find()) { return false; } } return true; } }; getInvocationServer().invalidateMatchingInvocations(matcher); } /** * Clears the proxy cache. */ public void clearCache() { // skip the clear on restart if (isStopping()) return; if (log.isLoggable(Level.FINER)) log.finest("ServletServer clearCache"); // the invocation cache must be cleared first because the old // filter chain entries must not point to the cache's // soon-to-be-invalid entries getInvocationServer().clearCache(); if (_proxyCache != null) _proxyCache.clear(); } /** * Returns the proxy cache hit count. */ public long getProxyCacheHitCount() { if (_proxyCache != null) return _proxyCache.getHitCount(); else return 0; } /** * Returns the proxy cache miss count. */ public long getProxyCacheMissCount() { if (_proxyCache != null) return _proxyCache.getMissCount(); else return 0; } /** * Returns any HMTP stream */ public MessageStream getHmtpStream() { return null; } public void restart() { String msg = L.l("Server restarting due to configuration change"); ShutdownSystem.shutdownActive(ExitCode.MODIFIED, msg); } /** * Closes the server. */ public void stop() { Thread thread = Thread.currentThread(); ClassLoader oldLoader = thread.getContextClassLoader(); try { thread.setContextClassLoader(getClassLoader()); if (! _lifecycle.toStopping()) return; // getInvocationServer().stop(); // notify other servers that we've stopped notifyStop(); Alarm alarm = _alarm; _alarm = null; if (alarm != null) alarm.dequeue(); try { if (_systemStore != null) _systemStore.close(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } /* try { if (_globalStore != null) _globalStore.close(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } */ /* try { if (_domainManager != null) _domainManager.close(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } */ try { ThreadPool.getThreadPool().interrupt(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } try { Thread.sleep(1); } catch (Throwable e) { } try { if (_hostContainer != null) _hostContainer.stop(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } try { getClassLoader().stop(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } _lifecycle.toStop(); } finally { thread.setContextClassLoader(oldLoader); } } /** * Notifications to cluster servers that we've stopped. */ protected void notifyStop() { } /** * Closes the server. */ public void destroy() { stop(); if (! _lifecycle.toDestroy()) return; Thread thread = Thread.currentThread(); ClassLoader oldLoader = thread.getContextClassLoader(); try { thread.setContextClassLoader(getClassLoader()); try { _hostContainer.destroy(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } log.fine(this + " destroyed"); getInvocationServer().destroy(); // getClassLoader().destroy(); _proxyCache = null; } finally { DynamicClassLoader.setOldLoader(thread, oldLoader); Resin resin = _resin; if (resin != null) resin.destroy(); } } public String toString() { return (getClass().getSimpleName() + "[id=" + getServerId() + ",cluster=" + _selfServer.getCluster().getId() + "]"); } }