Package com.caucho.server.resin

Source Code of com.caucho.server.resin.Resin$Var

/*
* Copyright (c) 1998-2010 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.resin;

import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.BindException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.locks.LockSupport;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.management.ObjectName;

import com.caucho.VersionFactory;
import com.caucho.bam.Broker;
import com.caucho.config.Config;
import com.caucho.config.ConfigException;
import com.caucho.config.Configurable;
import com.caucho.config.SchemaBean;
import com.caucho.config.functions.FmtFunctions;
import com.caucho.config.inject.InjectManager;
import com.caucho.config.inject.WebBeansAddLoaderListener;
import com.caucho.config.lib.ResinConfigLibrary;
import com.caucho.config.program.ConfigProgram;
import com.caucho.config.program.ContainerProgram;
import com.caucho.config.types.Bytes;
import com.caucho.config.types.Period;
import com.caucho.ejb.manager.EjbEnvironmentListener;
import com.caucho.env.jpa.ListenerPersistenceEnvironment;
import com.caucho.hemp.broker.HempBrokerManager;
import com.caucho.jsp.cfg.JspPropertyGroup;
import com.caucho.license.LicenseCheck;
import com.caucho.lifecycle.Lifecycle;
import com.caucho.lifecycle.LifecycleState;
import com.caucho.loader.Environment;
import com.caucho.loader.EnvironmentBean;
import com.caucho.loader.EnvironmentClassLoader;
import com.caucho.loader.EnvironmentLocal;
import com.caucho.loader.EnvironmentProperties;
import com.caucho.log.EnvironmentStream;
import com.caucho.log.RotateStream;
import com.caucho.management.server.ClusterMXBean;
import com.caucho.management.server.ResinMXBean;
import com.caucho.management.server.ThreadPoolMXBean;
import com.caucho.naming.Jndi;
import com.caucho.network.server.NetworkServer;
import com.caucho.repository.ModuleRepository;
import com.caucho.server.admin.Management;
import com.caucho.server.admin.TransactionManager;
import com.caucho.server.cache.TempFileManager;
import com.caucho.server.cluster.Cluster;
import com.caucho.server.cluster.ClusterPod;
import com.caucho.server.cluster.ClusterServer;
import com.caucho.server.cluster.Server;
import com.caucho.server.cluster.SingleCluster;
import com.caucho.server.repository.ModuleRepositoryImpl;
import com.caucho.server.util.JniCauchoSystem;
import com.caucho.server.webbeans.ResinWebBeansProducer;
import com.caucho.util.Alarm;
import com.caucho.util.CompileException;
import com.caucho.util.L10N;
import com.caucho.util.QDate;
import com.caucho.util.Shutdown;
import com.caucho.util.ThreadPool;
import com.caucho.vfs.MemoryPath;
import com.caucho.vfs.Path;
import com.caucho.vfs.QJniServerSocket;
import com.caucho.vfs.QServerSocket;
import com.caucho.vfs.ReadStream;
import com.caucho.vfs.Vfs;
import com.caucho.vfs.WriteStream;

/**
* The Resin class represents the top-level container for Resin.
* It exactly matches the <resin> tag in the resin.xml
*/
public class Resin extends Shutdown implements EnvironmentBean, SchemaBean
{
  private static Logger _log;
  private static L10N _L;

  public static final int EXIT_OK = 0;
  public static final int EXIT_HALT = 3;

  private static final EnvironmentLocal<Resin> _resinLocal
    = new EnvironmentLocal<Resin>();

  private final EnvironmentLocal<String> _serverIdLocal
    = new EnvironmentLocal<String>("caucho.server-id");

  private EnvironmentClassLoader _classLoader;
  private boolean _isGlobal;

  private String _serverId = "";
  private final boolean _isWatchdog;
  private DynamicServer _dynamicServer;

  private ClusterPod _dynPod;
  private String _dynCluster;
  private String _dynAddress;
  private int _dynPort;

  private Path _resinHome;
  private Path _rootDirectory;

  private Path _resinDataDirectory;
 
  private NetworkServer _networkServer;

  private long _minFreeMemory = 2 * 1024L * 1024L;
  private long _shutdownWaitMax = 60000L;

  private SecurityManager _securityManager;

  private ArrayList<ConfigProgram> _clusterDefaults
    = new ArrayList<ConfigProgram>();

  private ArrayList<Cluster> _clusters
    = new ArrayList<Cluster>();

  private Lifecycle _lifecycle;

  private Server _server;

  private long _initialStartTime;
  private long _startTime;

  private String _licenseErrorMessage;

  private String _configFile;
  private Path _resinConf;

  private ClassLoader _systemClassLoader;

  private Thread _mainThread;
  private FailSafeHaltThread _failSafeHaltThread;
  private ShutdownThread _shutdownThread;

  private ArrayList<BoundPort> _boundPortList
    = new ArrayList<BoundPort>();

  protected Management _management;

  private ModuleRepositoryImpl _repository = new ModuleRepositoryImpl();
  private TempFileManager _tempFileManager;

  private ThreadPoolAdmin _threadPoolAdmin;
  private ObjectName _objectName;
  private ResinAdmin _resinAdmin;
  private ResinActor _resinActor;

  private InputStream _waitIn;

  private Socket _pingSocket;

  private String _stage = null;
  private boolean _isDumpHeapOnExit;

  /**
   * Creates a new resin server.
   */
  protected Resin(ClassLoader loader, boolean isWatchdog)
  {
    this(loader, isWatchdog, null);
  }

  /**
   * Creates a new resin server.
   */
  protected Resin(ClassLoader loader,
                  boolean isWatchdog,
                  String licenseErrorMessage)
  {
    _startTime = Alarm.getCurrentTime();

    _isWatchdog = isWatchdog;
    _licenseErrorMessage = licenseErrorMessage;

    // DynamicClassLoader.setJarCacheEnabled(true);
    Environment.init();

    if (loader == null)
      loader = ClassLoader.getSystemClassLoader();

    _isGlobal = (loader == ClassLoader.getSystemClassLoader());

    if (loader instanceof EnvironmentClassLoader)
      _classLoader = (EnvironmentClassLoader) loader;
    else
      _classLoader = EnvironmentClassLoader.create();
  }

  /**
   * Creates a new Resin instance
   */
  public static Resin create()
  {
    return create(Thread.currentThread().getContextClassLoader(), false);
  }

  /**
   * Creates a new Resin instance
   */
  public static Resin createWatchdog()
  {
    ClassLoader loader = Thread.currentThread().getContextClassLoader();

    Resin resin = create(loader, true);

    return resin;
  }

