432321 - jetty-start / Allow defining extra start directories for common configurations

+ Introduction of ConfigSources (a properly ordered list of ConfigSource
  impls) to aide in initial setup of configuration sources, prior to
  being parsed by StartArgs for the final runtime configuration of
  the jetty server.
This commit is contained in:
Joakim Erdfelt 2014-04-10 11:54:27 -07:00
parent 1b9f0cb945
commit 682a01792f
13 changed files with 1169 additions and 131 deletions

View File

@ -563,7 +563,7 @@ public class Main
// ------------------------------------------------------------
// 1) Directory Locations
// Set Home and Base at the start, as all other paths encountered
// Set Home and Base at the start, as many other paths encountered
// will be based off of them.
baseHome.initialize(args);

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Stack;
@ -63,6 +64,48 @@ public final class Props implements Iterable<Prop>
private Map<String, Prop> props = new HashMap<>();
public void addAll(Props other)
{
this.props.putAll(other.props);
}
public void addAllProperties(List<String> args, String source)
{
for (String arg : args)
{
// Start property (syntax similar to System property)
if (arg.startsWith("-D"))
{
String[] assign = arg.substring(2).split("=",2);
switch (assign.length)
{
case 2:
setProperty(assign[0],assign[1],source);
break;
case 1:
setProperty(assign[0],"",source);
break;
default:
break;
}
continue;
}
// Is this a raw property declaration?
int idx = arg.indexOf('=');
if (idx >= 0)
{
String key = arg.substring(0,idx);
String value = arg.substring(idx + 1);
setProperty(key,value,source);
continue;
}
// All other strings are ignored
}
}
public String cleanReference(String property)
{
String name = property.trim();
@ -156,9 +199,14 @@ public final class Props implements Iterable<Prop>
}
public Prop getProp(String key)
{
return getProp(key,true);
}
public Prop getProp(String key, boolean searchSystemProps)
{
Prop prop = props.get(key);
if (prop == null)
if ((prop == null) && searchSystemProps)
{
// try system property
prop = getSystemProperty(key);
@ -214,6 +262,11 @@ public final class Props implements Iterable<Prop>
return props.values().iterator();
}
public void reset()
{
props.clear();
}
public void setProperty(Prop prop)
{
props.put(prop.key,prop);

View File

@ -68,8 +68,9 @@ public class StartArgs
}
private static final String SERVER_MAIN = "org.eclipse.jetty.xml.XmlConfiguration";
private List<String> commandLine = new ArrayList<>();
/** List of enabled modules */
private Set<String> modules = new HashSet<>();
/** Map of enabled modules to the source of where that activation occurred */

View File

@ -23,10 +23,12 @@ import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import org.eclipse.jetty.start.config.ConfigSource;
/**
* Simple Start .INI handler
*/
public class StartIni extends TextFile implements ConfigSource
public class StartIni extends TextFile
{
private Path basedir;
@ -78,18 +80,4 @@ public class StartIni extends TextFile implements ConfigSource
{
return basedir;
}
@Override
public String getId()
{
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> getArgs()
{
// TODO Auto-generated method stub
return null;
}
}

View File

@ -0,0 +1,117 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.config;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jetty.start.Props;
/**
* Configuration Source representing the Command Line arguments.
*/
public class CommandLineConfigSource implements ConfigSource
{
public static final String CMD_LINE_SOURCE = "<command-line>";
private final List<String> args;
private final Props props;
public CommandLineConfigSource(String rawargs[])
{
this.args = Arrays.asList(rawargs);
this.props = new Props();
this.props.addAllProperties(args, CMD_LINE_SOURCE);
}
@Override
public Props getProps()
{
return props;
}
@Override
public String getProperty(String key)
{
return props.getString(key);
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
CommandLineConfigSource other = (CommandLineConfigSource)obj;
if (args == null)
{
if (other.args != null)
{
return false;
}
}
else if (!args.equals(other.args))
{
return false;
}
return true;
}
@Override
public List<String> getArgs()
{
return args;
}
@Override
public String getId()
{
return CMD_LINE_SOURCE;
}
@Override
public int getWeight()
{
return -1; // default value for command line
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = (prime * result) + ((args == null)?0:args.hashCode());
return result;
}
@Override
public String toString()
{
return String.format("%s[%s,args.length=%d]",this.getClass().getSimpleName(),getId(),getArgs().size());
}
}

View File

@ -0,0 +1,76 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.config;
import java.util.List;
import org.eclipse.jetty.start.Props;
/**
* A Configuration Source
*/
public interface ConfigSource
{
/**
* The identifier for this source.
* <p>
* Used in end-user display of the source.
*
* @return the configuration source identifier.
*/
public String getId();
/**
* The weight of this source, used for proper ordering of the config source search order.
* <p>
* Recommended Weights:
* <pre>
* -1 = the command line
* 0 = the ${jetty.base} source
* [1..n] = extra-start-dir entries from command line
* [n+1..n] = extra-start-dir entries from start.ini (or start.d/*.ini)
* 9999999 = the ${jetty.home} source
* </pre>
*
* @return the weight of the config source. (lower value is more important)
*/
public int getWeight();
/**
* The list of Arguments for this ConfigSource
*
* @return the list of Arguments for this ConfigSource
*/
public List<String> getArgs();
/**
* The properties for this ConfigSource
*
* @return the properties for this ConfigSource
*/
public Props getProps();
/**
* Return the value of the specified property.
*
* @param key the key to lookup
* @return the value of the property, or null if not found
*/
public String getProperty(String key);
}

View File

@ -0,0 +1,126 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.config;
import static org.eclipse.jetty.start.UsageException.*;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.start.FS;
import org.eclipse.jetty.start.Props;
import org.eclipse.jetty.start.Props.Prop;
import org.eclipse.jetty.start.UsageException;
/**
* Weighted List of ConfigSources.
* <p>
*/
public class ConfigSources implements Iterable<ConfigSource>
{
private static class WeightedConfigSourceComparator implements Comparator<ConfigSource>
{
@Override
public int compare(ConfigSource o1, ConfigSource o2)
{
return o1.getWeight() - o2.getWeight();
}
}
private LinkedList<ConfigSource> sources = new LinkedList<>();
private Props props = new Props();
private AtomicInteger xtraSourceWeight = new AtomicInteger(1);
public void add(ConfigSource source) throws IOException
{
if (sources.contains(source))
{
// TODO: needs a better/more clear error message
throw new UsageException(ERR_BAD_ARG,"Duplicate Configuration Source Reference: " + source);
}
sources.add(source);
Collections.sort(sources,new WeightedConfigSourceComparator());
updateProps();
// look for --extra-start-dir entries
for (String arg : source.getArgs())
{
if (arg.startsWith("--extra-start-dir"))
{
String ref = getValue(arg);
String dirName = props.expand(ref);
Path dir = FS.toPath(dirName);
DirConfigSource dirsource = new DirConfigSource(ref,dir,xtraSourceWeight.incrementAndGet(),true);
add(dirsource);
}
}
}
public Prop getProp(String key)
{
return props.getProp(key);
}
public Props getProps()
{
return props;
}
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;
}
@Override
public Iterator<ConfigSource> iterator()
{
return sources.iterator();
}
private void updateProps()
{
props.reset();
// add all properties from config sources (in reverse order)
ListIterator<ConfigSource> iter = sources.listIterator(sources.size());
while (iter.hasPrevious())
{
ConfigSource source = iter.previous();
props.addAll(source.getProps());
}
}
}

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.start;
package org.eclipse.jetty.start.config;
import java.io.IOException;
import java.nio.file.DirectoryStream;
@ -26,6 +26,12 @@ import java.nio.file.PathMatcher;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.start.FS;
import org.eclipse.jetty.start.PathMatchers;
import org.eclipse.jetty.start.Props;
import org.eclipse.jetty.start.Props.Prop;
import org.eclipse.jetty.start.StartIni;
/**
* A Directory based {@link ConfigSource}.
* <p>
@ -35,7 +41,9 @@ public class DirConfigSource implements ConfigSource
{
private final String id;
private final Path dir;
private final int weight;
private final List<String> args;
private final Props props;
/**
* Create DirConfigSource with specified identifier and directory.
@ -44,15 +52,19 @@ public class DirConfigSource implements ConfigSource
* the identifier for this {@link ConfigSource}
* @param dir
* the directory for this {@link ConfigSource}
* @param weight
* the configuration weight (used for search order)
* @param canHaveArgs
* true if this directory can have start.ini or start.d entries. (false for directories like ${jetty.home}, for example)
* @throws IOException
* if unable to load the configuration args
*/
public DirConfigSource(String id, Path dir, boolean canHaveArgs) throws IOException
public DirConfigSource(String id, Path dir, int weight, boolean canHaveArgs) throws IOException
{
this.id = id;
this.dir = dir;
this.weight = weight;
this.props = new Props();
this.args = new ArrayList<>();
@ -62,7 +74,8 @@ public class DirConfigSource implements ConfigSource
if (FS.canReadFile(iniFile))
{
StartIni ini = new StartIni(iniFile);
args.addAll(ini.getArgs());
args.addAll(ini.getLines());
this.props.addAllProperties(ini.getLines(),iniFile.toString());
}
Path startDdir = dir.resolve("start.d");
@ -85,13 +98,49 @@ public class DirConfigSource implements ConfigSource
if (FS.canReadFile(diniFile))
{
StartIni ini = new StartIni(diniFile);
args.addAll(ini.getArgs());
args.addAll(ini.getLines());
this.props.addAllProperties(ini.getLines(),diniFile.toString());
}
}
}
}
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((dir == null)?0:dir.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DirConfigSource other = (DirConfigSource)obj;
if (dir == null)
{
if (other.dir != null)
return false;
}
else if (!dir.equals(other.dir))
return false;
return true;
}
@Override
public List<String> getArgs()
{
return args;
}
public Path getDir()
{
return dir;
@ -104,8 +153,31 @@ public class DirConfigSource implements ConfigSource
}
@Override
public List<String> getArgs()
public int getWeight()
{
return args;
return weight;
}
@Override
public Props getProps()
{
return props;
}
@Override
public String getProperty(String key)
{
Prop prop = props.getProp(key,false);
if (prop == null)
{
return null;
}
return prop.value;
}
@Override
public String toString()
{
return String.format("%s[%s,%s,args.length=%d]",this.getClass().getSimpleName(),id,dir,getArgs().size());
}
}

