/*
* 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.resin;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.caucho.VersionFactory;
import com.caucho.log.EnvironmentStream;
import com.caucho.log.RotateStream;
import com.caucho.server.util.JniCauchoSystem;
import com.caucho.util.L10N;
import com.caucho.vfs.Path;
import com.caucho.vfs.QJniServerSocket;
import com.caucho.vfs.QServerSocket;
import com.caucho.vfs.Vfs;
import com.caucho.vfs.WriteStream;
/**
* The parsed Resin command-line arguments
*/
class ResinArgs
{
private static final Logger log = Logger.getLogger(ResinArgs.class.getName());
private static final L10N L = new L10N(ResinArgs.class);
private String _serverId = "default";
private Path _resinHome;
private Path _rootDirectory;
private Path _dataDirectory;
private String _resinConf;
private Socket _pingSocket;
private String _joinCluster;
private String _serverAddress;
private int _serverPort;
private boolean _isRestart;
private ArrayList<BoundPort> _boundPortList
= new ArrayList<BoundPort>();
private String _stage = null;
private boolean _isDumpHeapOnExit;
public ResinArgs(String []args)
throws Exception
{
preConfigureInit();
parseCommandLine(args);
}
/**
* Must be called after the Resin.create()
*/
private void preConfigureInit()
{
String resinHome = System.getProperty("resin.home");
if (resinHome != null)
_resinHome = Vfs.lookup(resinHome);
else
_resinHome = Vfs.getPwd();
_rootDirectory = _resinHome;
// server.root backwards compat
String resinRoot = System.getProperty("server.root");
if (resinRoot != null)
_rootDirectory = Vfs.lookup(resinRoot);
// resin.root backwards compat
resinRoot = System.getProperty("resin.root");
if (resinRoot != null)
_rootDirectory = Vfs.lookup(resinRoot);
}
public String getServerId()
{
return _serverId;
}
public Path getResinHome()
{
return _resinHome;
}
/**
* Gets the root directory.
*/
public Path getRootDirectory()
{
return _rootDirectory;
}
/**
* Gets the root directory.
*/
public Path getDataDirectory()
{
return _dataDirectory;
}
public Socket getPingSocket()
{
return _pingSocket;
}
/**
* The configuration file used to start the server.
*/
public String getResinConf()
{
return _resinConf;
}
public Path getResinConfPath()
{
Path pwd = Vfs.lookup();
Path resinConf = null;
String resinConfFile = getResinConf();
if (resinConfFile != null) {
if (log.isLoggable(Level.FINER))
log.finer(this + " looking for conf in " + pwd.lookup(resinConfFile));
resinConf = pwd.lookup(resinConfFile);
}
else if (pwd.lookup("conf/resin.xml").canRead())
resinConfFile = "conf/resin.xml";
else { // backward compat
resinConfFile = "conf/resin.conf";
}
Path rootDirectory = getRootDirectory();
if (resinConf == null || ! resinConf.exists()) {
if (log.isLoggable(Level.FINER))
log.finer(this + " looking for conf in "
+ rootDirectory.lookup(resinConfFile));
resinConf = _rootDirectory.lookup(resinConfFile);
}
if (! resinConf.exists() && ! _resinHome.equals(_rootDirectory)) {
if (log.isLoggable(Level.FINER))
log.finer(this + " looking for conf in "
+ _resinHome.lookup(resinConfFile));
resinConf = _resinHome.lookup(resinConfFile);
}
// for error messages, show path relative to rootDirectory
if (! resinConf.exists())
resinConf = rootDirectory.lookup(resinConfFile);
return resinConf;
}
/**
* Returns the bound port list.
*/
public ArrayList<BoundPort> getBoundPortList()
{
return _boundPortList;
}
/**
* Returns the stage to start with.
*/
public String getStage()
{
return _stage;
}
public String getJoinCluster()
{
return _joinCluster;
}
public String getServerAddress()
{
return _serverAddress;
}
public int getServerPort()
{
return _serverPort;
}
public boolean isDumpHeapOnExit()
{
return _isDumpHeapOnExit;
}
private void parseCommandLine(String []argv)
throws Exception
{
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"))) {
_resinConf = 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("-server")
|| argv[i].equals("--server"))) {
_serverId = argv[i + 1];
if (_serverId.equals(""))
_serverId = "default";
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")
|| argv[i].equals("-server-root")
|| argv[i].equals("--server-root")) {
_rootDirectory = _resinHome.lookup(argv[i + 1]);
i += 2;
}
else if (argv[i].equals("-data-directory")
|| argv[i].equals("--data-directory")) {
_dataDirectory = Vfs.lookup(argv[i + 1]);
i += 2;
}
else if (argv[i].equals("-service")) {
JniCauchoSystem.create().initJniBackground();
// windows service
i += 1;
}
else if (i + 1 < len
&& (argv[i].equals("-join-cluster")
|| argv[i].equals("--join-cluster"))) {
_joinCluster = argv[i + 1];
i += 2;
}
else if (i + 1 < len
&& (argv[i].equals("-server-address")
|| argv[i].equals("--server-address"))) {
_serverAddress = argv[i + 1];
i += 2;
}
else if (i + 1 < len
&& (argv[i].equals("-server-port")
|| argv[i].equals("--server-port"))) {
_serverPort = Integer.parseInt(argv[i + 1]);
i += 2;
}
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(1);
}
/*
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("gui")) {
i += 1;
}
else if (argv[i].equals("console")) {
i += 1;
}
else if (argv[i].equals("watchdog")) {
i += 1;
}
else if (argv[i].equals("start-with-foreground")) {
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: bin/resin.sh [-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(" -data-directory <dir> : select a resin-data directory"));
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"));
}
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;
}
}
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;
}
}
}