  /**
   * Creates a new Resin instance
   */
  public static Resin create(ClassLoader loader, boolean isWatchdog)
  {
    String licenseErrorMessage = null;

    Resin resin = null;

    try {
      Class<?> cl = Class.forName("com.caucho.server.resin.ProResin");
      Constructor<?> ctor = cl.getConstructor(new Class[] { ClassLoader.class, boolean.class });

      resin = (Resin) ctor.newInstance(loader, isWatchdog);
    } catch (ConfigException e) {
      log().log(Level.FINER, e.toString(), e);

      licenseErrorMessage = e.getMessage();
    } catch (InvocationTargetException e) {
      Throwable cause = e.getCause();

      log().log(Level.FINER, cause.toString(), cause);

      if (cause instanceof ConfigException) {
        licenseErrorMessage = cause.getMessage();
      }
      else {
        String msg = L().l("  Using Resin(R) Open Source under the GNU Public License (GPL).\n"
                           + "\n"
                           + "  See http://www.caucho.com for information on Resin Professional,\n"
                           + "  including caching, clustering, JNI acceleration, and OpenSSL integration.\n"
                           + "\n  Exception=" + cause + "\n");
      }
    } catch (Throwable e) {
      log().log(Level.FINER, e.toString(), e);

      String causeMsg = "";
      if (! (e instanceof ClassNotFoundException)) {
        causeMsg = "\n  Exception=" + e + "\n";
      }


      String msg = L().l("  Using Resin(R) Open Source under the GNU Public License (GPL).\n"
                         + "\n"
                         + "  See http://www.caucho.com for information on Resin Professional,\n"
                         + "  including caching, clustering, JNI acceleration, and OpenSSL integration.\n"
                         + causeMsg);

      licenseErrorMessage = msg;
    }

    if (resin == null) {
      try {
        Class<?> cl = Class.forName("com.caucho.license.LicenseCheckImpl");
        LicenseCheck license = (LicenseCheck) cl.newInstance();

        license.requirePersonal(1);

        licenseErrorMessage = license.doLogging();
      } catch (ConfigException e) {
        licenseErrorMessage = e.getMessage();
      } catch (Throwable e) {
        // message should already be set above
      }

      resin = new Resin(loader, isWatchdog, licenseErrorMessage);
    }

    _resinLocal.set(resin, loader);

    // resin.initEnvironment();

    return resin;
  }

  /**
   * Creates a new Resin instance
   */
  public static Resin createOpenSource()
  {
    return createOpenSource(Thread.currentThread().getContextClassLoader());
  }

  /**
   * Creates a new Resin instance
   */
  public static Resin createOpenSource(ClassLoader loader)
  {
    return new Resin(loader, false, null);
  }

  /**
   * Returns the resin server.
   */
  public static Resin getLocal()
  {
    return _resinLocal.get();
  }

  /**
   * Returns the resin server.
   */
  public static Resin getCurrent()
  {
    return getLocal();
  }

  /**
   * Must be called after the Resin.create()
   */
  public void preConfigureInit()
  {
    if (_lifecycle != null)
      return;

    Thread thread = Thread.currentThread();
    ClassLoader oldLoader = thread.getContextClassLoader();

    try {
      thread.setContextClassLoader(_classLoader);

      _resinLocal.set(this, _classLoader);

      _lifecycle = new Lifecycle(log(), "Resin[]");

      String resinHome = System.getProperty("resin.home");

      if (resinHome != null)
        setResinHome(Vfs.lookup(resinHome));
      else
        setResinHome(Vfs.getPwd());

      if (getRootDirectory() == null) {
        setRootDirectory(getResinHome());

        // server.root backwards compat
        String serverRoot = System.getProperty("server.root");

        if (serverRoot != null)
          setRootDirectory(Vfs.lookup(serverRoot));

        // resin.root backwards compat
        serverRoot = System.getProperty("resin.root");

        if (serverRoot != null)
          setRootDirectory(Vfs.lookup(serverRoot));
      }

      if (getRootDirectory() == null)
        throw new NullPointerException();

      // default server id
      if (getServerId() == null)
        setServerId("");
     
      String serverName = getServerId();
      if (serverName == null || "".equals(serverName))
        serverName = "default";
     
      Path resinData = getRootDirectory().lookup("resin-data");
      _networkServer = new NetworkServer(serverName,
                                         getRootDirectory(),
                                         resinData.lookup(serverName));

      // watchdog/0212
      // else
      //  setRootDirectory(Vfs.getPwd());

      Environment.addChildLoaderListener(new ListenerPersistenceEnvironment());
      Environment.addChildLoaderListener(new WebBeansAddLoaderListener());
      Environment.addChildLoaderListener(new EjbEnvironmentListener());
      InjectManager webBeans = InjectManager.create();

      Config.setProperty("resinHome", getResinHome());
      Config.setProperty("resin", new Var());
      Config.setProperty("server", new Var());
      Config.setProperty("java", new JavaVar());
      Config.setProperty("system", System.getProperties());
      Config.setProperty("getenv", System.getenv());

      new HempBrokerManager();

      _management = createResinManagement();

      if (webBeans.getBeans(ResinWebBeansProducer.class).size() == 0) {
        Config.setProperty("fmt", new FmtFunctions());

        ResinConfigLibrary.configure(webBeans);

        try {
          Method method = Jndi.class.getMethod("lookup", new Class[] { String.class });
          Config.setProperty("jndi", method);
          Config.setProperty("jndi:lookup", method);
        } catch (Exception e) {
          throw ConfigException.create(e);
        }

        webBeans.addManagedBean(webBeans.createManagedBean(ResinWebBeansProducer.class));
        webBeans.update();
      }

      _threadPoolAdmin = ThreadPoolAdmin.create();
      _resinAdmin = new ResinAdmin(this);

      _threadPoolAdmin.register();

      MemoryAdmin.create();
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw ConfigException.create(e);
    } finally {
      thread.setContextClassLoader(oldLoader);
    }
  }

  /**
   * Returns the classLoader
   */
  public ClassLoader getClassLoader()
  {
    return _classLoader;
  }

  public ObjectName getObjectName()
  {
    return _objectName;
  }

  public ResinMXBean getAdmin()
  {
    return _resinAdmin;
  }

  /**
   * Returns the admin broker
   */
  public Broker getAdminBroker()
  {
    return _management.getAdminBroker();
  }

  public ThreadPoolMXBean getThreadPoolAdmin()
  {
    return _threadPoolAdmin;
  }

  protected String getLicenseMessage()
  {
    return null;
  }

  protected String getLicenseErrorMessage()
  {
    return _licenseErrorMessage;
  }

