diff --git a/jetty-server/src/main/config/modules/ext.mod b/jetty-server/src/main/config/modules/ext.mod
index 329a833d442..1207bddc391 100644
--- a/jetty-server/src/main/config/modules/ext.mod
+++ b/jetty-server/src/main/config/modules/ext.mod
@@ -3,7 +3,7 @@
#
[lib]
-lib/ext/*.jar
+regex:lib/ext/.*\.jar$
[files]
lib/
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/BaseHome.java b/jetty-start/src/main/java/org/eclipse/jetty/start/BaseHome.java
index 2986c195579..d00b1e06949 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/BaseHome.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/BaseHome.java
@@ -32,6 +32,8 @@ import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.eclipse.jetty.start.FS.RelativeRegexFilter;
+
/**
* File access for ${jetty.home}
, ${jetty.base}
, directories.
*
@@ -286,9 +288,85 @@ public class BaseHome
return homeFiles;
}
}
+
+ /**
+ * Get all of the files that are in a specific relative directory, with applied regex.
+ *
+ * If the same found path exists in both ${jetty.base}
and ${jetty.home}
, then the one in ${jetty.base}
is returned
+ * (it overrides the one in ${jetty.home})
+ *
+ * All regex paths are assumed to be in unix notation (use of "/"
to separate paths, as "\"
is used to escape in regex)
+ *
+ * @param regex
+ * the regex to use to match against the found files.
+ * @return the list of files found.
+ */
+ public List listFilesRegex(String regex)
+ {
+ Objects.requireNonNull(regex,"Glob cannot be null");
+
+ Pattern pattern = Pattern.compile(regex);
+
+ List homeFiles = new ArrayList<>();
+ if (FS.canReadDirectory(homeDir))
+ {
+ StartLog.debug("Finding files in ${jetty.home} that match: %s",regex);
+ recurseDir(homeFiles,homeDir,new FS.RelativeRegexFilter(homeDir,pattern));
+ StartLog.debug("Found %,d files",homeFiles.size());
+ }
+
+ if (isBaseDifferent())
+ {
+ // merge
+ List ret = new ArrayList<>();
+ if (FS.canReadDirectory(baseDir))
+ {
+ List baseFiles = new ArrayList<>();
+ StartLog.debug("Finding files in ${jetty.base} that match: %s",regex);
+ recurseDir(baseFiles,baseDir,new FS.RelativeRegexFilter(baseDir,pattern));
+ StartLog.debug("Found %,d files",baseFiles.size());
+
+ for (File base : baseFiles)
+ {
+ String relpath = toRelativePath(baseDir,base);
+ File home = new File(homeDir,FS.separators(relpath));
+ if (home.exists())
+ {
+ homeFiles.remove(home);
+ }
+ ret.add(base);
+ }
+ }
+
+ // add any remaining home files.
+ ret.addAll(homeFiles);
+ StartLog.debug("Merged Files: %,d files%n",ret.size());
+
+ Collections.sort(ret,new NaturalSort.Files());
+ return ret;
+ }
+ else
+ {
+ // simple return
+ Collections.sort(homeFiles,new NaturalSort.Files());
+ return homeFiles;
+ }
+ }
+
+ private void recurseDir(List files, File dir, RelativeRegexFilter filter)
+ {
+ // find matches first
+ files.addAll(Arrays.asList(dir.listFiles(filter)));
+
+ // now dive down into sub-directories
+ for (File subdir : dir.listFiles(FS.DirFilter.INSTANCE))
+ {
+ recurseDir(files,subdir,filter);
+ }
+ }
/**
- * Collect the list of files in both ${jetty.base}
and ${jetty.home}
, with , even if the same file shows up in both places.
+ * Collect the list of files in both ${jetty.base}
and ${jetty.home}
, even if the same file shows up in both places.
*/
public List rawListFiles(String relPathToDirectory, FileFilter filter)
{
@@ -338,9 +416,10 @@ public class BaseHome
}
}
+ // TODO - inline
private String toRelativePath(File dir, File path)
{
- return dir.toURI().relativize(path.toURI()).toASCIIString();
+ return FS.toRelativePath(dir,path);
}
/**
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Classpath.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Classpath.java
index 3333b52d613..fb18fa080e4 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Classpath.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Classpath.java
@@ -75,6 +75,7 @@ public class Classpath implements Iterable
public boolean addComponent(File path)
{
+ StartLog.debug("Adding classpath component: %s",path);
if ((path == null) || (!path.exists()))
{
// not a valid component
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java b/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java
index 977985ccdb4..e1119d4ce65 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java
@@ -37,6 +37,39 @@ public class FS
return true;
}
}
+
+ public static class DirFilter implements FileFilter
+ {
+ public static final DirFilter INSTANCE = new DirFilter();
+
+ @Override
+ public boolean accept(File path)
+ {
+ return path.isDirectory();
+ }
+ }
+
+ public static class RelativeRegexFilter implements FileFilter
+ {
+ private final File baseDir;
+ private final Pattern pattern;
+
+ public RelativeRegexFilter(File baseDir, Pattern pattern)
+ {
+ this.baseDir = baseDir;
+ this.pattern = pattern;
+ }
+
+ @Override
+ public boolean accept(File path)
+ {
+ // get relative path
+ String relativePath = FS.toRelativePath(baseDir,path);
+
+ // see if it matches
+ return (pattern.matcher(relativePath).matches());
+ }
+ }
public static class FilenameRegexFilter implements FileFilter
{
@@ -149,6 +182,11 @@ public class FS
{
return filename.toLowerCase(Locale.ENGLISH).endsWith(".xml");
}
+
+ public static String toRelativePath(File baseDir, File path)
+ {
+ return baseDir.toURI().relativize(path.toURI()).toASCIIString();
+ }
public static String separators(String path)
{
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java
index bc1359772ab..487d9ffbad3 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java
@@ -306,7 +306,7 @@ public class Module
}
else
{
- // blank lines and comments are valid for initialize section
+ // blank lines and comments are valid for ini-template section
if ((line.length() == 0) || line.startsWith("#"))
{
if ("INI-TEMPLATE".equals(sectionType))
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java b/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
index 97875637e6d..0b140e1d9f9 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
@@ -323,8 +323,20 @@ public class StartArgs
for (String rawlibref : module.getLibs())
{
String libref = properties.expand(rawlibref);
+
+ if (libref.startsWith("regex:"))
+ {
+ String regex = libref.substring("regex:".length());
+ for (File libfile : baseHome.listFilesRegex(regex))
+ {
+ classpath.addComponent(libfile);
+ }
+ continue;
+ }
+
libref = FS.separators(libref);
+ // Any globs here?
if (libref.contains("*"))
{
// Glob Reference
@@ -895,7 +907,7 @@ public class StartArgs
{
parse(line,StartArgs.CMD_LINE_SOURCE);
}
-
+
return this;
}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/ConfigurationAssert.java b/jetty-start/src/test/java/org/eclipse/jetty/start/ConfigurationAssert.java
index 0f739369f8c..382611b7467 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/ConfigurationAssert.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/ConfigurationAssert.java
@@ -96,7 +96,7 @@ public class ConfigurationAssert
}
}
List actualProperties = new ArrayList<>();
- for(Prop prop: args.getProperties())
+ for (Prop prop : args.getProperties())
{
String name = prop.key;
if ("jetty.home".equals(name) || "jetty.base".equals(name) || prop.origin.equals(Props.ORIGIN_SYSPROP))
@@ -120,10 +120,31 @@ public class ConfigurationAssert
List actualDownloads = new ArrayList<>();
for (FileArg darg : args.getFiles())
{
- actualDownloads.add(String.format("%s:%s",darg.uri,darg.location));
+ if (darg.uri != null)
+ {
+ actualDownloads.add(String.format("%s:%s",darg.uri,darg.location));
+ }
}
assertContainsUnordered("Downloads",expectedDownloads,actualDownloads);
-
+
+ // Validate Files/Dirs creation
+ List expectedFiles = new ArrayList<>();
+ for(String line: textFile)
+ {
+ if(line.startsWith("FILE|"))
+ {
+ expectedFiles.add(getValue(line));
+ }
+ }
+ List actualFiles = new ArrayList<>();
+ for(FileArg farg: args.getFiles())
+ {
+ if(farg.uri == null)
+ {
+ actualFiles.add(farg.location);
+ }
+ }
+ assertContainsUnordered("Files/Dirs",expectedFiles,actualFiles);
}
private static String shorten(BaseHome baseHome, File path, File testResourcesDir)
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java
index ddf005e587e..1e3348ade19 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java
@@ -44,7 +44,7 @@ public class ModulesTest
Modules modules = new Modules();
modules.registerAll(basehome, DEFAULT_ARGS);
- Assert.assertThat("Module count",modules.count(),is(29));
+ Assert.assertThat("Module count",modules.count(),is(30));
}
@Test
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/TestUseCases.java b/jetty-start/src/test/java/org/eclipse/jetty/start/TestUseCases.java
index 5173afd72c8..4790eff1f6f 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/TestUseCases.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/TestUseCases.java
@@ -73,6 +73,12 @@ public class TestUseCases
assertUseCase("home","base.with.db","assert-with-db.txt");
}
+ @Test
+ public void testWithDeepExt() throws Exception
+ {
+ assertUseCase("home","base.with.ext","assert-with.ext.txt");
+ }
+
@Test
public void testWithPropsBasic() throws Exception
{
diff --git a/jetty-start/src/test/resources/usecases/assert-with.ext.txt b/jetty-start/src/test/resources/usecases/assert-with.ext.txt
new file mode 100644
index 00000000000..7759a419943
--- /dev/null
+++ b/jetty-start/src/test/resources/usecases/assert-with.ext.txt
@@ -0,0 +1,26 @@
+# The XMLs we expect (order is important)
+XML|${jetty.home}/etc/jetty.xml
+XML|${jetty.home}/etc/jetty-http.xml
+
+# The LIBs we expect (order is irrelevant)
+LIB|${jetty.home}/lib/jetty-continuation-TEST.jar
+LIB|${jetty.home}/lib/jetty-http-TEST.jar
+LIB|${jetty.home}/lib/jetty-io-TEST.jar
+LIB|${jetty.home}/lib/jetty-schemas-3.1.jar
+LIB|${jetty.home}/lib/jetty-server-TEST.jar
+LIB|${jetty.home}/lib/jetty-util-TEST.jar
+LIB|${jetty.home}/lib/jetty-xml-TEST.jar
+LIB|${jetty.home}/lib/servlet-api-3.1.jar
+LIB|${jetty.base}/lib/ext/agent.jar
+LIB|${jetty.base}/lib/ext/jdbc/mariadb-jdbc.jar
+LIB|${jetty.base}/lib/ext/logging/slf4j-api.jar
+LIB|${jetty.base}/lib/ext/logging/jul-to-slf4j.jar
+LIB|${jetty.base}/lib/ext/logging/logback-core.jar
+LIB|${jetty.base}/lib/ext/logging/logback-classic.jar
+
+# The Properties we expect (order is irrelevant)
+PROP|jetty.port=9090
+
+# Files / Directories to create
+FILE|lib/
+FILE|lib/ext/
diff --git a/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/agent.jar b/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/agent.jar
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/jdbc/mariadb-jdbc.jar b/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/jdbc/mariadb-jdbc.jar
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/logging/jul-to-slf4j.jar b/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/logging/jul-to-slf4j.jar
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/logging/logback-classic.jar b/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/logging/logback-classic.jar
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/logging/logback-core.jar b/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/logging/logback-core.jar
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/logging/slf4j-api.jar b/jetty-start/src/test/resources/usecases/base.with.ext/lib/ext/logging/slf4j-api.jar
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/jetty-start/src/test/resources/usecases/base.with.ext/lib/jetty-util-alt.jar b/jetty-start/src/test/resources/usecases/base.with.ext/lib/jetty-util-alt.jar
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/jetty-start/src/test/resources/usecases/base.with.ext/start.ini b/jetty-start/src/test/resources/usecases/base.with.ext/start.ini
new file mode 100644
index 00000000000..c8fa93065c4
--- /dev/null
+++ b/jetty-start/src/test/resources/usecases/base.with.ext/start.ini
@@ -0,0 +1,6 @@
+
+--module=server
+--module=http
+--module=ext
+
+jetty.port=9090
diff --git a/jetty-start/src/test/resources/usecases/home/modules/ext.mod b/jetty-start/src/test/resources/usecases/home/modules/ext.mod
new file mode 100644
index 00000000000..c84697a5631
--- /dev/null
+++ b/jetty-start/src/test/resources/usecases/home/modules/ext.mod
@@ -0,0 +1,10 @@
+#
+# ext module
+#
+
+[lib]
+regex:lib/ext/.*\.jar$
+
+[files]
+lib/
+lib/ext/
diff --git a/jetty-start/src/test/resources/usecases/home/modules/server.mod b/jetty-start/src/test/resources/usecases/home/modules/server.mod
index d0c2de35d74..b1e9f336738 100644
--- a/jetty-start/src/test/resources/usecases/home/modules/server.mod
+++ b/jetty-start/src/test/resources/usecases/home/modules/server.mod
@@ -2,6 +2,9 @@
# Base server
#
+[optional]
+ext
+
[depend]
base
xml