View File

@ -16,28 +16,21 @@
// ========================================================================
//
package org.eclipse.jetty.start;
package org.eclipse.jetty.start.config;
import java.util.List;
import java.io.IOException;
import java.nio.file.Path;
/**
* A Configuration Source
* ${jetty.base} specific ConfigSource
*/
public interface ConfigSource
public class JettyBaseConfigSource extends DirConfigSource
{
/**
* The identifier for this source.
* <p>
* Used in end-user display of the source.
*
* @return the configuration source identifier.
*/
public String getId();
// Standard weight for ${jetty.base}, so that it comes after command line, and before everything else
private final static int WEIGHT = 0;
/**
* The list of Arguments for this ConfigSource
*
* @return the list of Arguments for this ConfigSource
*/
public List<String> getArgs();
public JettyBaseConfigSource(Path dir) throws IOException
{
super("${jetty.base}",dir,WEIGHT,true);
}
}

View File

@ -16,34 +16,21 @@
// ========================================================================
//
package org.eclipse.jetty.start;
package org.eclipse.jetty.start.config;
import java.util.Arrays;
import java.util.List;
import java.io.IOException;
import java.nio.file.Path;
/**
* Configuration Source representing the Command Line arguments.
* ${jetty.home} specific ConfigSource
*/
public class CommandLineConfigSource implements ConfigSource
public class JettyHomeConfigSource extends DirConfigSource
{
public static final String CMD_LINE_SOURCE = "<command-line>";
// Standard weight for ${jetty.home}, so that it comes after everything else
private final static int WEIGHT = 9999999;
private final List<String> args;
public CommandLineConfigSource(String rawargs[])
public JettyHomeConfigSource(Path dir) throws IOException
{
args = Arrays.asList(rawargs);
}
@Override
public String getId()
{
return CMD_LINE_SOURCE;
}
@Override
public List<String> getArgs()
{
return args;
super("${jetty.home}",dir,WEIGHT,false);
}
}