  /**
   * Sets the classLoader
   */
  public void setEnvironmentClassLoader(EnvironmentClassLoader loader)
  {
    _classLoader = loader;
  }

  /**
   * Returns the relax schema.
   */
  public String getSchema()
  {
    return "com/caucho/server/resin/resin.rnc";
  }

  /**
   * Sets the server id.
   */
  public void setServerId(String serverId)
  {
    Config.setProperty("serverId", serverId);

    _serverId = serverId;
    _serverIdLocal.set(serverId);
  }

  /**
   * Returns the server id.
   */
  public String getServerId()
  {
    return _serverId;
  }

  /**
   * Returns true for a Resin server, false for a watchdog.
   */
  public boolean isResinServer()
  {
    return ! _isWatchdog;
  }

  public boolean isWatchdog()
  {
    return _isWatchdog;
  }

  public String getUniqueServerName()
  {
    String name;

    if (_isWatchdog)
      name = _serverId + "_watchdog";
    else
      name = _serverId;

    name = name.replace('-', '_');

    return name;
  }

  public static String getCurrentServerId()
  {
    Resin resin = getCurrent();

    if (resin != null)
      return resin.getServerId();
    else
      return "";
  }

  /**
   * Sets the server id.
   */
  public void setDynamicServer(String clusterId, String address, int port)
  {
    String id = address + ":" + port;

    _dynCluster = clusterId;
    _dynAddress = address;
    _dynPort = port;

    if (_serverId == null)
      setServerId(id);
  }

  /**
   * Returns the server id.
   */
  public String getDisplayServerId()
  {
    if ("".equals(_serverId))
      return "default";
    else
      return _serverId;
  }

  /**
   * Sets the config file.
   */
  public void setConfigFile(String configFile)
  {
    _configFile = configFile;
  }

  /**
   * Sets resin.home
   */
  public void setResinHome(Path home)
  {
    _resinHome = home;
  }

  /**
   * Returns resin.home.
   */
  public Path getResinHome()
  {
    return _resinHome;
  }

  /**
   * Sets the root directory.
   */
  public void setRootDirectory(Path root)
  {
    _rootDirectory = root;

    if (root == null)
      throw new NullPointerException();
  }

  /**
   * Gets the root directory.
   */
  public Path getRootDirectory()
  {
    return _rootDirectory;
  }

  /**
   * Returns the resin-data directory
   */
  public Path getResinDataDirectory()
  {
    Path path;

    if (_resinDataDirectory != null)
      path = _resinDataDirectory;
    else if (_isWatchdog)
      path = getRootDirectory().lookup("watchdog-data");
    else
      path = getRootDirectory().lookup("resin-data");

    if (path instanceof MemoryPath) { // QA
      path = Vfs.lookup("file:/tmp/caucho/qa/resin-data");
    }

    return path;
  }

  /**
   * Sets the resin-data directory
   */
  public void setResinDataDirectory(Path path)
  {
    if (path.isFile()) {
      throw new ConfigException(L().l("resin-data-directory '{0}' must not be a file",
                                    path));
    }

    _resinDataDirectory = path;
  }

  /**
   * Sets the admin directory
   */
  public void setAdminPath(Path path)
  {
    // setResinDataDirectory(path);
  }

  /**
   * The configuration file used to start the server.
   */
  public Path getResinConf()
  {
    return _resinConf;
  }

  protected String getResinName()
  {
    return "Resin";
  }

  /**
   * Set true for Resin pro.
   */
  public boolean isProfessional()
  {
    return false;
  }

  /**
   * Returns the cluster names.
   */
  public ClusterMXBean []getClusters()
  {
    ClusterMXBean []clusters = new ClusterMXBean[_clusters.size()];

    for (int i = 0; i < _clusters.size(); i++)
      clusters[i] = _clusters.get(i).getAdmin();

    return clusters;
  }

  public void addClusterDefault(ContainerProgram program)
  {
    _clusterDefaults.add(program);
  }

  @Configurable
  public Cluster createCluster()
    throws ConfigException
  {
    Cluster cluster = instantiateCluster();

    for (int i = 0; i < _clusterDefaults.size(); i++)
      _clusterDefaults.get(i).configure(cluster);

    return cluster;
  }

  protected Cluster instantiateCluster()
  {
    return new SingleCluster(this);
  }

  @Configurable
  public void addCluster(Cluster cluster)
  {
    _clusters.add(cluster);
  }

  public ArrayList<Cluster> getClusterList()
  {
    return _clusters;
  }

  /**
   * Set true if the server should enable environment-based
   * system properties.
   */
  public void setEnvironmentSystemProperties(boolean isEnable)
  {
    EnvironmentProperties.enableEnvironmentSystemProperties(isEnable);
  }

  /**
   * Configures the thread pool
   */
  public ThreadPoolConfig createThreadPool()
    throws Exception
  {
    return new ThreadPoolConfig();
  }

  /**
   * Sets the user name for setuid.
   */
  public void setUserName(String userName)
  {
  }

  /**
   * Sets the group name for setuid.
   */
  public void setGroupName(String groupName)
  {
  }

  /**
   * Sets the minimum free memory allowed.
   */
  public void setMinFreeMemory(Bytes minFreeMemory)
  {
    _minFreeMemory = minFreeMemory.getBytes();
  }

  /**
   * Gets the minimum free memory allowed.
   */
  public long getMinFreeMemory()
  {
    return _minFreeMemory;
  }

  /**
   * Sets the shutdown time
   */
  public void setShutdownWaitMax(Period shutdownWaitMax)
  {
    _shutdownWaitMax = shutdownWaitMax.getPeriod();
  }

  /**
   * Gets the minimum free memory allowed.
   */
  public long getShutdownWaitMax()
  {
    return _shutdownWaitMax;
  }

  /**
   * Set true if system properties are global.
   */
  public void setGlobalSystemProperties(boolean isGlobal)
  {
  }

  public SecurityManagerConfig createSecurityManager()
  {
    return new SecurityManagerConfig();
  }

  public void setWatchdogManager(ConfigProgram program)
  {
  }

  /**
   * Configures the TM.
   */
  @Deprecated
  public TransactionManager createTransactionManager()
    throws ConfigException
  {
    log().warning(L().l("<transaction-manager> tag belongs in <management>"));

    return new TransactionManager(this);
  }

  @Deprecated
  public void addManagement(ConfigProgram program)
  {
    _clusterDefaults.add(program);
  }

  @Deprecated
  public Management createResinManagement()
  {
    if (_management == null) {
      _management = new Management();

      _management.setResin(this);
    }

    return _management;
  }

  public ModuleRepository createModuleRepository()
  {
    return _repository;
  }

