Start.d in-progress, coordinating with Jesse

This commit is contained in:
Joakim Erdfelt 2013-08-22 08:50:38 -07:00
parent 2605c90d23
commit 5600d411ed
10 changed files with 751 additions and 221 deletions

View File

@ -53,47 +53,7 @@ public class BaseHome
public BaseHome(File homeDir, File baseDir)
{
this.homeDir = homeDir;
this.baseDir = baseDir==null?homeDir:baseDir;
}
public void initialize(ArrayList<String> arguments)
{
Pattern jetty_home=Pattern.compile("(-D)?jetty.home=(.*)");
Pattern jetty_base=Pattern.compile("(-D)?jetty.base=(.*)");
for (String arg : arguments)
{
Matcher home_match=jetty_home.matcher(arg);
if (home_match.matches())
setHomeDir(new File(home_match.group(2)));
Matcher base_match=jetty_base.matcher(arg);
if (base_match.matches())
setBaseDir(new File(base_match.group(2)));
}
}
public boolean isBaseDifferent()
{
return homeDir.compareTo(baseDir) != 0;
}
public void setBaseDir(File dir)
{
this.baseDir = dir;
try
{
System.setProperty("jetty.base",dir.getCanonicalPath());
}
catch(IOException e)
{
e.printStackTrace();
}
}
public File getBaseDir()
{
return baseDir;
this.baseDir = baseDir == null?homeDir:baseDir;
}
public String getBase()
@ -105,6 +65,23 @@ public class BaseHome
return baseDir.getAbsolutePath();
}
public File getBaseDir()
{
return baseDir;
}
/**
* Create a file reference to some content in <code>"${jetty.base}"</code>
*
* @param path
* the path to reference
* @return the file reference
*/
public File getBaseFile(String path)
{
return new File(baseDir,FS.separators(path));
}
/**
* Get a specific file reference.
* <p>
@ -144,17 +121,9 @@ public class BaseHome
return new File(rpath);
}
public void setHomeDir(File dir)
public String getHome()
{
this.homeDir = dir;
try
{
System.setProperty("jetty.home",dir.getCanonicalPath());
}
catch(IOException e)
{
e.printStackTrace();
}
return homeDir.getAbsolutePath();
}
public File getHomeDir()
@ -162,9 +131,29 @@ public class BaseHome
return homeDir;
}
public String getHome()
public void initialize(StartArgs args)
{
return homeDir.getAbsolutePath();
Pattern jetty_home = Pattern.compile("(-D)?jetty.home=(.*)");
Pattern jetty_base = Pattern.compile("(-D)?jetty.base=(.*)");
for (String arg : args.getCommandLine())
{
Matcher home_match = jetty_home.matcher(arg);
if (home_match.matches())
{
setHomeDir(new File(home_match.group(2)));
}
Matcher base_match = jetty_base.matcher(arg);
if (base_match.matches())
{
setBaseDir(new File(base_match.group(2)));
}
}
}
public boolean isBaseDifferent()
{
return homeDir.compareTo(baseDir) != 0;
}
/**
@ -209,7 +198,7 @@ public class BaseHome
File baseFiles[] = basePath.listFiles(filter);
List<File> ret = new ArrayList<>();
if (baseFiles!=null)
if (baseFiles != null)
{
for (File base : baseFiles)
{
@ -262,6 +251,32 @@ public class BaseHome
return ret;
}
public void setBaseDir(File dir)
{
this.baseDir = dir;
try
{
System.setProperty("jetty.base",dir.getCanonicalPath());
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void setHomeDir(File dir)
{
this.homeDir = dir;
try
{
System.setProperty("jetty.home",dir.getCanonicalPath());
}
catch (IOException e)
{
e.printStackTrace();
}
}
private String toRelativePath(File dir, File path)
{
return dir.toURI().relativize(path.toURI()).toASCIIString();
@ -296,7 +311,7 @@ public class BaseHome
{
return path;
}
String value;
if (isBaseDifferent())

View File

@ -38,6 +38,22 @@ public class FS
}
}
public static class FilenameRegexFilter implements FileFilter
{
private final Pattern pattern;
public FilenameRegexFilter(String regex)
{
pattern = Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
}
@Override
public boolean accept(File path)
{
return path.isFile() && pattern.matcher(path.getName()).matches();
}
}
public static class FileNamesFilter implements FileFilter
{
private final String filenames[];
@ -65,22 +81,6 @@ public class FS
}
}
public static class FilenameRegexFilter implements FileFilter
{
private final Pattern pattern;
public FilenameRegexFilter(String regex)
{
pattern = Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
}
@Override
public boolean accept(File path)
{
return path.isFile() && pattern.matcher(path.getName()).matches();
}
}
public static class IniFilter extends FilenameRegexFilter
{
public IniFilter()
@ -96,11 +96,23 @@ public class FS
super("^.*\\.xml$");
}
}
public static boolean canReadDirectory(File path)
{
return (path.exists() && path.isDirectory() && path.canRead());
}
public static boolean canReadFile(File path)
{
return (path.exists() && path.isFile() && path.canRead());
}
public static void close(Closeable c)
{
if (c == null)
{
return;
}
try
{

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.start;
import static org.eclipse.jetty.start.UsageException.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
@ -52,14 +53,41 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Main start class.
* <p>
* Main start class. This class is intended to be the main class listed in the MANIFEST.MF of the start.jar archive. It allows an application to be started with
* the command "java -jar start.jar".
* </p>
*
* This class is intended to be the main class listed in the MANIFEST.MF of the start.jar archive. It allows the Jetty Application server to be started with the
* command "java -jar start.jar".
* <p>
* The behaviour of Main is controlled by the parsing of the {@link Config} "org/eclipse/start/start.config" file obtained as a resource or file.
* </p>
* Argument processing steps:
* <ol>
* <li>Directory Locations:
* <ul>
* <li>jetty.home=[directory] (the jetty.home location)</li>
* <li>jetty.base=[directory] (the jetty.base location)</li>
* </ul>
* </li>
* <li>Start Logging behavior:
* <ul>
* <li>--debug (debugging enabled)</li>
* <li>--start-log-file=logs/start.log (output start logs to logs/start.log location)</li>
* </ul>
* </li>
* <li>Module Resolution</li>
* <li>Properties Resolution</li>
* <li>Execution
* <ul>
* <li>--list-modules</li>
* <li>--list-classpath</li>
* <li>--list-config</li>
* <li>--version</li>
* <li>--help</li>
* <li>--dry-run</li>
* <li>--exec</li>
* <li>--stop</li>
* <li>(or normal startup)</li>
* </ul>
* </li>
* </ol>
*/
public class Main
{
@ -68,10 +96,6 @@ public class Main
private static final Pattern NNN_MODULE_INI = Pattern.compile("^(\\d\\d\\d-)(.*?\\.ini)(\\.disabled)?$",Pattern.CASE_INSENSITIVE);
private static final int EXIT_USAGE = 1;
private static final int ERR_LOGGING = -1;
private static final int ERR_INVOKE_MAIN = -2;
private static final int ERR_NOT_STOPPED = -4;
private static final int ERR_UNKNOWN = -5;
private boolean _showUsage = false;
private boolean _dumpVersions = false;
private boolean _listConfig = false;
@ -95,9 +119,13 @@ public class Main
if (xmls != null)
main.start(xmls);
}
catch (UsageException e)
{
usageExit(e.getCause(),e.getExitCode());
}
catch (Throwable e)
{
usageExit(e,ERR_UNKNOWN);
usageExit(e,UsageException.ERR_UNKNOWN);
}
}
@ -111,28 +139,80 @@ public class Main
return _config;
}
public List<String> processCommandLine(String[] args) throws Exception
public List<String> processCommandLine(String[] cmdLine) throws Exception
{
StartArgs args = new StartArgs(cmdLine);
BaseHome baseHome = _config.getBaseHome();
ArrayList<String> cmd_line = new ArrayList<>(Arrays.asList(args));
// Processing Order is important!
// ------------------------------------------------------------
// 1) Directory Locations
// Set Home and Base at the start, as all other paths encountered
// will be based off of them.
_config.getBaseHome().initialize(cmd_line);
List<StartIni> inis = new ArrayList<>();
// Do we have a start.ini?
File start_ini=_config.getBaseHome().getFile("start.ini");
if (start_ini.exists()&& start_ini.canRead() && !start_ini.isDirectory())
inis.add(new StartIni(start_ini));
// Do we have a start.d?
File start_d=_config.getBaseHome().getFile("start.d");
if (start_d.exists()&& start_d.canRead() && start_d.isDirectory())
_config.getBaseHome().initialize(args);
// ------------------------------------------------------------
// 2) Start Logging
StartLog.getInstance().initialize(baseHome,args);
// ------------------------------------------------------------
// 3) Load Inis
File start_ini = baseHome.getBaseFile("start.ini");
if (FS.canReadFile(start_ini))
{
List<File> files=new ArrayList<>();
args.parse(new StartIni(start_ini));
}
File start_d = _config.getBaseHome().getBaseFile("start.d");
if (FS.canReadDirectory(start_d))
{
List<File> files = new ArrayList<>();
for (File file : start_d.listFiles(new FS.IniFilter()))
{
files.add(file);
}
Collections.sort(files,new NaturalSort.Files());
for (File file : files)
{
args.parse(new StartIni(file));
}
}
// 4) Parse everything provided.
// This would be the directory information +
// the various start inis
// and then the raw command line arguments
args.parseCommandLine();
// 5) Module Registration
Modules modules = new Modules();
modules.registerAll(baseHome);
// 6) Active Module Resolution
for (String enabledModule : args.getEnabledModules())
{
modules.enable(enabledModule);
}
modules.buildGraph();
List<Module> activeModules = modules.resolveEnabled();
// 7) Lib & XML Expansion / Resolution
args.expandModules(baseHome, activeModules);
/*
// Do we have a start.ini?
File start_ini = _config.getBaseHome().getFile("start.ini");
if (start_ini.exists() && start_ini.canRead() && !start_ini.isDirectory())
inis.add(new StartIni(start_ini));
// Do we have a start.d?
File start_d = _config.getBaseHome().getFile("start.d");
if (start_d.exists() && start_d.canRead() && start_d.isDirectory())
{
List<File> files = new ArrayList<>();
for (File file : start_d.listFiles(new FS.IniFilter()))
files.add(file);
@ -145,18 +225,17 @@ public class Main
inis.add(new StartIni(cmd_line));
// TODO - we could sort the StartIni files by dependency here
// The XML Configuration Files to initialize with
List<String> xmls = new ArrayList<String>();
// Expand arguments
for (StartIni ini:inis)
for (StartIni ini : inis)
{
String source = "<cmdline>";
if (ini.getFile()!=null)
source=ini.getFile().getAbsolutePath();
if (ini.getFile() != null)
source = ini.getFile().getAbsolutePath();
for (String arg : ini.getLines())
{
@ -372,10 +451,10 @@ public class Main
xmls.add(arg);
}
}
return xmls;
}
*/
return null;
}
private void download(String arg)
{
@ -487,13 +566,13 @@ public class Main
}
else if (info.equals("@STARTINI"))
{
BaseHome hb=_config.getBaseHome();
BaseHome hb = _config.getBaseHome();
File start_d = hb.getFile("start.d");
if (start_d.exists() && start_d.isDirectory())
{
File[] files=start_d.listFiles(new FS.FilenameRegexFilter("(\\d\\d\\d-)?.*\\.ini(\\.disabled)?"));
File[] files = start_d.listFiles(new FS.FilenameRegexFilter("(\\d\\d\\d-)?.*\\.ini(\\.disabled)?"));
Arrays.sort(files,new NaturalSort.Files());
for (File file: files)
for (File file : files)
{
String path = _config.getBaseHome().toShortForm(file);
System.out.printf("%s%s%n",indent,path);
@ -1168,18 +1247,18 @@ public class Main
_jvmArgs.addAll(jvmArgs);
}
private void enable(final String module,boolean verbose) throws IOException
private void enable(final String module, boolean verbose) throws IOException
{
final String mini = module + ".ini";
final String disable = module + ".ini.disabled";
BaseHome hb=_config.getBaseHome();
BaseHome hb = _config.getBaseHome();
File start_d = hb.getFile("start.d");
boolean found=false;
File enabled=null;
boolean found = false;
File enabled = null;
if (start_d.exists() && start_d.isDirectory())
{
for (File file: start_d.listFiles(new FS.FilenameRegexFilter("(\\d\\d\\d-)?"+Pattern.quote(module)+"\\.ini(\\.disabled)?")))
for (File file : start_d.listFiles(new FS.FilenameRegexFilter("(\\d\\d\\d-)?" + Pattern.quote(module) + "\\.ini(\\.disabled)?")))
{
String n = file.getName();
if (n.equalsIgnoreCase(mini))
@ -1189,20 +1268,20 @@ public class Main
found = true;
break;
}
if (n.equalsIgnoreCase(disable))
{
enabled=new File(file.getParentFile(),mini);
enabled = new File(file.getParentFile(),mini);
System.err.printf("Enabling Module %s as %s%n",module,hb.toShortForm(enabled));
file.renameTo(enabled);
found = true;
break;
}
Matcher matcher = NNN_MODULE_INI.matcher(n);
if (matcher.matches())
{
if (matcher.group(3)==null)
if (matcher.group(3) == null)
{
if (verbose)
System.err.printf("Module %s already enabled in %s as %s%n",module,hb.toShortForm(file.getParent()),n);
@ -1210,12 +1289,12 @@ public class Main
}
else
{
enabled=new File(file.getParentFile(),matcher.group(1)+mini);
enabled = new File(file.getParentFile(),matcher.group(1) + mini);
System.err.printf("Enabling Module %s as %s%n",module,hb.toShortForm(enabled));
file.renameTo(enabled);
found = true;
}
}
}
}
}
@ -1226,14 +1305,14 @@ public class Main
if (start_home.exists() && start_home.isDirectory())
{
for (File file: start_home.listFiles(new FS.FilenameRegexFilter("(\\d\\d\\d-)?"+Pattern.quote(module)+"\\.ini(\\.disabled)?")))
for (File file : start_home.listFiles(new FS.FilenameRegexFilter("(\\d\\d\\d-)?" + Pattern.quote(module) + "\\.ini(\\.disabled)?")))
{
try
{
String n = file.getName();
if (n.equalsIgnoreCase(mini) || n.equalsIgnoreCase(disable))
{
enabled=new File(start_d,mini);
enabled = new File(start_d,mini);
Files.copy(file.toPath(),enabled.toPath());
System.err.printf("Enabling Module %s as %s%n",module,hb.toShortForm(enabled));
found = true;
@ -1243,14 +1322,14 @@ public class Main
Matcher matcher = NNN_MODULE_INI.matcher(n);
if (matcher.matches())
{
enabled=new File(start_d,matcher.group(1)+mini);
enabled = new File(start_d,matcher.group(1) + mini);
Files.copy(file.toPath(),enabled.toPath());
System.err.printf("Enabling Module %s as %s%n",module,hb.toShortForm(enabled));
found = true;
break;
}
}
catch(IOException e)
catch (IOException e)
{
e.printStackTrace();
}
@ -1262,20 +1341,20 @@ public class Main
{
System.err.printf("Module %s not found!%n",module);
}
else if (enabled!=null)
else if (enabled != null)
{
// handle dependencies
StartIni ini=new StartIni(enabled);
for (String line:ini.getLineMatches(Pattern.compile("^DEPEND=.*$")))
StartIni ini = new StartIni(enabled);
for (String line : ini.getLineMatches(Pattern.compile("^DEPEND=.*$")))
{
String depend=line.trim().split("=")[1];
for (String m:depend.split(","))
String depend = line.trim().split("=")[1];
for (String m : depend.split(","))
enable(m,false);
}
for (String line:ini.getLineMatches(Pattern.compile("^EXCLUDE=.*$")))
for (String line : ini.getLineMatches(Pattern.compile("^EXCLUDE=.*$")))
{
String depend=line.trim().split("=")[1];
for (String m:depend.split(","))
String depend = line.trim().split("=")[1];
for (String m : depend.split(","))
disable(m,false);
}
}
@ -1286,12 +1365,12 @@ public class Main
final String mini = module + ".ini";
final String disable = module + ".ini.disabled";
BaseHome hb=_config.getBaseHome();
BaseHome hb = _config.getBaseHome();
File start_d = hb.getFile("start.d");
boolean found=false;
boolean found = false;
if (start_d.exists() && start_d.isDirectory())
{
for (File file: start_d.listFiles(new FS.FilenameRegexFilter("(\\d\\d\\d-)?"+Pattern.quote(module)+"\\.ini(\\.disabled)?")))
for (File file : start_d.listFiles(new FS.FilenameRegexFilter("(\\d\\d\\d-)?" + Pattern.quote(module) + "\\.ini(\\.disabled)?")))
{
String n = file.getName();
if (n.equalsIgnoreCase(disable))
@ -1311,7 +1390,7 @@ public class Main
Matcher matcher = NNN_MODULE_INI.matcher(n);
if (matcher.matches())
{
if (matcher.group(3)!=null)
if (matcher.group(3) != null)
{
if (verbose)
System.err.printf("Module %s already disabled in %s as %s%n",module,hb.toShortForm(file.getParent()),n);
@ -1319,7 +1398,7 @@ public class Main
}
else
{
String disabled=matcher.group(1)+disable;
String disabled = matcher.group(1) + disable;
System.err.printf("Disabling Module %s in %s as %s%n",module,hb.toShortForm(file.getParent()),disabled);
file.renameTo(new File(file.getParentFile(),disabled));
found = true;

View File

@ -0,0 +1,213 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start;
import static org.eclipse.jetty.start.UsageException.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The Arguments required to start Jetty.
*/
public class StartArgs
{
// TODO: might make sense to declare this in modules/base.mod
private static final String SERVER_MAIN = "org.eclipse.jetty.xml.XmlConfiguration.class";
private List<String> commandLine = new ArrayList<>();
private List<String> enabledModules = new ArrayList<>();
private List<String> downloads = new ArrayList<>();
private List<String> classpath = new ArrayList<>();
private List<String> xmls = new ArrayList<>();
private Map<String, String> properties = new HashMap<>();
private Map<String, String> systemProperties = new HashMap<>();
private Map<String, String> jvmArgs = new HashMap<>();
// Should the server be run?
private boolean run = true;
private boolean help = false;
private boolean stopCommand = false;
private boolean listModules = false;
private boolean listClasspath = false;
private boolean listConfig = false;
private boolean version = false;
private boolean dryRun = false;
private boolean exec = false;
public StartArgs(String[] commandLineArgs)
{
commandLine.addAll(Arrays.asList(commandLineArgs));
}
public List<String> getStartCommands()
{
return null;
}
public List<String> getCommandLine()
{
return this.commandLine;
}
public void parse(TextFile file)
{
for (String line : file)
{
parse(line);
}
}
public void parse(String arg)
{
if ("--help".equals(arg) || "-?".equals(arg))
{
help = true;
run = false;
return;
}
if ("--stop".equals(arg))
{
stopCommand = true;
run = false;
/*
* int port = Integer.parseInt(_config.getProperty("STOP.PORT","-1")); String key = _config.getProperty("STOP.KEY",null); int timeout =
* Integer.parseInt(_config.getProperty("STOP.WAIT","0")); stop(port,key,timeout);
*/
return;
}
if (arg.startsWith("--download="))
{
downloads.add(getValue(arg));
return;
}
if ("--list-classpath".equals(arg) || "--version".equals(arg) || "-v".equals(arg) || "--info".equals(arg))
{
listClasspath = true;
run = false;
return;
}
if ("--list-config".equals(arg))
{
listConfig = true;
run = false;
return;
}
if ("--dry-run".equals(arg) || "--exec-print".equals(arg))
{
dryRun = true;
run = false;
return;
}
if (arg.startsWith("--enable="))
{
String moduleName = getValue(arg);
// TODO:
run = false;
return;
}
if (arg.startsWith("--disable="))
{
String moduleName = getValue(arg);
// TODO:
run = false;
return;
}
if (arg.startsWith("MODULE="))
{
enabledModules.add(getValue(arg));
return;
}
if (arg.startsWith("MODULES="))
{
for (String moduleName : getValue(arg).split(","))
{
if (moduleName == null)
{
continue; // skip
}
enabledModules.add(moduleName.trim());
}
return;
}
// Start property (syntax similar to System property)
if(arg.startsWith("-D"))
{
String[] assign = arg.substring(2).split("=",2);
// TODO systemProperties.add(assign[0]);
switch (assign.length)
{
case 2:
System.setProperty(assign[0],assign[1]);
break;
case 1:
System.setProperty(assign[0],"");
break;
default:
break;
}
return;
}
}
private String getValue(String arg)
{
int idx = arg.indexOf('=');
if (idx == (-1))
{
throw new UsageException(ERR_BAD_ARG,"Argument is missing a required value: %s",arg);
}
String value = arg.substring(idx + 1).trim();
if (value.length() <= 0)
{
throw new UsageException(ERR_BAD_ARG,"Argument is missing a required value: %s",arg);
}
return value;
}
public void parseCommandLine()
{
for (String line : commandLine)
{
parse(line);
}
}
public List<String> getEnabledModules()
{
return this.enabledModules;
}
public void expandModules(BaseHome baseHome, List<Module> activeModules)
{
// TODO Auto-generated method stub
}
}

View File

@ -18,111 +18,34 @@
package org.eclipse.jetty.start;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
/**
* Simple Start .INI handler
*/
public class StartIni implements Iterable<String>
public class StartIni extends TextFile
{
public static interface IncludeListener
{
public List<StartIni> onIniInclude(String path) throws IOException;
}
private final File file;
private final List<String> lines= new ArrayList<>();
public StartIni(File file) throws FileNotFoundException, IOException
{
this.file = file;
try (FileReader reader = new FileReader(file))
{
try (BufferedReader buf = new BufferedReader(reader))
{
String line;
while ((line = buf.readLine()) != null)
process(line.trim());
}
}
super(file);
}
public StartIni(ArrayList<String> arguments)
public void addUniqueLine(String line)
{
file=null;
for (String line: arguments)
process(line);
}
private void process(String line)
{
if (line.length() == 0)
return;
if (line.charAt(0) == '#')
return;
// Smart Handling, split into multiple OPTIONS lines (for dup check reasons)
if (line.startsWith("OPTIONS="))
if (line.startsWith("MODULES="))
{
int idx = line.indexOf('=');
String value = line.substring(idx + 1);
for (String part : value.split(","))
{
addUniqueLine("OPTION=" + part);
super.addUniqueLine("MODULE=" + part);
}
}
else
{
// Add line as-is
addUniqueLine(line);
super.addUniqueLine(line);
}
}
private void addUniqueLine(String line)
{
if (lines.contains(line))
{
// skip
return;
}
lines.add(line);
}
public File getFile()
{
return file;
}
public List<String> getLineMatches(Pattern pattern)
{
List<String> ret = new ArrayList<>();
for (String line : lines)
{
if (pattern.matcher(line).matches())
{
ret.add(line);
}
}
return ret;
}
public List<String> getLines()
{
return lines;
}
@Override
public Iterator<String> iterator()
{
return lines.iterator();
}
}

View File

@ -0,0 +1,125 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Centralized Place for logging.
* <p>
* Because startup cannot rely on Jetty's Logging, an alternative logging is established.
* <p>
* Optional behavior is to create a ${jetty.base}/logs/start.log with whatever output the startup process produces.
*/
public class StartLog
{
private final static StartLog INSTANCE = new StartLog();
public static StartLog getInstance()
{
return INSTANCE;
}
private boolean debug = false;
public void initLogFile(File logfile) throws IOException
{
if (logfile != null)
{
File logDir = logfile.getParentFile();
if (!logDir.exists() || !logDir.canWrite())
{
String err = String.format("Cannot write %s to directory %s [directory doesn't exist or is read-only]",logfile.getName(),
logDir.getAbsolutePath());
throw new UsageException(UsageException.ERR_LOGGING,new IOException(err));
}
File startLog = logfile;
if (!startLog.exists() && !startLog.createNewFile())
{
// Output about error is lost in majority of cases.
throw new UsageException(UsageException.ERR_LOGGING,new IOException("Unable to create: " + startLog.getAbsolutePath()));
}
if (!startLog.canWrite())
{
// Output about error is lost in majority of cases.
throw new UsageException(UsageException.ERR_LOGGING,new IOException("Unable to write to: " + startLog.getAbsolutePath()));
}
PrintStream logger = new PrintStream(new FileOutputStream(startLog,false));
System.setOut(logger);
System.setErr(logger);
System.out.println("Establishing " + logfile + " on " + new Date());
}
}
public static void debug(String format, Object... args)
{
if (INSTANCE.debug)
{
System.out.printf(format + "%n",args);
}
}
public static void warn(String format, Object... args)
{
System.err.printf(format + "%n",args);
}
public void initialize(BaseHome baseHome, StartArgs args) throws IOException
{
Pattern debugBoolPat = Pattern.compile("(-D)?debug=(.*)");
Pattern debugPat = Pattern.compile("(-D)?debug");
Pattern logFilePat = Pattern.compile("(-D)?start-log-file=(.*)");
Matcher matcher;
for (String arg : args.getCommandLine())
{
matcher = debugBoolPat.matcher(arg);
if (matcher.matches())
{
debug = Boolean.parseBoolean(matcher.group(2));
continue;
}
matcher = debugPat.matcher(arg);
if (matcher.matches())
{
debug = true;
continue;
}
matcher = logFilePat.matcher(arg);
if (matcher.matches())
{
String filename = matcher.group(2);
File logfile = baseHome.getBaseFile(filename);
initLogFile(logfile);
}
}
}
}

View File

@ -0,0 +1,110 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
/**
* Simple common abstraction for Text files, that consist of a series of lines.
* <p>
* Ignoring lines that are empty, deemed to be comments, or are duplicates of prior lines.
*/
public class TextFile implements Iterable<String>
{
private final File file;
private final List<String> lines = new ArrayList<>();
public TextFile(File file) throws FileNotFoundException, IOException
{
this.file = file;
try (FileReader reader = new FileReader(file))
{
try (BufferedReader buf = new BufferedReader(reader))
{
String line;
while ((line = buf.readLine()) != null)
{
process(line.trim());
}
}
}
}
public void addUniqueLine(String line)
{
if (lines.contains(line))
{
// skip
return;
}
lines.add(line);
}
public File getFile()
{
return file;
}
public List<String> getLineMatches(Pattern pattern)
{
List<String> ret = new ArrayList<>();
for (String line : lines)
{
if (pattern.matcher(line).matches())
{
ret.add(line);
}
}
return ret;
}
public List<String> getLines()
{
return lines;
}
@Override
public Iterator<String> iterator()
{
return lines.iterator();
}
private void process(String line)
{
if (line.length() == 0)
{
return;
}
if (line.charAt(0) == '#')
{
return;
}
addUniqueLine(line);
}
}

View File

@ -0,0 +1,50 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start;
/**
* A Usage Error has occured. Print the usage and exit with the appropriate exit code.
*/
@SuppressWarnings("serial")
public class UsageException extends RuntimeException
{
public static final int ERR_LOGGING = -1;
public static final int ERR_INVOKE_MAIN = -2;
public static final int ERR_NOT_STOPPED = -4;
public static final int ERR_UNKNOWN = -5;
public static final int ERR_BAD_ARG = -6;
private int exitCode;
public UsageException(int exitCode, Throwable cause)
{
super(cause);
this.exitCode = exitCode;
}
public UsageException(int exitCode, String format, Object... objs)
{
super(String.format(format,objs));
this.exitCode = exitCode;
}
public int getExitCode()
{
return exitCode;
}
}

View File

@ -32,11 +32,13 @@ import java.util.Vector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
*/
@Ignore
public class MainTest
{
/* ------------------------------------------------------------ */

View File

@ -39,6 +39,7 @@ import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@Ignore
public class PropertyPassingTest
{
private static class ConsoleCapture implements Runnable