View File

@ -21,17 +21,11 @@ package org.eclipse.jetty.start;
import static org.hamcrest.Matchers.*;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.start.Props.Prop;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Assert;
import org.junit.Rule;
@ -69,26 +63,6 @@ public class ExtraStartTest
@Rule
public TestingDir testdir = new TestingDir();
private void copyTestDir(String testResourceDir, File destDir) throws IOException
{
FS.ensureDirExists(destDir);
File srcDir = MavenTestingUtils.getTestResourceDir(testResourceDir);
IO.copyDir(srcDir,destDir);
}
private void makeFile(File dir, String relFilePath, String... contents) throws IOException
{
File outputFile = new File(dir,OS.separators(relFilePath));
FS.ensureDirExists(outputFile.getParentFile());
try (FileWriter writer = new FileWriter(outputFile); PrintWriter out = new PrintWriter(writer))
{
for (String content : contents)
{
out.println(content);
}
}
}
private MainResult runMain(File baseDir, File homeDir, String... cmdLineArgs) throws Exception
{
MainResult ret = new MainResult();
@ -108,15 +82,15 @@ public class ExtraStartTest
@Test
public void testNoExtras() throws Exception
{
// Create home
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1");
// Simple command line - no reference to extra-start-dirs
@ -136,17 +110,17 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
makeFile(common,"start.ini","jetty.port=8080");
TestEnv.makeFile(common,"start.ini","jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1");
// Simple command line reference to extra-start-dir
@ -170,17 +144,17 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
makeFile(common,"start.ini","jetty.port=8080");
TestEnv.makeFile(common,"start.ini","jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1");
// Simple command line reference to extra-start-dir via property (also on command line)
@ -206,7 +180,7 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create opt
File opt = testdir.getFile("opt");
@ -215,12 +189,12 @@ public class ExtraStartTest
// Create common
File common = new File(opt, "common");
FS.ensureEmpty(common);
makeFile(common,"start.ini","jetty.port=8080");
TestEnv.makeFile(common,"start.ini","jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1");
String dirRef = "${my.opt}" + File.separator + "common";
@ -248,7 +222,7 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create opt
File opt = testdir.getFile("opt");
@ -257,17 +231,17 @@ public class ExtraStartTest
// Create common
File common = new File(opt, "common");
FS.ensureEmpty(common);
makeFile(common,"start.ini","jetty.port=8080");
TestEnv.makeFile(common,"start.ini","jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1");
String dirRef = "${my.opt}" + File.separator + "${my.dir}";
// Simple command line reference to extra-start-dir via property (also on command line)
// Simple command line reference to extra-start-dir via property (also on command line)
MainResult result = runMain(base,home,
// property to 'opt' dir
"my.opt=" + opt.getAbsolutePath(),
@ -292,7 +266,7 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create common
File common = testdir.getFile("common");
@ -301,7 +275,7 @@ public class ExtraStartTest
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());
@ -323,7 +297,7 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create common
File common = testdir.getFile("common");
@ -336,7 +310,7 @@ public class ExtraStartTest
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath(), //
"--extra-start-dir=" + corp.getAbsolutePath());
@ -360,25 +334,25 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
makeFile(corp,"start.ini", //
TestEnv.makeFile(corp,"start.ini", //
"jetty.port=9090");
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
makeFile(common,"start.ini", //
TestEnv.makeFile(common,"start.ini", //
"--extra-start-dir=" + corp.getAbsolutePath(), //
"jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());
@ -401,18 +375,18 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
makeFile(corp,"start.ini", //
TestEnv.makeFile(corp,"start.ini", //
"jetty.port=9090");
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
makeFile(common,"start.ini", //
TestEnv.makeFile(common,"start.ini", //
"my.corp=" + corp.getAbsolutePath(), //
"--extra-start-dir=${my.corp}", //
"jetty.port=8080");
@ -420,7 +394,7 @@ public class ExtraStartTest
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"my.common="+common.getAbsolutePath(), //
"--extra-start-dir=${my.common}");
@ -444,32 +418,32 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create devops
File devops = testdir.getFile("devops");
FS.ensureEmpty(devops);
makeFile(devops,"start.ini", //
TestEnv.makeFile(devops,"start.ini", //
"--module=logging", //
"jetty.port=2222");
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
makeFile(corp,"start.ini", //
TestEnv.makeFile(corp,"start.ini", //
"jetty.port=9090");
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
makeFile(common,"start.ini", //
TestEnv.makeFile(common,"start.ini", //
"--extra-start-dir=" + corp.getAbsolutePath(), //
"jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());
@ -495,25 +469,25 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
makeFile(corp,"start.ini", //
TestEnv.makeFile(corp,"start.ini", //
"jetty.port=9090");
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
makeFile(common,"start.ini", //
TestEnv.makeFile(common,"start.ini", //
"--extra-start-dir=" + corp.getAbsolutePath(), //
"jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());
@ -538,7 +512,7 @@ public class ExtraStartTest
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
copyTestDir("usecases/home",home);
TestEnv.copyTestDir("usecases/home",home);
// Create common
File common = testdir.getFile("common");
@ -547,14 +521,14 @@ public class ExtraStartTest
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
makeFile(corp,"start.ini",
TestEnv.makeFile(corp,"start.ini",
// standard property
"jetty.port=9090",
// INTENTIONAL BAD Reference (duplicate)
"--extra-start-dir=" + common.getAbsolutePath());
// Populate common
makeFile(common,"start.ini",
TestEnv.makeFile(common,"start.ini",
// standard property
"jetty.port=8080",
// reference to corp
@ -563,7 +537,7 @@ public class ExtraStartTest
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
makeFile(base,"start.ini", //
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());

View File

@ -0,0 +1,52 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.OS;
public class TestEnv
{
public static void copyTestDir(String testResourceDir, File destDir) throws IOException
{
FS.ensureDirExists(destDir);
File srcDir = MavenTestingUtils.getTestResourceDir(testResourceDir);
IO.copyDir(srcDir,destDir);
}
public static void makeFile(File dir, String relFilePath, String... contents) throws IOException
{
File outputFile = new File(dir,OS.separators(relFilePath));
FS.ensureDirExists(outputFile.getParentFile());
try (FileWriter writer = new FileWriter(outputFile); PrintWriter out = new PrintWriter(writer))
{
for (String content : contents)
{
out.println(content);
}
}
}
}

View File

@ -0,0 +1,599 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.config;
import static org.hamcrest.Matchers.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jetty.start.ConfigurationAssert;
import org.eclipse.jetty.start.Props.Prop;
import org.eclipse.jetty.start.TestEnv;
import org.eclipse.jetty.start.UsageException;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
public class ConfigSourcesTest
{
@Rule
public TestingDir testdir = new TestingDir();
private void assertIdOrder(ConfigSources sources, String... expectedOrder)
{
List<String> actualList = new ArrayList<>();
for (ConfigSource source : sources)
{
actualList.add(source.getId());
}
List<String> expectedList = Arrays.asList(expectedOrder);
ConfigurationAssert.assertOrdered("ConfigSources.id order",expectedList,actualList);
}
private void assertDirOrder(ConfigSources sources, File... expectedDirOrder)
{
List<String> actualList = new ArrayList<>();
for (ConfigSource source : sources)
{
if (source instanceof DirConfigSource)
{
actualList.add(((DirConfigSource)source).getDir().toString());
}
}
List<String> expectedList = new ArrayList<>();
for (File path : expectedDirOrder)
{
expectedList.add(path.getAbsolutePath());
}
ConfigurationAssert.assertOrdered("ConfigSources.dir order",expectedList,actualList);
}
private void assertProperty(ConfigSources sources, String key, String expectedValue)
{
Prop prop = sources.getProp(key);
Assert.assertThat("getProp('" + key + "') should not be null",prop,notNullValue());
Assert.assertThat("getProp('" + key + "')",prop.value,is(expectedValue));
}
@Test
public void testOrder_BasicConfig() throws IOException
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1");
ConfigSources sources = new ConfigSources();
String[] cmdLine = new String[0];
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyBaseConfigSource(base.toPath()));
sources.add(new JettyHomeConfigSource(home.toPath()));
assertIdOrder(sources,"<command-line>","${jetty.base}","${jetty.home}");
}
@Test
public void testOrder_With1ExtraConfig() throws IOException
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());
ConfigSources sources = new ConfigSources();
String[] cmdLine = new String[0];
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
assertIdOrder(sources,"<command-line>","${jetty.base}",common.getAbsolutePath(),"${jetty.home}");
}
@Test
public void testCommandLine_1Extra_FromSimpleProp() throws Exception
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
TestEnv.makeFile(common,"start.ini","jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1");
ConfigSources sources = new ConfigSources();
// Simple command line reference to extra-start-dir via property (also on command line)
String[] cmdLine = new String[] {
// property
"my.common=" + common.getAbsolutePath(),
// reference via property
"--extra-start-dir=${my.common}" };
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
assertIdOrder(sources,"<command-line>","${jetty.base}","${my.common}","${jetty.home}");
assertDirOrder(sources,base,common,home);
assertProperty(sources,"jetty.host","127.0.0.1");
assertProperty(sources,"jetty.port","8080"); // from 'common'
}
@Test
public void testCommandLine_1Extra_FromPropPrefix() throws Exception
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create opt
File opt = testdir.getFile("opt");
FS.ensureEmpty(opt);
// Create common
File common = new File(opt,"common");
FS.ensureEmpty(common);
TestEnv.makeFile(common,"start.ini","jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1");
String dirRef = "${my.opt}" + File.separator + "common";
ConfigSources sources = new ConfigSources();
// Simple command line reference to extra-start-dir via property (also on command line)
String[] cmdLine = new String[] {
// property to 'opt' dir
"my.opt=" + opt.getAbsolutePath(),
// reference via property prefix
"--extra-start-dir=" + dirRef };
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
assertIdOrder(sources,"<command-line>","${jetty.base}",dirRef,"${jetty.home}");
assertDirOrder(sources,base,common,home);
assertProperty(sources,"jetty.host","127.0.0.1");
assertProperty(sources,"jetty.port","8080"); // from 'common'
}
@Test
public void testCommandLine_1Extra_FromCompoundProp() throws Exception
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create opt
File opt = testdir.getFile("opt");
FS.ensureEmpty(opt);
// Create common
File common = new File(opt,"common");
FS.ensureEmpty(common);
TestEnv.makeFile(common,"start.ini","jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1");
String dirRef = "${my.opt}" + File.separator + "${my.dir}";
ConfigSources sources = new ConfigSources();
// Simple command line reference to extra-start-dir via property (also on command line)
String[] cmdLine = new String[] {
// property to 'opt' dir
"my.opt=" + opt.getAbsolutePath(),
// property to commmon dir name
"my.dir=common",
// reference via property prefix
"--extra-start-dir=" + dirRef };
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
assertIdOrder(sources,"<command-line>","${jetty.base}",dirRef,"${jetty.home}");
assertDirOrder(sources,base,common,home);
assertProperty(sources,"jetty.host","127.0.0.1");
assertProperty(sources,"jetty.port","8080"); // from 'common'
}
@Test
public void testRefCommon() throws Exception
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
TestEnv.makeFile(common,"start.ini","jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());
ConfigSources sources = new ConfigSources();
String cmdLine[] = new String[0];
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
assertIdOrder(sources,"<command-line>","${jetty.base}",common.getAbsolutePath(),"${jetty.home}");
assertDirOrder(sources,base,common,home);
assertProperty(sources,"jetty.host","127.0.0.1");
assertProperty(sources,"jetty.port","8080"); // from 'common'
}
@Test
public void testRefCommonAndCorp() throws Exception
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
TestEnv.makeFile(common,"start.ini","jetty.port=8080");
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath(), //
"--extra-start-dir=" + corp.getAbsolutePath());
ConfigSources sources = new ConfigSources();
String cmdLine[] = new String[0];
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
assertIdOrder(sources,"<command-line>","${jetty.base}",
common.getAbsolutePath(),
corp.getAbsolutePath(),
"${jetty.home}");
assertDirOrder(sources,base,common,corp,home);
assertProperty(sources,"jetty.host","127.0.0.1");
assertProperty(sources,"jetty.port","8080"); // from 'common'
}
@Test
public void testRefCommonRefCorp() throws Exception
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
TestEnv.makeFile(corp,"start.ini", //
"jetty.port=9090");
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
TestEnv.makeFile(common,"start.ini", //
"--extra-start-dir=" + corp.getAbsolutePath(), //
"jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());
ConfigSources sources = new ConfigSources();
String cmdLine[] = new String[0];
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
assertIdOrder(sources,"<command-line>","${jetty.base}",
common.getAbsolutePath(),
corp.getAbsolutePath(),
"${jetty.home}");
assertDirOrder(sources,base,common,corp,home);
assertProperty(sources,"jetty.host","127.0.0.1");
assertProperty(sources,"jetty.port","8080"); // from 'common'
}
@Test
public void testRefCommonRefCorp_FromSimpleProps() throws Exception
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
TestEnv.makeFile(corp,"start.ini", //
"jetty.port=9090");
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
TestEnv.makeFile(common,"start.ini", //
"my.corp=" + corp.getAbsolutePath(), //
"--extra-start-dir=${my.corp}", //
"jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"my.common="+common.getAbsolutePath(), //
"--extra-start-dir=${my.common}");
ConfigSources sources = new ConfigSources();
String cmdLine[] = new String[0];
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
assertIdOrder(sources,"<command-line>",
"${jetty.base}",
"${my.common}",
"${my.corp}",
"${jetty.home}");
assertDirOrder(sources,base,common,corp,home);
assertProperty(sources,"jetty.host","127.0.0.1");
assertProperty(sources,"jetty.port","8080"); // from 'common'
}
@Test
public void testRefCommonRefCorp_CmdLineRef() throws Exception
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create devops
File devops = testdir.getFile("devops");
FS.ensureEmpty(devops);
TestEnv.makeFile(devops,"start.ini", //
"--module=logging", //
"jetty.port=2222");
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
TestEnv.makeFile(corp,"start.ini", //
"jetty.port=9090");
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
TestEnv.makeFile(common,"start.ini", //
"--extra-start-dir=" + corp.getAbsolutePath(), //
"jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());
ConfigSources sources = new ConfigSources();
String cmdLine[] = new String[]{
// command line provided extra-start-dir ref
"--extra-start-dir=" + devops.getAbsolutePath()};
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
assertIdOrder(sources,"<command-line>",
"${jetty.base}",
devops.getAbsolutePath(),
common.getAbsolutePath(),
corp.getAbsolutePath(),
"${jetty.home}");
assertDirOrder(sources,base,devops,common,corp,home);
assertProperty(sources,"jetty.host","127.0.0.1");
assertProperty(sources,"jetty.port","2222"); // from 'common'
}
@Test
public void testRefCommonRefCorp_CmdLineProp() throws Exception
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
TestEnv.makeFile(corp,"start.ini", //
"jetty.port=9090");
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
TestEnv.makeFile(common,"start.ini", //
"--extra-start-dir=" + corp.getAbsolutePath(), //
"jetty.port=8080");
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());
ConfigSources sources = new ConfigSources();
String cmdLine[] = new String[]{
// command line property should override all others
"jetty.port=7070"
};
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
assertIdOrder(sources,"<command-line>","${jetty.base}",
common.getAbsolutePath(),
corp.getAbsolutePath(),
"${jetty.home}");
assertDirOrder(sources,base,common,corp,home);
assertProperty(sources,"jetty.host","127.0.0.1");
assertProperty(sources,"jetty.port","7070"); // from <command-line>
}
@Test
public void testBadDoubleRef() throws Exception
{
// Create home
File home = testdir.getFile("home");
FS.ensureEmpty(home);
TestEnv.copyTestDir("usecases/home",home);
// Create common
File common = testdir.getFile("common");
FS.ensureEmpty(common);
// Create corp
File corp = testdir.getFile("corp");
FS.ensureEmpty(corp);
TestEnv.makeFile(corp,"start.ini",
// standard property
"jetty.port=9090",
// INTENTIONAL BAD Reference (duplicate)
"--extra-start-dir=" + common.getAbsolutePath());
// Populate common
TestEnv.makeFile(common,"start.ini",
// standard property
"jetty.port=8080",
// reference to corp
"--extra-start-dir=" + corp.getAbsolutePath());
// Create base
File base = testdir.getFile("base");
FS.ensureEmpty(base);
TestEnv.makeFile(base,"start.ini", //
"jetty.host=127.0.0.1",//
"--extra-start-dir=" + common.getAbsolutePath());
ConfigSources sources = new ConfigSources();
try
{
String cmdLine[] = new String[0];
sources.add(new CommandLineConfigSource(cmdLine));
sources.add(new JettyHomeConfigSource(home.toPath()));
sources.add(new JettyBaseConfigSource(base.toPath()));
Assert.fail("Should have thrown a UsageException");
}
catch (UsageException e)
{
Assert.assertThat("UsageException",e.getMessage(),containsString("Duplicate"));
}
}
}