  public TempFileManager getTempFileManager()
  {
    if (_tempFileManager == null) {
      Path path = getResinDataDirectory();

      _tempFileManager = new TempFileManager(path);
    }

    return _tempFileManager;
  }

  /**
   * Adds a new security provider
   */
  public void addSecurityProvider(Class<?> providerClass)
    throws Exception
  {
    if (! Provider.class.isAssignableFrom(providerClass))
      throw new ConfigException(L().l("security-provider {0} must implement java.security.Provider",
                                    providerClass.getName()));

    Security.addProvider((Provider) providerClass.newInstance());
  }

  /**
   * Configures JSP (backwards compatibility).
   */
  public JspPropertyGroup createJsp()
  {
    return new JspPropertyGroup();
  }

  /**
   * Ignore the boot configuration
   */
  public void addBoot(ContainerProgram program)
    throws Exception
  {
  }

  /**
   * Sets the initial start time.
   */
  void setInitialStartTime(long now)
  {
    _initialStartTime = now;
  }

  /**
   * Returns the initial start time.
   */
  public Date getInitialStartTime()
  {
    return new Date(_initialStartTime);
  }

  /**
   * Returns the start time.
   */
  public Date getStartTime()
  {
    return new Date(_startTime);
  }

  /**
   * Returns the current lifecycle state.
   */
  public LifecycleState getLifecycleState()
  {
    return _lifecycle;
  }

  /**
   * Initialize the server.
   */
  @PostConstruct
  public void init()
  {
    preConfigureInit();

    _lifecycle.toInit();
  }

  /**
   * Returns the active server.
   */
  public Server getServer()
  {
    return _server;
  }

  public void setServer(Server server)
  {
    assert(_server == null);

    _server = server;
  }

  /**
   * Returns the management api.
   */
  public Management getManagement()
  {
    return _management;
  }

  public Server createServer()
  {
    if (_server == null) {
      ClusterServer clusterServer = null;

      if (_dynCluster != null) {
        clusterServer
          = loadDynamicServer(_dynPod, _serverId, _dynAddress, _dynPort);
      }

      if (clusterServer == null)
        clusterServer = findClusterServer(_serverId);

      if (clusterServer == null)
        throw new ConfigException(L().l("server-id '{0}' has no matching <server> definition.",
                                        _serverId));


      Server server = clusterServer.startServer(_networkServer);

      assert(server == _server);

      if (_stage != null)
        _server.setStage(_stage);

      // _server.start();
    }

    return _server;
  }

  protected ClusterServer loadDynamicServer(ClusterPod pod,
                                            String dynId,
                                            String dynAddress,
                                            int dynPort)
  {
    throw new ConfigException(L().l("dynamic-server requires Resin Professional"));
  }

  /**
   * Starts the server.
   */
  public void start()
    throws Exception
  {
    preConfigureInit();

    if (! _lifecycle.toActive())
      return;

    Thread thread = Thread.currentThread();
    ClassLoader oldLoader = thread.getContextClassLoader();

    try {
      thread.setContextClassLoader(getClassLoader());

      // force a GC on start
      System.gc();

      ClusterServer clusterServer = null;

      if (_dynCluster != null) {
        clusterServer = findClusterServer(_serverId);

        if (clusterServer != null)
          throw new ConfigException(L().l("dynamic-server '{0}' must not have a static configuration configured in the resin.xml.",
                                          _serverId));

        Cluster cluster = findCluster(_dynCluster);

        if (cluster == null) {
          throw new ConfigException(L().l("dynamic-server cluster '{0}' does not exist.  Dynamic servers must be added to an existing cluster.",
                                          _dynamicServer.getCluster()));
        }

        if (! cluster.isDynamicServerEnable()) {
          throw new ConfigException(L().l("cluster '{0}' does not allow dynamic servers.  Add a <dynamic-server-enable/> tag to the <cluster> to enable it.",
                                          cluster.getId()));
        }

        _dynPod = cluster.getPodList()[0];

        if (_dynPod == null)
          throw new NullPointerException();
      }

      /*
      // XXX: get the server
      for (Cluster cluster : _clusters) {
        cluster.start();
      }
      */

      _server = createServer();

      for (int i = 0; i < _boundPortList.size(); i++) {
        BoundPort port = _boundPortList.get(i);

        _server.bind(port.getAddress(),
                     port.getPort(),
                     port.getServerSocket());
      }

      _server.start();

      Environment.start(getClassLoader());

      /*
        if (! hasListeningPort()) {
        log().warning(L().l("-server \"{0}\" has no matching http or srun ports.  Check the resin.xml and -server values.",
        _serverId));
        }
      */

      log().severe(this + " started in " + (Alarm.getExactTime() - _startTime) + "ms");
    } finally {
      thread.setContextClassLoader(oldLoader);
    }
  }

  /**
   * Starts the server.
   */
  public void stop()
  {
    if (! _lifecycle.toStop())
      return;
  }

  public boolean isDynamicServer()
  {
    for (int i = 0; i < _clusters.size(); i++) {
      Cluster cluster = _clusters.get(i);

      if (cluster.isDynamicServerEnable())
        return true;
    }

    return false;
  }

  public Cluster findCluster(String id)
  {
    for (int i = 0; i < _clusters.size(); i++) {
      Cluster cluster = _clusters.get(i);

      if (cluster.getId().equals(id))
        return cluster;
    }

    return null;
  }

  public ClusterServer findClusterServer(String id)
  {
    for (int i = 0; i < _clusters.size(); i++) {
      Cluster cluster = _clusters.get(i);

      ClusterServer server = cluster.findServer(id);

      if (server != null)
        return server;
    }

    return null;
  }

  /**
   * Dump threads for debugging
   */
  public void dumpThreads()
  {
  }

  /**
   * Returns true if active.
   */
  public boolean isActive()
  {
    return _lifecycle.isActive();
  }

  /**
   * Returns true if the server is closing.
   */
  public boolean isClosing()
  {
    return _lifecycle.isDestroying();
  }

  /**
   * Returns true if the server is closed.
   */
  public boolean isClosed()
  {
    return _lifecycle.isDestroyed();
  }

  public void startFailSafeShutdown(String msg)
  {
    // start the fail-safe thread in case the shutdown fails
    FailSafeHaltThread haltThread = _failSafeHaltThread;
    if (haltThread != null)
      haltThread.startShutdown();

    log().severe(msg);
  }
  /**
   * Start the server shutdown
   */
  public void startShutdown(String msg)
  {
    startFailSafeShutdown(msg);

    if (_lifecycle.isDestroying())
      return;

    ShutdownThread shutdownThread = _shutdownThread;
    if (shutdownThread != null)
      shutdownThread.startShutdown();
    else
      shutdownImpl();
  }

  public void destroy()
  {
    startFailSafeShutdown("Resin shutdown from destroy() call");

    if (_lifecycle.isDestroying())
      return;

    shutdownImpl();
  }

  /**
   * Closes the server.
   */
  private void shutdownImpl()
  {
    // start the fail-safe thread in case the shutdown fails
    FailSafeHaltThread haltThread = _failSafeHaltThread;
    if (haltThread != null)
      haltThread.startShutdown();

    try {
      if (_isDumpHeapOnExit) {
        dumpHeapOnExit();
      }

      try {
        Socket socket = _pingSocket;

        if (socket != null)
          socket.setSoTimeout(1000);
      } catch (Throwable e) {
        log().log(Level.WARNING, e.toString(), e);
      }

      try {
        Server server = _server;

        if (server != null)
          server.destroy();
      } catch (Throwable e) {
        log().log(Level.WARNING, e.toString(), e);
      } finally {
        _server = null;
      }

      try {
        Management management = _management;
        _management = null;

        if (management != null)
          management.destroy();
      } catch (Throwable e) {
        log().log(Level.WARNING, e.toString(), e);
      }

      _threadPoolAdmin.unregister();

      if (_isGlobal)
        Environment.closeGlobal();
      else
        _classLoader.destroy();
    } finally {
      _lifecycle.toDestroy();

      if (Alarm.isTest()) {
        log().finer("test simulating exit");
      }
      else if (_mainThread != null)
        System.exit(EXIT_OK); // check exit code with config errors
    }
  }

  public void parseCommandLine(String []argv)
    throws Exception
  {
    preConfigureInit();

    int len = argv.length;
    int i = 0;

    while (i < len) {
      // RandomUtil.addRandom(argv[i]);

      if (i + 1 < len
          && (argv[i].equals("-stdout")
              || argv[i].equals("--stdout"))) {
        Path path = Vfs.lookup(argv[i + 1]);

        RotateStream stream = RotateStream.create(path);
        stream.init();
        WriteStream out = stream.getStream();
        out.setDisableClose(true);

        EnvironmentStream.setStdout(out);

        i += 2;
      }
      else if (i + 1 < len
               && (argv[i].equals("-stderr")
                   || argv[i].equals("--stderr"))) {
        Path path = Vfs.lookup(argv[i + 1]);

        RotateStream stream = RotateStream.create(path);
        stream.init();
        WriteStream out = stream.getStream();
        out.setDisableClose(true);

        EnvironmentStream.setStderr(out);

        i += 2;
      }
      else if (i + 1 < len
               && (argv[i].equals("-conf")
                   || argv[i].equals("--conf"))) {
        _configFile = argv[i + 1];
        i += 2;
      }
      else if (argv[i].equals("-log-directory")
               || argv[i].equals("--log-directory")) {
        i += 2;
      }
      else if (argv[i].equals("-config-server")
               || argv[i].equals("--config-server")) {
        i += 2;
      }
      else if (argv[i].equals("--dump-heap-on-exit")) {
        _isDumpHeapOnExit = true;

        i += 1;
      }
      else if (i + 1 < len
               && (argv[i].equals("-dynamic-server")
                   || argv[i].equals("--dynamic-server"))) {
        String []values = argv[i + 1].split(":");

        if (values.length == 3) {
          String clusterId = values[0];
          String address = values[1];
          int port = Integer.parseInt(values[2]);

          setDynamicServer(clusterId, address, port);
        } else {
          System.out.println("-dynamic-server requires 'cluster:address:port' at '" + argv[i + 1] + "'");

          System.exit(66);
        }

        i += 2;
      }
      else if (i + 1 < len
               && (argv[i].equals("-server")
                   || argv[i].equals("--server"))) {
        setServerId(argv[i + 1]);
        i += 2;
      }
      else if (argv[i].equals("-resin-home")
               || argv[i].equals("--resin-home")) {
        _resinHome = Vfs.lookup(argv[i + 1]);

        i += 2;
      }
      else if (argv[i].equals("-root-directory")
               || argv[i].equals("--root-directory")
               || argv[i].equals("-resin-root")
               || argv[i].equals("--resin-root")) {
        _rootDirectory = _resinHome.lookup(argv[i + 1]);

        i += 2;
      }
      else if (argv[i].equals("-server-root") // backwards compat
               || argv[i].equals("--server-root")) {
        _rootDirectory = _resinHome.lookup(argv[i + 1]);

        i += 2;
      }
      else if (argv[i].equals("-service")) {
        JniCauchoSystem.create().initJniBackground();
        // windows service
        i += 1;
      }
      else if (argv[i].equals("-version")
               || argv[i].equals("--version")) {
        System.out.println(VersionFactory.getFullVersion());
        System.exit(66);
      }
      else if (argv[i].equals("-watchdog-port")
               || argv[i].equals("--watchdog-port")) {
        // watchdog
        i += 2;
      }
      else if (argv[i].equals("-socketwait")
               || argv[i].equals("--socketwait")
               || argv[i].equals("-pingwait")
               || argv[i].equals("--pingwait")) {
        int socketport = Integer.parseInt(argv[i + 1]);

        Socket socket = null;
        for (int k = 0; k < 15 && socket == null; k++) {
          try {
            socket = new Socket("127.0.0.1", socketport);
          } catch (Throwable e) {
            System.out.println(new Date());
            e.printStackTrace();
          }

          if (socket == null)
            Thread.sleep(1000);
        }

        if (socket == null) {
          System.err.println("Can't connect to parent process through socket " + socketport);
          System.err.println("Resin needs to connect to its parent.");
          System.exit(0);
        }

        /*
        if (argv[i].equals("-socketwait") || argv[i].equals("--socketwait"))
          _waitIn = socket.getInputStream();
        */

        _pingSocket = socket;

        //socket.setSoTimeout(60000);

        i += 2;
      }
      else if ("-port".equals(argv[i]) || "--port".equals(argv[i])) {
        int fd = Integer.parseInt(argv[i + 1]);
        String addr = argv[i + 2];
        if ("null".equals(addr))
          addr = null;
        int port = Integer.parseInt(argv[i + 3]);

        _boundPortList.add(new BoundPort(QJniServerSocket.openJNI(fd, port),
                                         addr,
                                         port));

        i += 4;
      }
      else if ("start".equals(argv[i])
               || "restart".equals(argv[i])) {
        JniCauchoSystem.create().initJniBackground();
        i++;
      }
      else if (argv[i].equals("-verbose")
               || argv[i].equals("--verbose")) {
        i += 1;
      }
      else if (argv[i].equals("console")) {
        i += 1;
      }
      else if (argv[i].equals("-fine")
               || argv[i].equals("--fine")) {
        i += 1;
      }
      else if (argv[i].equals("-finer")
               || argv[i].equals("--finer")) {
        i += 1;
      }
      else if (argv[i].startsWith("-D")
               || argv[i].startsWith("-J")
               || argv[i].startsWith("-X")) {
        i += 1;
      }
      else if ("-stage".equals(argv[i])
               || "--stage".equals(argv[i])) {
        _stage = argv[i + 1];
        i += 2;
      }
      else if ("-preview".equals(argv[i])
               || "--preview".equals(argv[i])) {
        _stage = "preview";
        i += 1;
      }
      else if ("-debug-port".equals(argv[i])
               || "--debug-port".equals(argv[i])) {
        i += 2;
      }
      else if ("-jmx-port".equals(argv[i])
               || "--jmx-port".equals(argv[i])) {
        i += 2;
      }
      else {
        System.out.println(L().l("unknown argument '{0}'", argv[i]));
        System.out.println();
        usage();
        System.exit(66);
      }
    }
  }

  private static void usage()
  {
    System.err.println(L().l("usage: java -jar resin.jar [-options] [start | stop | restart]"));
    System.err.println(L().l(""));
    System.err.println(L().l("where options include:"));
    System.err.println(L().l("   -conf <file>          : select a configuration file"));
    System.err.println(L().l("   -log-directory <dir>  : select a logging directory"));
    System.err.println(L().l("   -resin-home <dir>     : select a resin home directory"));
    System.err.println(L().l("   -root-directory <dir> : select a root directory"));
    System.err.println(L().l("   -server <id>          : select a <server> to run"));
    System.err.println(L().l("   -watchdog-port <port> : override the watchdog-port"));
    System.err.println(L().l("   -verbose              : print verbose starting information"));
    System.err.println(L().l("   -preview              : run as a preview server"));
  }

  /**
   * Initialize the server, binding to TCP and starting the threads.
   */
  public void initMain()
    throws Throwable
  {
    preConfigureInit();

    _mainThread = Thread.currentThread();
    _mainThread.setContextClassLoader(_systemClassLoader);

    addRandom();

    if (! Alarm.isTest()) {
      _failSafeHaltThread = new FailSafeHaltThread();
      _failSafeHaltThread.start();
    }

    _shutdownThread = new ShutdownThread();
    _shutdownThread.start();

    setShutdown(this);

    System.out.println(VersionFactory.getFullVersion());
    System.out.println(VersionFactory.getCopyright());
    System.out.println();

    String licenseMessage = getLicenseMessage();

    if (licenseMessage != null) {
      log().warning(licenseMessage);
      System.out.println(licenseMessage);
    }

    String licenseErrorMessage = getLicenseErrorMessage();

    if (licenseErrorMessage != null) {
      log().warning(licenseErrorMessage);
      System.err.println(licenseErrorMessage);
    }

    System.out.println("Starting " + getResinName()
                       + " on " + QDate.formatLocal(_startTime));
    System.out.println();

    Environment.init();

    // buildResinClassLoader();

    // validateEnvironment();

    Thread thread = Thread.currentThread();

    thread.setContextClassLoader(_systemClassLoader);

    if (_classLoader != null)
      thread.setContextClassLoader(_classLoader);

    Path pwd = Vfs.getPwd();

    if (_rootDirectory == null)
      _rootDirectory = _resinHome;

    Vfs.setPwd(_rootDirectory);

    Path resinConf = null;

    if (_configFile != null) {
      if (log().isLoggable(Level.FINER))
        log().finer(this + " looking for conf in " +  pwd.lookup(_configFile));

      resinConf = pwd.lookup(_configFile);
    }

    if (_configFile == null) {
      if (pwd.lookup("conf/resin.xml").canRead())
        _configFile = "conf/resin.xml";
      else { // backward compat
        _configFile = "conf/resin.conf";
      }
    }

    if (resinConf == null || ! resinConf.exists()) {
      if (log().isLoggable(Level.FINER))
        log().finer(this + " looking for conf in " +  _rootDirectory.lookup(_configFile));

      resinConf = _rootDirectory.lookup(_configFile);
    }

    if (! resinConf.exists() && ! _resinHome.equals(_rootDirectory)) {
      if (log().isLoggable(Level.FINER))
        log().finer(this + " looking for conf in " +  _resinHome.lookup(_configFile));

      resinConf = _resinHome.lookup(_configFile);
    }

    // for error messages, show path relative to rootDirectory
    if (! resinConf.exists())
      resinConf = _rootDirectory.lookup(_configFile);

    _resinConf = resinConf;

    // server.setServerRoot(_serverRoot);

    Vfs.setPwd(getRootDirectory());

    Config config = new Config();
    // server/10hc
    // config.setResinInclude(true);

    config.configure(this, resinConf, getSchema());

    ClusterServer clusterServer = findClusterServer(_serverId);

    start();
  }

  private void addRandom()
  {
    /*
    RandomUtil.addRandom(System.currentTimeMillis());
    RandomUtil.addRandom(Runtime.getRuntime().freeMemory());

    RandomUtil.addRandom(System.identityHashCode(_mainThread));
    RandomUtil.addRandom(System.identityHashCode(_systemClassLoader));
    RandomUtil.addRandom(VersionFactory.getFullVersion());

    try {
      RandomUtil.addRandom(InetAddress.getLocalHost().toString());
    } catch (Throwable e) {
    }
    */

    /*
    // for systems with /dev/urandom, read more bits from it.
    try {
      InputStream is = new FileInputStream("/dev/urandom");

      for (int i = 0; i < 16; i++)
        RandomUtil.addRandom(is.read());

      is.close();
    } catch (Throwable e) {
    }

    RandomUtil.addRandom(System.currentTimeMillis());
    */
  }

  protected void dumpHeapOnExit()
  {

  }

  public void memoryShutdown(String msg)
  {
    _isDumpHeapOnExit = true;

    startShutdown(msg);

    try {
      Thread.sleep(10 * 60 * 1000L);
    } catch (Exception e) {
      // interrupted exception
    }
  }

  /**
   * Thread to wait until Resin should be stopped.
   */
  public void waitForExit()
  {
    int socketExceptionCount = 0;
    Integer memoryTest;
    Runtime runtime = Runtime.getRuntime();

    /*
     * If the server has a parent process watching over us, close
     * gracefully when the parent dies.
     */
    while (! isClosing()) {
      try {
        Thread.sleep(10);

        if (! checkMemory(runtime)) {
          startFailSafeShutdown("Resin shutdown from out of memory");
          dumpHeapOnExit();
          return;
        }

        if (! checkFileDescriptor()) {
          startFailSafeShutdown("Resin shutdown from out of file descriptors");
          dumpHeapOnExit();
          return;
        }

        if (_waitIn != null) {
          if (_waitIn.read() >= 0) {
            socketExceptionCount = 0;
          }
          else
            log().warning(L().l("Stopping due to watchdog or user."));

          return;
        }
        else {
          synchronized (this) {
            wait(10000);
          }
        }
      } catch (SocketTimeoutException e) {
        socketExceptionCount = 0;
      } catch (InterruptedIOException e) {
        socketExceptionCount = 0;
      } catch (InterruptedException e) {
        socketExceptionCount = 0;
      } catch (SocketException e) {
        // The Solaris JVM will throw SocketException periodically
        // instead of interrupted exception, so those exceptions need to
        // be ignored.

        // However, the Windows JVMs will throw connection reset by peer
        // instead of returning an end of file in the read.  So those
        // need to be trapped to close the socket.
        if (socketExceptionCount++ == 0) {
          log().log(Level.FINE, e.toString(), e);
        }
        else if (socketExceptionCount > 100)
          return;
      } catch (OutOfMemoryError e) {
        startFailSafeShutdown("Resin shutdown from out of memory");
        dumpHeapOnExit();

        try {
          EnvironmentStream.getOriginalSystemErr().println("Resin halting due to out of memory");
        } catch (Exception e1) {
        } finally {
          System.exit(1);
        }
      } catch (Throwable e) {
        log().log(Level.WARNING, e.toString(), e);

        return;
      }
    }
  }

  private boolean checkMemory(Runtime runtime)
    throws InterruptedException
  {
    long minFreeMemory = getMinFreeMemory();

    if (minFreeMemory <= 0) {
      // memory check disabled
      return true;
    }
    else if (2 * minFreeMemory < getFreeMemory(runtime)) {
      // plenty of free memory
      return true;
    }
    else {
      if (log().isLoggable(Level.FINER)) {
        log().finer(L().l("free memory {0} max:{1} total:{2} free:{3}",
                          "" + getFreeMemory(runtime),
                          "" + runtime.maxMemory(),
                          "" + runtime.totalMemory(),
                          "" + runtime.freeMemory()));
      }

      log().info(L().l("Forcing GC due to low memory. {0} free bytes.",
                       getFreeMemory(runtime)));

      runtime.gc();

      Thread.sleep(1000);

      runtime.gc();

      if (getFreeMemory(runtime) < minFreeMemory) {
        log().severe(L().l("Restarting due to low free memory. {0} free bytes",
                           getFreeMemory(runtime)));

        return false;
      }
    }

    // second memory check
    Object memoryTest = new Integer(0);

    return true;
  }

  private boolean checkFileDescriptor()
  {
    try {
      ReadStream is = _resinConf.openRead();
      is.close();

      return true;
    } catch (IOException e) {
      log().severe(L().l("Restarting due to file descriptor failure:\n{0}",
                         e));

      return false;
    }
  }

  public String toString()
  {
    return getClass().getSimpleName() + "[id=" + _serverId + "]";
  }

  private static long getFreeMemory(Runtime runtime)
  {
    long maxMemory = runtime.maxMemory();
    long totalMemory = runtime.totalMemory();
    long freeMemory = runtime.freeMemory();

    // Some JDKs (JRocket) return 0 for the maxMemory
    if (maxMemory < totalMemory)
      return freeMemory;
    else
      return maxMemory - totalMemory + freeMemory;
  }

  /**
   * The main start of the web server.
   *
   * <pre>
   * -conf resin.xml   : alternate configuration file
   * -port port        : set the server's portt
   * <pre>
   */
  public static void main(String []argv)
  {
    try {
      Environment.init();

      validateEnvironment();

      final Resin resin = Resin.create();

      resin.preConfigureInit();

      resin.parseCommandLine(argv);

      resin.initMain();

      Server server = resin.getServer();

      resin.startResinActor();

      resin.waitForExit();

      resin.startShutdown("Resin shutdown from watchdog exit");

      Thread.sleep(resin.getShutdownWaitMax() + 600000);
      System.exit(0);
    } catch (Throwable e) {
      Throwable cause;

      for (cause = e;
           cause != null && cause.getCause() != null;
           cause = cause.getCause()) {
        if (cause instanceof CompileException) {
          break;
        }
      }

      if (cause instanceof BindException) {
        System.err.println(e.getMessage());

        log().severe(e.toString());

        log().log(Level.FINE, e.toString(), e);

        System.exit(67);
      }
      else if (e instanceof CompileException) {
        System.err.println(e.getMessage());

        log().log(Level.CONFIG, e.toString(), e);
      }
      else {
        e.printStackTrace(System.err);
      }
    } finally {
      System.exit(1);
    }
  }

  private void startResinActor()
    throws IOException
  {
    _resinActor = new ResinActor(this);

    if (_pingSocket != null) {
      InputStream is = _pingSocket.getInputStream();
      OutputStream os = _pingSocket.getOutputStream();

      ResinLink link = new ResinLink(_resinActor, is, os);

      ThreadPool.getThreadPool().schedule(link);
    }
  }

  /**
   * Validates the environment.
   */
  private static void validateEnvironment()
    throws ConfigException
  {
    String loggingManager = System.getProperty("java.util.logging.manager");

    if (loggingManager == null
        || ! loggingManager.equals("com.caucho.log.LogManagerImpl")) {
      log().warning(L().l("The following system property must be set:\n  -Djava.util.logging.manager=com.caucho.log.LogManagerImpl\nThe JDK 1.4 Logging manager must be set to Resin's log manager."));
    }

    /*
    validatePackage("javax.servlet.Servlet", new String[] {"2.5", "1.5"});
    validatePackage("javax.servlet.jsp.jstl.core.Config", new String[] {"1.1"});
    validatePackage("javax.management.MBeanServer", new String[] { "1.2", "1.5" });
    validatePackage("javax.resource.spi.ResourceAdapter", new String[] {"1.5", "1.4"});
    */
  }

  private static L10N L()
  {
    if (_L == null)
      _L = new L10N(Resin.class);

    return _L;
  }

  private static Logger log()
  {
    if (_log == null)
      _log = Logger.getLogger(Resin.class.getName());

    return _log;
  }

  static class BoundPort {
    private QServerSocket _ss;
    private String _address;
    private int _port;

    BoundPort(QServerSocket ss, String address, int port)
    {
      if (ss == null)
        throw new NullPointerException();

      _ss = ss;
      _address = address;
      _port = port;
    }

    public QServerSocket getServerSocket()
    {
      return _ss;
    }

    public int getPort()
    {
      return _port;
    }

    public String getAddress()
    {
      return _address;
    }
  }

  /**
   * EL variables
   */
  public class Var {
    /**
     * Returns the resin.id
     */
    public String getId()
    {
      return _serverId;
    }

    /**
     * Returns the local address
     *
     * @return IP address
     */
    public String getAddress()
    {
      try {
        Server server = _server;

        if (server != null) {
          ClusterServer clusterServer = server.getSelfServer();

          return clusterServer.getAddress();
        }
        else
          return InetAddress.getLocalHost().getHostAddress();
      } catch (Exception e) {
        log().log(Level.FINE, e.toString(), e);

        return "localhost";
      }
    }

    /**
     * Returns the port (backward compat)
     */
    public int getPort()
    {
      Server server = _server;

      if (server != null) {
        ClusterServer clusterServer = server.getSelfServer();

        return clusterServer.getPort();
      }
      else
        return 0;
    }

    /**
     * Returns the port (backward compat)
     */
    public String getHttpAddress()
    {
      return getAddress();
    }

    /**
     * Returns the port (backward compat)
     */
    public String getHttpsAddress()
    {
      return getAddress();
    }

    /**
     * Returns the port (backward compat)
     */
    public int getHttpPort()
    {
      return 0;
    }

    /**
     * Returns the port (backward compat)
     */
    public int getHttpsPort()
    {
      return 0;
    }

    /**
     * Returns the resin config.
     */
    public Path getConf()
    {
      if (Alarm.isTest())
        return Vfs.lookup("file:/home/resin/conf/resin.xml");
      else
        return getResinConf();
    }

    /**
     * Returns the resin home.
     */
    public Path getHome()
    {
      if (Alarm.isTest())
        return Vfs.lookup("file:/home/resin");
      else
        return Resin.this.getResinHome();
    }

    /**
     * Returns the root directory.
     *
     * @return the root directory
     */
    public Path getRoot()
    {
      if (Alarm.isTest())
        return Vfs.lookup("file:/var/www");
      else
        return Resin.this.getRootDirectory();
    }

    public String getUserName()
    {
      return System.getProperty("user.name");
    }

    /**
     * Returns the version
     *
     * @return version
     */
    public String getVersion()
    {
      if (Alarm.isTest())
        return "3.1.test";
      else
        return VersionFactory.getVersion();
    }

    /**
     * Returns the version date
     *
     * @return version
     */
    public String getVersionDate()
    {
      if (Alarm.isTest())
        return "19980508T0251";
      else
        return VersionFactory.getVersionDate();
    }

    /**
     * Returns the local hostname
     *
     * @return version
     */
    public String getHostName()
    {
      try {
        if (Alarm.isTest())
          return "localhost";
        else
          return InetAddress.getLocalHost().getHostName();
      } catch (Exception e) {
        log().log(Level.FINE, e.toString(), e);

        return "localhost";
      }
    }

    /**
     * Returns the root directory.
     *
     * @return resin.home
     */
    public Path getRootDir()
    {
      return getRoot();
    }

    /**
     * Returns the root directory.
     *
     * @return resin.home
     */
    public Path getRootDirectory()
    {
      return getRoot();
    }

    /**
     * Returns true for Resin professional.
     */
    public boolean isProfessional()
    {
      return Resin.this.isProfessional();
    }

    /**
     * Returns the -server id
     */
    public String getServerId()
    {
      return _serverId;
    }
  }

  /**
   * Java variables
   */
  public class JavaVar {
    /**
     * Returns true for JDK 5
     */
    public boolean isJava5()
    {
      return true;
    }

    /**
     * Returns the JDK properties
     */
    public Properties getProperties()
    {
      return System.getProperties();
    }

    /**
     * Returns the user name
     */
    public String getUserName()
    {
      return System.getProperty("user.name");
    }

    /**
     * Returns the JDK version
     */
    public String getVersion()
    {
      return System.getProperty("java.version");
    }

    /**
     * Returns the JDK home
     */
    public Path getHome()
    {
      return Vfs.lookup(System.getProperty("java.home"));
    }
  }

  class SecurityManagerConfig {
    private boolean _isEnable = true;

    SecurityManagerConfig()
    {
      if (_securityManager == null)
        _securityManager = new SecurityManager();
    }

    public void setEnable(boolean enable)
    {
      _isEnable = enable;
    }

    public void setValue(boolean enable)
    {
      setEnable(enable);
    }

    public void setPolicyFile(Path path)
      throws ConfigException
    {
      if (! path.canRead())
        throw new ConfigException(L().l("policy-file '{0}' must be readable.",
                                      path));

    }

    @PostConstruct
    public void init()
    {
      if (_isEnable)
        System.setSecurityManager(_securityManager);
    }
  }

  class ShutdownThread extends Thread {
    private volatile boolean _isShutdown;

    ShutdownThread()
    {
      setName("resin-shutdown");
      setDaemon(true);
    }

    /**
     * Starts the destroy sequence
     */
    public void startShutdown()
    {
      _isShutdown = true;
      LockSupport.unpark(this);
    }

    public void run()
    {
      while (! _isShutdown) {
        try {
          LockSupport.park();
        } catch (Exception e) {
        }
      }

      shutdownImpl();
    }
  }

  class FailSafeHaltThread extends Thread {
    private volatile boolean _isShutdown;

    FailSafeHaltThread()
    {
      setName("resin-fail-safe-halt");
      setDaemon(true);
    }

    /**
     * Starts the shutdown sequence
     */
    public void startShutdown()
    {
      _isShutdown = true;
      LockSupport.unpark(this);
    }

    public void run()
    {
      while (! _isShutdown) {
        try {
          LockSupport.park();
        } catch (Exception e) {
        }
      }

      long expire = System.currentTimeMillis() + _shutdownWaitMax;
      long now;

      while ((now = System.currentTimeMillis()) < expire) {
        try {
          Thread.interrupted();
          Thread.sleep(expire - now);
        } catch (Exception e) {
        }
      }

      Runtime.getRuntime().halt(Resin.EXIT_HALT);
    }
  }

  static class DynamicServer {
    private final String _cluster;
    private final String _address;
    private final int _port;

    DynamicServer(String cluster, String address, int port)
    {
      _cluster = cluster;
      _address = address;
      _port = port;
    }

    String getCluster()
    {
      return _cluster;
    }

    String getAddress()
    {
      return _address;
    }

    int getPort()
    {
      return _port;
    }
  }
}
TOP

Related Classes of com.caucho.server.resin.Resin$Var

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.