From 84df81c28894443bb650a78d1bd32293a1490482 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 19 Aug 2013 12:30:53 +1000 Subject: [PATCH 01/16] 414635 Modular start.d and jetty.base property Fixed NPE from XmlConfiguration reordered so command line comes after start.ini and start.d --- .../java/org/eclipse/jetty/start/Config.java | 19 +++++++++++++------ .../java/org/eclipse/jetty/start/Main.java | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java index 7365199b7e7..ee490370f64 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java @@ -166,7 +166,7 @@ public class Config { ver = "Unknown"; } - _version = ver; + __version = ver; } /** @@ -184,8 +184,9 @@ public class Config } }; - private static final String _version; + private static final String __version; private static boolean DEBUG = false; + private static Config __instance; private final Map _properties = new HashMap(); private final Map _classpaths = new HashMap(); private final List _xml = new ArrayList(); @@ -193,6 +194,11 @@ public class Config private int argCount = 0; + public Config() + { + __instance=this; + } + private final Set _options = new TreeSet(new Comparator() { // Make sure "*" is always at the end of the list @@ -431,7 +437,8 @@ public class Config _properties.clear(); } - public Properties getProperties() + /* This method is static so it can be accessed by XmlConfiguration */ + public static Properties getProperties() { Properties properties = new Properties(); // Add System Properties First @@ -441,8 +448,8 @@ public class Config properties.put(name, System.getProperty(name)); } // Add Config Properties Next (overwriting any System Properties that exist) - for (String key : _properties.keySet()) { - properties.put(key,_properties.get(key)); + for (String key : __instance._properties.keySet()) { + properties.put(key,__instance._properties.get(key)); } return properties; } @@ -450,7 +457,7 @@ public class Config public String getProperty(String name) { if ("version".equalsIgnoreCase(name)) { - return _version; + return __version; } // Search Config Properties First if (_properties.containsKey(name)) { diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index 7390ac88608..f62b44cbfb1 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -127,7 +127,7 @@ public class Main if (arg.startsWith("--ini=") || arg.equals("--ini")) ini = true; if (!ini) - arguments.add("--ini=start.ini"); + arguments.add(0,"--ini=start.ini"); // The XML Configuration Files to initialize with List xmls = new ArrayList(); From bead95314a6538f62c40808dcb5b641e35db5dd9 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 19 Aug 2013 13:22:02 +1000 Subject: [PATCH 02/16] 414635 Modular start.d and jetty.base property Added more info in README.TXT files --- .../src/main/resources/start.d/README.TXT | 26 +++++++++++++++++++ .../main/resources/webapps.demo/README.TXT | 7 ++++- .../src/main/resources/webapps/README.TXT | 8 ++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 jetty-distribution/src/main/resources/start.d/README.TXT diff --git a/jetty-distribution/src/main/resources/start.d/README.TXT b/jetty-distribution/src/main/resources/start.d/README.TXT new file mode 100644 index 00000000000..28e2492913e --- /dev/null +++ b/jetty-distribution/src/main/resources/start.d/README.TXT @@ -0,0 +1,26 @@ + +This start.d directory contains modular ini files that are appended to the effective command line +used to start jetty by the command: + + java -jar start.jar + + +The modules are executed in alphabetic order and the 'NNN-' prefixes are a convention to make that ordering +explicit regardless of module name. + +All modules ending with '.ini' will be executed and it is a convention that disabled modules are renamed to +end with '.ini.disabled'. The start.jar mechanism can be used to enable/disable modules with commands like: + + java -jar start.jar --enable=ssl --enable=spdy + +Note that the numeric prefix can be skipped in such commands. + + +The ini modules have a simple dependency mechanism so a module can declare if it depends on or conflicts with +other modules. For example the spdy module includes the entries: + + EXCLUDE=https + DEPEND=npn,ssl + +This says that spdy cannot be used with the https module (both use the same port and spdy provides https) and +that the npn and ssl modules must also be enabled. diff --git a/jetty-distribution/src/main/resources/webapps.demo/README.TXT b/jetty-distribution/src/main/resources/webapps.demo/README.TXT index ec2bea255cb..d6fb93b8996 100644 --- a/jetty-distribution/src/main/resources/webapps.demo/README.TXT +++ b/jetty-distribution/src/main/resources/webapps.demo/README.TXT @@ -3,5 +3,10 @@ This directory is scanned by the demo WebAppDeployer provider created in the etc/jetty-demo.xml file and enabled by the start.d/900-demo.ini file. -For normal deployment, use the webapps directory. +To disable the demo, either remove the start.d/900-demo.ini or issue the following command: + + java -jar start.jar --disable=demo + + +For normal webapp deployment, use the webapps directory. diff --git a/jetty-distribution/src/main/resources/webapps/README.TXT b/jetty-distribution/src/main/resources/webapps/README.TXT index dc2b38915e3..170137a0ec4 100644 --- a/jetty-distribution/src/main/resources/webapps/README.TXT +++ b/jetty-distribution/src/main/resources/webapps/README.TXT @@ -23,3 +23,11 @@ only the XML is deployed (which may use the war in its configuration). This directory is scanned for additions, removals and updates for hot deployment. +To configure the deployment mechanism, edit the files: + start.d/500-deploy.ini + etc/jetty-deploy.ini + +To disable the auto deploy mechanism use the command: + + java -jar start.jar --disable=deploy + From ecf30e41cbfcacb9778ac163b35c2c4f92e754fb Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sat, 17 Aug 2013 11:59:16 -0700 Subject: [PATCH 03/16] Fixing Jar close resource leak --- .../src/main/java/org/eclipse/jetty/start/JarVersion.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/JarVersion.java b/jetty-start/src/main/java/org/eclipse/jetty/start/JarVersion.java index 858a2c09e04..efd11ea7d2d 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/JarVersion.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/JarVersion.java @@ -127,10 +127,8 @@ public class JarVersion public static String getVersion(File file) { - try + try(JarFile jar = new JarFile(file)) { - JarFile jar = new JarFile(file); - String version = null; Manifest manifest = jar.getManifest(); From 72f8143d5e57f98c8548f838d20ab72166e689dd Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sat, 17 Aug 2013 11:59:56 -0700 Subject: [PATCH 04/16] Removing CORBA reference?? and adding improved debug method --- .../src/main/java/org/eclipse/jetty/start/Config.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java index ee490370f64..d971aca7fe3 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java @@ -45,8 +45,6 @@ import java.util.Set; import java.util.StringTokenizer; import java.util.TreeSet; -import org.omg.CORBA._PolicyStub; - /** *

* It allows an application to be started with the command "java -jar start.jar". @@ -334,6 +332,14 @@ public class Config System.err.println(msg); } } + + public static void debug(String format, Object ... args) + { + if (DEBUG) + { + System.err.printf(format+"%n",args); + } + } public static void debug(Throwable t) { From 998f95bfc01392c70d797bfa243446a9ed9ad7b3 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sat, 17 Aug 2013 12:00:25 -0700 Subject: [PATCH 05/16] More javadoc, minor cleanup --- .../java/org/eclipse/jetty/start/Main.java | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index f62b44cbfb1..47062ff526b 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -221,7 +221,7 @@ public class Main continue; } - + // Alternative start.config file if (arg.startsWith("--config=")) { _startConfig = arg.substring(9); @@ -230,6 +230,9 @@ public class Main // Special internal indicator that jetty was started by the jetty.sh Daemon + // All this does is setup a start.log that captures startup console output + // in the tiny window of time before the real logger kicks in. + // Useful for capturing when things go horribly wrong if ("--daemon".equals(arg)) { File startDir = new File(System.getProperty("jetty.logs","logs")); @@ -260,6 +263,7 @@ public class Main continue; } + // Start Property (syntax similar to System Property) if (arg.startsWith("-D")) { String[] assign = arg.substring(2).split("=",2); @@ -278,6 +282,7 @@ public class Main continue; } + // Anything else is a JVM argument if (arg.startsWith("-")) { _jvmArgs.add(arg); @@ -379,8 +384,7 @@ public class Main location.replaceAll("/",File.separator); File file = new File(location); - if (Config.isDebug()) - System.err.println("Download to "+file.getAbsolutePath()+(file.exists()?" Exists!":"")); + Config.debug("Download to %s %s",file.getAbsolutePath(),(file.exists()?"[Exists!]":"")); if (file.exists()) return; @@ -536,18 +540,34 @@ public class Main System.exit(EXIT_USAGE); } - String path(String path) + /** + * Replace/Shorten arbitrary path with property strings "${jetty.home}" or "${jetty.base}" where appropriate. + * + * @param path + * the path to shorten + * @return the potentially shortened path + */ + private String path(String path) { - if (path==null) + if (path == null) + { return path; + } if (path.startsWith(_config.getJettyHome())) - path = "${jetty.home}" + path.substring(_config.getJettyHome().length()); - if (_config.getJettyBase()!=null && path.startsWith(_config.getJettyBase())) - path = "${jetty.base}" + path.substring(_config.getJettyBase().length()); + { + return "${jetty.home}" + path.substring(_config.getJettyHome().length()); + } + if (_config.getJettyBase() != null && path.startsWith(_config.getJettyBase())) + { + return "${jetty.base}" + path.substring(_config.getJettyBase().length()); + } return path; } - String path(File file) + /** + * Convenience method for path(file.getCanonicalPath()) + */ + private String path(File file) { try { @@ -679,7 +699,7 @@ public class Main System.out.println(cmd.toString()); } - + // Informational command line, don't run jetty if (_noRun) return; @@ -1214,7 +1234,7 @@ public class Main /** * Convert a start.ini format file into an argument list. */ - List loadStartIni(File ini,String name) + private List loadStartIni(File ini,String name) { if (ini==null || !ini.exists() || ini.isDirectory() || !ini.canRead()) { From 46a94956ee97df383b3b186cb54867c428a19044 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sat, 17 Aug 2013 14:26:12 -0700 Subject: [PATCH 06/16] Adding HomeBase to simplify file access logic between jetty.home and jetty.base --- .../org/eclipse/jetty/start/HomeBase.java | 212 ++++++++++++++++++ .../org/eclipse/jetty/start/HomeBaseTest.java | 115 ++++++++++ .../test/resources/hb.1/base/start.d/jmx.ini | 0 .../resources/hb.1/base/start.d/logging.ini | 1 + .../resources/hb.1/base/start.d/myapp.ini | 0 .../src/test/resources/hb.1/base/start.ini | 7 + .../test/resources/hb.1/home/start.d/jmx.ini | 0 .../test/resources/hb.1/home/start.d/jndi.ini | 0 .../test/resources/hb.1/home/start.d/jsp.ini | 0 .../resources/hb.1/home/start.d/logging.ini | 1 + .../test/resources/hb.1/home/start.d/ssl.ini | 0 .../src/test/resources/hb.1/home/start.ini | 11 + 12 files changed, 347 insertions(+) create mode 100644 jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java create mode 100644 jetty-start/src/test/java/org/eclipse/jetty/start/HomeBaseTest.java create mode 100644 jetty-start/src/test/resources/hb.1/base/start.d/jmx.ini create mode 100644 jetty-start/src/test/resources/hb.1/base/start.d/logging.ini create mode 100644 jetty-start/src/test/resources/hb.1/base/start.d/myapp.ini create mode 100644 jetty-start/src/test/resources/hb.1/base/start.ini create mode 100644 jetty-start/src/test/resources/hb.1/home/start.d/jmx.ini create mode 100644 jetty-start/src/test/resources/hb.1/home/start.d/jndi.ini create mode 100644 jetty-start/src/test/resources/hb.1/home/start.d/jsp.ini create mode 100644 jetty-start/src/test/resources/hb.1/home/start.d/logging.ini create mode 100644 jetty-start/src/test/resources/hb.1/home/start.d/ssl.ini create mode 100644 jetty-start/src/test/resources/hb.1/home/start.ini diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java new file mode 100644 index 00000000000..7322bb6673a --- /dev/null +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java @@ -0,0 +1,212 @@ +// +// ======================================================================== +// 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.FileFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * File access for ${jetty.home}, and optional ${jetty.base}, directories + */ +public class HomeBase +{ + private static class AllFilter implements FileFilter + { + public static final AllFilter INSTANCE = new AllFilter(); + + @Override + public boolean accept(File pathname) + { + return true; + } + } + + private final File homeDir; + private final File baseDir; + + public HomeBase(File homeDir, File baseDir) + { + this.homeDir = homeDir; + this.baseDir = baseDir; + } + + /** + * Replace/Shorten arbitrary path with property strings "${jetty.home}" or "${jetty.base}" where appropriate. + * + * @param path + * the path to shorten + * @return the potentially shortened path + */ + public String toShortForm(String path) + { + if (path == null) + { + return path; + } + + String value = homeDir.getAbsolutePath(); + + if (path.startsWith(value)) + { + return "${jetty.home}" + path.substring(value.length()); + } + + if (baseDir != null) + { + value = baseDir.getAbsolutePath(); + if (path.startsWith(value)) + { + return "${jetty.base}" + path.substring(value.length()); + } + } + return path; + } + + /** + * Convenience method for toShortForm(file.getCanonicalPath()) + */ + public String toShortForm(File path) + { + try + { + return toShortForm(path.getCanonicalPath()); + } + catch (IOException ignore) + { + /* ignore */ + } + return toShortForm(path.getAbsolutePath()); + } + + /** + * Get a specific file reference. + *

+ * If file exists in ${jetty.base}, return its reference, otherwise return the ${jetty.home} references. + * + * @param relPath + * the path to get. + * @return the file references. + */ + public File getFile(String relPath) + { + String rpath = separators(relPath); + + if (baseDir != null) + { + File file = new File(baseDir,rpath); + if (file.exists()) + { + return file; + } + } + return new File(homeDir,rpath); + } + + public static String separators(String path) + { + StringBuilder ret = new StringBuilder(); + for (char c : path.toCharArray()) + { + if ((c == '/') || (c == '\\')) + { + ret.append(File.separatorChar); + } + else + { + ret.append(c); + } + } + return ret.toString(); + } + + /** + * Get all of the files that are in a specific relative directory. + *

+ * 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}) + * + * @param relPathToDirectory + * the relative path to the directory + * @return the list of files found. + */ + public List listFiles(String relPathToDirectory) + { + return listFiles(relPathToDirectory,AllFilter.INSTANCE); + } + + /** + * Get all of the files that are in a specific relative directory, with applied {@link FileFilter} + *

+ * 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}) + * + * @param relPathToDirectory + * the relative path to the directory + * @param filter + * the filter to use + * @return the list of files found. + */ + public List listFiles(String relPathToDirectory, FileFilter filter) + { + Objects.requireNonNull(filter,"FileFilter cannot be null"); + + File homePath = new File(homeDir,separators(relPathToDirectory)); + List homeFiles = new ArrayList<>(); + homeFiles.addAll(Arrays.asList(homePath.listFiles(filter))); + + if (baseDir != null) + { + // merge + File basePath = new File(baseDir,separators(relPathToDirectory)); + File baseFiles[] = basePath.listFiles(filter); + List ret = new ArrayList<>(); + + for (File base : baseFiles) + { + String relpath = toRelativePath(baseDir,base); + File home = new File(homeDir,separators(relpath)); + if (home.exists()) + { + homeFiles.remove(home); + } + ret.add(base); + } + + // add any remaining home files. + ret.addAll(homeFiles); + + return ret; + } + else + { + // simple return + return homeFiles; + } + } + + private String toRelativePath(File dir, File path) + { + return dir.toURI().relativize(path.toURI()).toASCIIString(); + } +} diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/HomeBaseTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/HomeBaseTest.java new file mode 100644 index 00000000000..5df9f12ea5f --- /dev/null +++ b/jetty-start/src/test/java/org/eclipse/jetty/start/HomeBaseTest.java @@ -0,0 +1,115 @@ +// +// ======================================================================== +// 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.hamcrest.Matchers.*; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jetty.toolchain.test.IO; +import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.junit.Assert; +import org.junit.Test; + +public class HomeBaseTest +{ + private void assertFileList(HomeBase hb, String message, List expected, List files) + { + List actual = new ArrayList<>(); + for (File file : files) + { + actual.add(hb.toShortForm(file)); + } + Assert.assertThat(message,actual,containsInAnyOrder(expected.toArray())); + } + + @Test + public void testGetFile_OnlyHome() throws IOException + { + File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home"); + File baseDir = null; + + HomeBase hb = new HomeBase(homeDir,baseDir); + File startIni = hb.getFile("/start.ini"); + + String ref = hb.toShortForm(startIni); + Assert.assertThat("Reference",ref,startsWith("${jetty.home}")); + + String contents = IO.readToString(startIni); + Assert.assertThat("Contents",contents,containsString("Home Ini")); + } + + @Test + public void testListFiles_OnlyHome() throws IOException + { + File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home"); + File baseDir = null; + + HomeBase hb = new HomeBase(homeDir,baseDir); + List files = hb.listFiles("/start.d"); + + List expected = new ArrayList<>(); + expected.add("${jetty.home}/start.d/jmx.ini"); + expected.add("${jetty.home}/start.d/jndi.ini"); + expected.add("${jetty.home}/start.d/jsp.ini"); + expected.add("${jetty.home}/start.d/logging.ini"); + expected.add("${jetty.home}/start.d/ssl.ini"); + + assertFileList(hb,"Files found",expected,files); + } + + @Test + public void testListFiles_Both() throws IOException + { + File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home"); + File baseDir = MavenTestingUtils.getTestResourceDir("hb.1/base"); + + HomeBase hb = new HomeBase(homeDir,baseDir); + List files = hb.listFiles("/start.d"); + + List expected = new ArrayList<>(); + expected.add("${jetty.base}/start.d/jmx.ini"); + expected.add("${jetty.home}/start.d/jndi.ini"); + expected.add("${jetty.home}/start.d/jsp.ini"); + expected.add("${jetty.base}/start.d/logging.ini"); + expected.add("${jetty.home}/start.d/ssl.ini"); + expected.add("${jetty.base}/start.d/myapp.ini"); + + assertFileList(hb,"Files found",expected,files); + } + + @Test + public void testGetFile_Both() throws IOException + { + File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home"); + File baseDir = MavenTestingUtils.getTestResourceDir("hb.1/base"); + + HomeBase hb = new HomeBase(homeDir,baseDir); + File startIni = hb.getFile("/start.ini"); + + String ref = hb.toShortForm(startIni); + Assert.assertThat("Reference",ref,startsWith("${jetty.base}")); + + String contents = IO.readToString(startIni); + Assert.assertThat("Contents",contents,containsString("Base Ini")); + } +} diff --git a/jetty-start/src/test/resources/hb.1/base/start.d/jmx.ini b/jetty-start/src/test/resources/hb.1/base/start.d/jmx.ini new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-start/src/test/resources/hb.1/base/start.d/logging.ini b/jetty-start/src/test/resources/hb.1/base/start.d/logging.ini new file mode 100644 index 00000000000..d648d1b1fd8 --- /dev/null +++ b/jetty-start/src/test/resources/hb.1/base/start.d/logging.ini @@ -0,0 +1 @@ +# Base Logging \ No newline at end of file diff --git a/jetty-start/src/test/resources/hb.1/base/start.d/myapp.ini b/jetty-start/src/test/resources/hb.1/base/start.d/myapp.ini new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-start/src/test/resources/hb.1/base/start.ini b/jetty-start/src/test/resources/hb.1/base/start.ini new file mode 100644 index 00000000000..c0ebe8c9a9f --- /dev/null +++ b/jetty-start/src/test/resources/hb.1/base/start.ini @@ -0,0 +1,7 @@ +#=========================================================== +# Base Ini +#=========================================================== + +OPTIONS=jmx +etc/jetty-jmx.xml + diff --git a/jetty-start/src/test/resources/hb.1/home/start.d/jmx.ini b/jetty-start/src/test/resources/hb.1/home/start.d/jmx.ini new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-start/src/test/resources/hb.1/home/start.d/jndi.ini b/jetty-start/src/test/resources/hb.1/home/start.d/jndi.ini new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-start/src/test/resources/hb.1/home/start.d/jsp.ini b/jetty-start/src/test/resources/hb.1/home/start.d/jsp.ini new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-start/src/test/resources/hb.1/home/start.d/logging.ini b/jetty-start/src/test/resources/hb.1/home/start.d/logging.ini new file mode 100644 index 00000000000..7161329d503 --- /dev/null +++ b/jetty-start/src/test/resources/hb.1/home/start.d/logging.ini @@ -0,0 +1 @@ +# Home Logging \ No newline at end of file diff --git a/jetty-start/src/test/resources/hb.1/home/start.d/ssl.ini b/jetty-start/src/test/resources/hb.1/home/start.d/ssl.ini new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-start/src/test/resources/hb.1/home/start.ini b/jetty-start/src/test/resources/hb.1/home/start.ini new file mode 100644 index 00000000000..69a418ea91a --- /dev/null +++ b/jetty-start/src/test/resources/hb.1/home/start.ini @@ -0,0 +1,11 @@ +#=========================================================== +# Home Ini +#=========================================================== + +OPTIONS=Server,jsp,resources,websocket,ext +etc/jetty.xml +start.d/ +etc/jetty-deploy.xml +etc/jetty-webapps.xml +etc/jetty-contexts.xml + From fe4b922127e62f444a9027cae4b5dec8733aadb8 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sat, 17 Aug 2013 14:27:18 -0700 Subject: [PATCH 07/16] Making warning show on System.err --- jetty-start/src/main/java/org/eclipse/jetty/start/Main.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index 47062ff526b..89886fe7654 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -362,8 +362,8 @@ public class Main // Anything else is considered an XML file. if (xmls.contains(arg)) { - System.out.println("WARN: Argument '" + arg + "' specified multiple times. Check start.ini?"); - System.out.println("Use \"java -jar start.jar --help\" for more information."); + System.err.println("WARN: Argument '" + arg + "' specified multiple times. Check start.ini?"); + System.err.println("Use \"java -jar start.jar --help\" for more information."); } xmls.add(arg); } From 34435931369fdc9df16151b416ceeef15d6cfbe1 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sat, 17 Aug 2013 14:30:13 -0700 Subject: [PATCH 08/16] Reducing code duplication --- .../src/main/java/org/eclipse/jetty/start/Main.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index 89886fe7654..f67ab4dbedc 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -1216,7 +1216,10 @@ public class Main static void usageExit(Throwable t, int exit) { - t.printStackTrace(System.err); + if (t != null) + { + t.printStackTrace(System.err); + } System.err.println(); System.err.println("Usage: java -jar start.jar [options] [properties] [configs]"); System.err.println(" java -jar start.jar --help # for more information"); @@ -1225,10 +1228,7 @@ public class Main static void usageExit(int exit) { - System.err.println(); - System.err.println("Usage: java -jar start.jar [options] [properties] [configs]"); - System.err.println(" java -jar start.jar --help # for more information"); - System.exit(exit); + usageExit(null, exit); } /** From 2b4099007f71d1e2e455f7123f480722d50cb5a0 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sat, 17 Aug 2013 16:22:20 -0700 Subject: [PATCH 09/16] Making Config use HomeBase q + Cleaning up Start INI handling with new StartIni class + Eliminating recursive sub-ini directory issue + Adding NaturalSort utility class + Adding FS utility class Conflicts: jetty-start/src/main/java/org/eclipse/jetty/start/Config.java jetty-start/src/main/java/org/eclipse/jetty/start/Main.java --- .../java/org/eclipse/jetty/start/Config.java | 92 +--- .../main/java/org/eclipse/jetty/start/FS.java | 89 ++++ .../org/eclipse/jetty/start/HomeBase.java | 230 ++++++---- .../java/org/eclipse/jetty/start/Main.java | 430 ++++++------------ .../org/eclipse/jetty/start/NaturalSort.java | 56 +++ .../org/eclipse/jetty/start/StartIni.java | 149 ++++++ .../org/eclipse/jetty/start/HomeBaseTest.java | 21 +- .../org/eclipse/jetty/start/MainTest.java | 25 +- .../jetty/start/PropertyPassingTest.java | 2 + .../src/test/resources/empty.home/start.ini | 3 + 10 files changed, 650 insertions(+), 447 deletions(-) create mode 100644 jetty-start/src/main/java/org/eclipse/jetty/start/FS.java create mode 100644 jetty-start/src/main/java/org/eclipse/jetty/start/NaturalSort.java create mode 100644 jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java create mode 100644 jetty-start/src/test/resources/empty.home/start.ini diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java index d971aca7fe3..751212651ae 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java @@ -170,21 +170,13 @@ public class Config /** * Natural language sorting for key names. */ - private final Comparator keySorter = new Comparator() - { - private final Collator collator = Collator.getInstance(); - - public int compare(String o1, String o2) - { - CollationKey key1 = collator.getCollationKey(o1); - CollationKey key2 = collator.getCollationKey(o2); - return key1.compareTo(key2); - } - }; + private final Comparator keySorter = new NaturalSort.Strings(); private static final String __version; private static boolean DEBUG = false; private static Config __instance; + + private final HomeBase _homebase; private final Map _properties = new HashMap(); private final Map _classpaths = new HashMap(); private final List _xml = new ArrayList(); @@ -192,11 +184,6 @@ public class Config private int argCount = 0; - public Config() - { - __instance=this; - } - private final Set _options = new TreeSet(new Comparator() { // Make sure "*" is always at the end of the list @@ -213,6 +200,21 @@ public class Config return o1.compareTo(o2); } }); + + public Config() + { + __instance=this; + _homebase = new HomeBase(); + setProperty("jetty.home",_homebase.getHome()); + if(_homebase.hasBase()) { + setProperty("jetty.base",_homebase.getBase()); + } + } + + public HomeBase getHomeBase() + { + return _homebase; + } public Classpath defineOption(String option) { @@ -292,32 +294,12 @@ public class Config private void close(InputStream stream) { - if (stream == null) - return; - - try - { - stream.close(); - } - catch (IOException ignore) - { - /* ignore */ - } + FS.close(stream); } private void close(Reader reader) { - if (reader == null) - return; - - try - { - reader.close(); - } - catch (IOException ignore) - { - /* ignore */ - } + FS.close(reader); } public static boolean isDebug() @@ -1031,38 +1013,4 @@ public class Config return buf.toString(); } - - public String getJettyHome() - { - return getProperty("jetty.home"); - } - - public String getJettyBase() - { - return getProperty("jetty.base"); - } - - public File getFileBaseHomeAbs(String filename) - { - File file; - - String base = getJettyBase(); - if (base!=null) - { - file=new File(base,filename); - if (file.exists()) - return file; - } - - file=new File(getJettyHome(),filename); - if (file.exists()) - return file; - - file=new File(filename); - if (file.exists()) - return file; - - return null; - - } } 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 new file mode 100644 index 00000000000..9476f8425ed --- /dev/null +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java @@ -0,0 +1,89 @@ +// +// ======================================================================== +// 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.Closeable; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.util.regex.Pattern; + +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 pattern.matcher(path.getName()).matches(); + } + } + + public static class IniFilter extends FilenameRegexFilter + { + public IniFilter() + { + super("^.*\\.ini$"); + } + } + + public static class XmlFilter extends FilenameRegexFilter + { + public XmlFilter() + { + super("^.*\\.xml$"); + } + } + + public static boolean isXml(String filename) + { + return Pattern.compile(".xml$",Pattern.CASE_INSENSITIVE).matcher(filename).matches(); + } + + public static boolean isFile(File file) + { + if (file == null) + { + return false; + } + return file.exists() && file.isFile(); + } + + public static void close(Closeable c) + { + if (c == null) + return; + + try + { + c.close(); + } + catch (IOException ignore) + { + /* ignore */ + } + } +} diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java index 7322bb6673a..a7097c612ad 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java @@ -23,6 +23,7 @@ import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -42,87 +43,6 @@ public class HomeBase } } - private final File homeDir; - private final File baseDir; - - public HomeBase(File homeDir, File baseDir) - { - this.homeDir = homeDir; - this.baseDir = baseDir; - } - - /** - * Replace/Shorten arbitrary path with property strings "${jetty.home}" or "${jetty.base}" where appropriate. - * - * @param path - * the path to shorten - * @return the potentially shortened path - */ - public String toShortForm(String path) - { - if (path == null) - { - return path; - } - - String value = homeDir.getAbsolutePath(); - - if (path.startsWith(value)) - { - return "${jetty.home}" + path.substring(value.length()); - } - - if (baseDir != null) - { - value = baseDir.getAbsolutePath(); - if (path.startsWith(value)) - { - return "${jetty.base}" + path.substring(value.length()); - } - } - return path; - } - - /** - * Convenience method for toShortForm(file.getCanonicalPath()) - */ - public String toShortForm(File path) - { - try - { - return toShortForm(path.getCanonicalPath()); - } - catch (IOException ignore) - { - /* ignore */ - } - return toShortForm(path.getAbsolutePath()); - } - - /** - * Get a specific file reference. - *

- * If file exists in ${jetty.base}, return its reference, otherwise return the ${jetty.home} references. - * - * @param relPath - * the path to get. - * @return the file references. - */ - public File getFile(String relPath) - { - String rpath = separators(relPath); - - if (baseDir != null) - { - File file = new File(baseDir,rpath); - if (file.exists()) - { - return file; - } - } - return new File(homeDir,rpath); - } - public static String separators(String path) { StringBuilder ret = new StringBuilder(); @@ -140,6 +60,104 @@ public class HomeBase return ret.toString(); } + private File homeDir; + private File baseDir; + + public HomeBase() + { + String userDir = System.getProperty("user.dir"); + this.homeDir = new File(System.getProperty("jetty.home",userDir)); + String base = System.getProperty("jetty.base"); + if (base != null) + { + this.baseDir = new File(base); + } + } + + public HomeBase(File homeDir, File baseDir) + { + this.homeDir = homeDir; + this.baseDir = baseDir; + } + + public boolean hasBase() + { + return this.baseDir != null; + } + + public void setBaseDir(File dir) + { + this.baseDir = dir; + } + + public File getBaseDir() + { + return baseDir; + } + + public String getBase() + { + if (baseDir == null) + { + return null; + } + return baseDir.getAbsolutePath(); + } + + /** + * Get a specific file reference. + *

+ * File references go through 3 possibly scenarios. + *

    + *
  1. If exists relative to ${jetty.base}, return that reference
  2. + *
  3. If exists relative to ${jetty.home}, return that reference
  4. + *
  5. Otherwise return absolute path reference
  6. + *
+ * + * @param path + * the path to get. + * @return the file reference. + */ + public File getFile(String path) + { + String rpath = separators(path); + + // Relative to Base Directory First + if (baseDir != null) + { + File file = new File(baseDir,rpath); + if (file.exists()) + { + return file; + } + } + + // Then relative to Home Directory + File file = new File(homeDir,rpath); + if (file.exists()) + { + return file; + } + + // Finally, as an absolute path + return new File(rpath); + } + + public void setHomeDir(File dir) + { + this.homeDir = dir; + } + + public File getHomeDir() + { + return homeDir; + } + + public String getHome() + { + return homeDir.getAbsolutePath(); + } + /** * Get all of the files that are in a specific relative directory. *

@@ -196,11 +214,13 @@ public class HomeBase // add any remaining home files. ret.addAll(homeFiles); + Collections.sort(ret, new NaturalSort.Files()); return ret; } else { // simple return + Collections.sort(homeFiles, new NaturalSort.Files()); return homeFiles; } } @@ -209,4 +229,52 @@ public class HomeBase { return dir.toURI().relativize(path.toURI()).toASCIIString(); } + + /** + * Convenience method for toShortForm(file.getCanonicalPath()) + */ + public String toShortForm(File path) + { + try + { + return toShortForm(path.getCanonicalPath()); + } + catch (IOException ignore) + { + /* ignore */ + } + return toShortForm(path.getAbsolutePath()); + } + + /** + * Replace/Shorten arbitrary path with property strings "${jetty.home}" or "${jetty.base}" where appropriate. + * + * @param path + * the path to shorten + * @return the potentially shortened path + */ + public String toShortForm(String path) + { + if (path == null) + { + return path; + } + + String value = homeDir.getAbsolutePath(); + + if (path.startsWith(value)) + { + return "${jetty.home}" + path.substring(value.length()); + } + + if (baseDir != null) + { + value = baseDir.getAbsolutePath(); + if (path.startsWith(value)) + { + return "${jetty.base}" + path.substring(value.length()); + } + } + return path; + } } diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index f67ab4dbedc..853c60ae7d7 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -26,7 +26,6 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; -import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -51,17 +50,17 @@ import java.util.Locale; import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Pattern; /*-------------------------------------------*/ /** *

- * 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". + * 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". *

* *

- * 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. + * 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. *

*/ public class Main @@ -78,10 +77,10 @@ public class Main private boolean _dumpVersions = false; private boolean _listConfig = false; private boolean _listOptions = false; - private boolean _noRun=false; + private boolean _noRun = false; private boolean _dryRun = false; private boolean _exec = false; - private final Config _config = new Config(); + private final Config _config; private final Set _sysProps = new HashSet<>(); private final List _jvmArgs = new ArrayList<>(); private final List _enable = new ArrayList<>(); @@ -107,40 +106,39 @@ public class Main Main() throws IOException { - String jetty_home=new File(System.getProperty("jetty.home",".")).getCanonicalPath(); - _config.setProperty("jetty.home",jetty_home); + _config = new Config(); } Config getConfig() { return _config; } - + public List processCommandLine(String[] args) throws Exception { - String source=""; - + String source = ""; + // Handle default ini args ArrayList arguments = new ArrayList<>(Arrays.asList(args)); - boolean ini=false; - for(String arg : arguments) + boolean ini = false; + for (String arg : arguments) if (arg.startsWith("--ini=") || arg.equals("--ini")) ini = true; if (!ini) arguments.add(0,"--ini=start.ini"); - + // The XML Configuration Files to initialize with List xmls = new ArrayList(); // Process the arguments in for loop so list of args can be extended. - for (int i=0;i8?arg.substring(9):arguments.get(++i); - _noRun=true; + String module = arg.length() > 8?arg.substring(9):arguments.get(++i); + _noRun = true; _enable.add(module); } if (arg.startsWith("--disable=") || arg.equals("--disable")) { - String module=arg.length()>9?arg.substring(10):arguments.get(++i); - _noRun=true; + String module = arg.length() > 9?arg.substring(10):arguments.get(++i); + _noRun = true; _disable.add(module); } - + if (arg.startsWith("--ini=") || arg.equals("--ini")) { ini = true; if (arg.length() > 6) { - String name=arg.substring(6); - File file=_config.getFileBaseHomeAbs(name); - arguments.addAll(i+1,loadStartIni(file,name)); + String name = arg.substring(6); + File file = _config.getHomeBase().getFile(name); + StartIni startini = new StartIni(file); + int idx; + while ((idx = startini.lineIndexOf(0,Pattern.compile("^.*/$"))) >= 0) + { + String subPath = startini.getLines().get(idx); + startini.getLines().remove(idx); + // find the sub ini files (based on HomeBase) + List childInis = _config.getHomeBase().listFiles(subPath,new FS.IniFilter()); + for (File childIni : childInis) + { + StartIni cini = new StartIni(childIni); + idx += startini.overlayAt(idx,cini); + } + } + arguments.addAll(i + 1,startini.getLines()); } - + continue; } - + // Alternative start.config file if (arg.startsWith("--config=")) { _startConfig = arg.substring(9); continue; } - - + // Special internal indicator that jetty was started by the jetty.sh Daemon // All this does is setup a start.log that captures startup console output // in the tiny window of time before the real logger kicks in. @@ -299,7 +309,7 @@ public class Main case 2: if ("_SRC_".equals(assign[0])) { - source=assign[1].trim(); + source = assign[1].trim(); } else if ("DEFINE".equals(assign[0])) { @@ -307,29 +317,29 @@ public class Main for (String opt : opts) _config.defineOption(opt.trim()); } - else if ("DEPEND".equals(assign[0])) + else if ("DEPEND".equals(assign[0])) { String opts[] = assign[1].split(","); for (String opt : opts) { - opt=opt.trim(); - if (!_config.getOptions().contains(opt)) + opt = opt.trim(); + if (!_config.getOptions().contains(opt)) { - System.err.printf("ERROR: Missing Dependency: %s DEPEND %s%n",path(source),opt ); - _noRun=true; + System.err.printf("ERROR: Missing Dependency: %s DEPEND %s%n",path(source),opt); + _noRun = true; } } } - else if ("EXCLUDE".equals(assign[0])) + else if ("EXCLUDE".equals(assign[0])) { String opts[] = assign[1].split(","); for (String opt : opts) { - opt=opt.trim(); - if (_config.getOptions().contains(opt)) + opt = opt.trim(); + if (_config.getOptions().contains(opt)) { - System.err.printf("ERROR: Excluded Dependency: %s EXCLUDE %s%n",path(source),opt ); - _noRun=true; + System.err.printf("ERROR: Excluded Dependency: %s EXCLUDE %s%n",path(source),opt); + _noRun = true; } } } @@ -348,7 +358,7 @@ public class Main this._config.setProperty(assign[0],assign[1]); } break; - + case 1: this._config.setProperty(assign[0],null); break; @@ -376,42 +386,42 @@ public class Main try { String[] split = arg.split(":",3); - if (split.length!=3 || "http".equalsIgnoreCase(split[0]) || !split[1].startsWith("//")) + if (split.length != 3 || "http".equalsIgnoreCase(split[0]) || !split[1].startsWith("//")) throw new IllegalArgumentException("Not --download=:"); - - String location=split[2]; - if (File.separatorChar!='/') + + String location = split[2]; + if (File.separatorChar != '/') location.replaceAll("/",File.separator); File file = new File(location); - + Config.debug("Download to %s %s",file.getAbsolutePath(),(file.exists()?"[Exists!]":"")); if (file.exists()) return; - - URL url = new URL(split[0].substring(11)+":"+split[1]); - System.err.println("DOWNLOAD: "+url+" to "+location); + URL url = new URL(split[0].substring(11) + ":" + split[1]); + + System.err.println("DOWNLOAD: " + url + " to " + location); if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); - byte[] buf=new byte[8192]; + byte[] buf = new byte[8192]; try (InputStream in = url.openStream(); OutputStream out = new FileOutputStream(file);) { - while(true) + while (true) { int len = in.read(buf); - if (len>0) + if (len > 0) out.write(buf,0,len); - if (len<0) + if (len < 0) break; } } } - catch(Exception e) + catch (Exception e) { - System.err.println("ERROR: processing "+arg+"\n"+e); + System.err.println("ERROR: processing " + arg + "\n" + e); e.printStackTrace(); usageExit(EXIT_USAGE); } @@ -457,7 +467,7 @@ public class Main } else if (info.equals("@CONFIGS")) { - FileFilter filter =new FileFilter() + FileFilter filter = new FileFilter() { public boolean accept(File path) { @@ -470,45 +480,25 @@ public class Main return (name.startsWith("jetty") && name.endsWith(".xml")); } }; - - // list home etc - File etc = new File(_config.getJettyHome(),"etc"); - if (!etc.exists() || !etc.isDirectory()) - { - System.out.print(indent); - System.out.println("Unable to find/list " + etc); - continue; - } - List configFiles = new ArrayList(); - File[] configs = etc.listFiles(filter); - configFiles.addAll(Arrays.asList(configs)); - - // list base etc - if (!_config.getJettyHome().equals(_config.getJettyBase())) - { - etc = new File(_config.getJettyBase(),"etc"); - if (etc.exists() && etc.isDirectory()) - { - configs = etc.listFiles(filter); - configFiles.addAll(Arrays.asList(configs)); - } - } - - Collections.sort(configFiles); + + // list etc + List configFiles = _config.getHomeBase().listFiles("etc",filter); for (File configFile : configFiles) + { System.out.printf("%s%s%n",indent,path(configFile)); + } } else if (info.equals("@STARTINI")) { for (File file : _iniFiles) { - String path=path(file); + String path = path(file); System.out.printf("%s%s%n",indent,path); if (Config.isDebug()) { - try (FileReader reader=new FileReader(file); BufferedReader in = new BufferedReader(reader);) + try (FileReader reader = new FileReader(file); BufferedReader in = new BufferedReader(reader);) { String arg; while ((arg = in.readLine()) != null) @@ -540,45 +530,16 @@ public class Main System.exit(EXIT_USAGE); } - /** - * Replace/Shorten arbitrary path with property strings "${jetty.home}" or "${jetty.base}" where appropriate. - * - * @param path - * the path to shorten - * @return the potentially shortened path - */ private String path(String path) { - if (path == null) - { - return path; - } - if (path.startsWith(_config.getJettyHome())) - { - return "${jetty.home}" + path.substring(_config.getJettyHome().length()); - } - if (_config.getJettyBase() != null && path.startsWith(_config.getJettyBase())) - { - return "${jetty.base}" + path.substring(_config.getJettyBase().length()); - } - return path; + return _config.getHomeBase().toShortForm(path); } - - /** - * Convenience method for path(file.getCanonicalPath()) - */ - private String path(File file) + + private String path(File file) { - try - { - return path(file.getCanonicalPath()); - } - catch (IOException e) - { - } - return path(file.getAbsolutePath()); + return _config.getHomeBase().toShortForm(file); } - + public void invokeMain(ClassLoader classloader, String classname, List args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { @@ -622,24 +583,11 @@ public class Main main.invoke(null,method_params); } - /* ------------------------------------------------------------ */ public static void close(Closeable c) { - if (c == null) - { - return; - } - try - { - c.close(); - } - catch (IOException e) - { - e.printStackTrace(System.err); - } + FS.close(c); } - /* ------------------------------------------------------------ */ public void start(List xmls) throws IOException, InterruptedException { // Load potential Config (start.config) @@ -676,7 +624,7 @@ public class Main enable(m); for (String m : _disable) disable(m); - + // Show the usage information and return if (_showUsage) usage(); @@ -698,7 +646,7 @@ public class Main CommandLineBuilder cmd = buildCommandLine(classpath,configuredXmls); System.out.println(cmd.toString()); } - + // Informational command line, don't run jetty if (_noRun) return; @@ -793,26 +741,25 @@ public class Main private String resolveXmlConfig(String xmlFilename) throws FileNotFoundException { - if (!xmlFilename.toLowerCase(Locale.ENGLISH).endsWith(".xml")) + if (!FS.isXml(xmlFilename)) { // Nothing to resolve. return xmlFilename; } - // Look for the file as absolute, jetty-base or jetty-home - File xml = _config.getFileBaseHomeAbs(xmlFilename); - if (xml!=null && xml.isFile()) + // Try normal locations + File xml = _config.getHomeBase().getFile(xmlFilename); + if (FS.isFile(xml)) + { return xml.getAbsolutePath(); - - // Try corrected / for \ - xml = _config.getFileBaseHomeAbs(fixPath(xmlFilename)); - if (xml!=null && xml.isFile()) - return xml.getAbsolutePath(); - - // Try in etc - xml = _config.getFileBaseHomeAbs("etc/"+xmlFilename); - if (xml!=null && xml.isFile()) + } + + // Try again, but prefixed with "etc/" + xml = _config.getHomeBase().getFile("etc/" + xmlFilename); + if (FS.isFile(xml)) + { return xml.getAbsolutePath(); + } throw new FileNotFoundException("Unable to find XML Config: " + xmlFilename); } @@ -825,9 +772,11 @@ public class Main { cmd.addArg(x); } - cmd.addRawArg("-Djetty.home=" + _config.getJettyHome()); - if (_config.getJettyBase()!=null) - cmd.addRawArg("-Djetty.base=" + _config.getJettyBase()); + cmd.addRawArg("-Djetty.home=" + _config.getHomeBase().getHome()); + if (_config.getHomeBase().hasBase()) + { + cmd.addRawArg("-Djetty.base=" + _config.getHomeBase().getBase()); + } // Special Stop/Shutdown properties ensureSystemPropertySet("STOP.PORT"); @@ -857,14 +806,13 @@ public class Main for (String xml : xmls) { - cmd.addRawArg(xml); + cmd.addRawArg(xml); } return cmd; } /** - * Ensure that the System Properties are set (if defined as a System property, or start.config property, or - * start.ini property) + * Ensure that the System Properties are set (if defined as a System property, or start.config property, or start.ini property) * * @param key * the key to be sure of @@ -950,8 +898,13 @@ public class Main System.out.println("Note: If using multiple options (eg: 'Server,servlet,webapp,jms,jmx') " + "then overlapping entries will not be repeated in the eventual classpath."); System.out.println(); - System.out.printf("${jetty.home} = %s%n",_config.getJettyHome()); - System.out.printf("${jetty.base} = %s%n",_config.getJettyBase()); + System.out.printf("${jetty.home} = %s%n",_config.getHomeBase().getHome()); + String base = ""; + if (_config.getHomeBase().hasBase()) + { + base = _config.getHomeBase().getBase(); + } + System.out.printf("${jetty.base} = %s%n",base); System.out.println(); for (String sectionId : sectionIds) @@ -1014,11 +967,6 @@ public class Main System.out.printf("%2d: %20s | %s\n",i++,getVersion(element),path(element)); } - private String fixPath(String path) - { - return path.replace('/',File.separatorChar); - } - private String getVersion(File element) { if (element.isDirectory()) @@ -1079,8 +1027,8 @@ public class Main /** * Load Configuration. * - * No specific configuration is real until a {@link Config#getCombinedClasspath(java.util.Collection)} is used to - * execute the {@link Class} specified by {@link Config#getMainClassname()} is executed. + * No specific configuration is real until a {@link Config#getCombinedClasspath(java.util.Collection)} is used to execute the {@link Class} specified by + * {@link Config#getMainClassname()} is executed. * * @param xmls * the command line specified xml configuration options. @@ -1228,114 +1176,32 @@ public class Main static void usageExit(int exit) { - usageExit(null, exit); - } - - /** - * Convert a start.ini format file into an argument list. - */ - private List loadStartIni(File ini,String name) - { - if (ini==null || !ini.exists() || ini.isDirectory() || !ini.canRead()) - { - System.err.println("Warning - bad ini file: " + name); - // No start.ini found, skip load. - return Collections.emptyList(); - } - - ini=ini.getAbsoluteFile(); - if (!_iniFiles.contains(ini)) - _iniFiles.add(ini); - List args = new ArrayList(); - - args.add("_SRC_="+name); - - FileReader reader = null; - BufferedReader buf = null; - try - { - reader = new FileReader(ini); - buf = new BufferedReader(reader); - - String arg; - while ((arg = buf.readLine()) != null) - { - arg = arg.trim(); - if (arg.length() == 0 || arg.startsWith("#")) - { - continue; - } - - if (arg.endsWith("/")) - { - try - { - File start_d = _config.getFileBaseHomeAbs(arg); - if (start_d!=null && start_d.isDirectory()) - { - _iniDirs.add(start_d); - File[] inis = start_d.listFiles(new FilenameFilter() - { - @Override - public boolean accept(File dir, String name) - { - return name.toLowerCase(Locale.ENGLISH).endsWith(".ini"); - } - }); - Arrays.sort(inis); - - for (File i : inis) - args.addAll(loadStartIni(i,i.getAbsolutePath())); - - args.add("_SRC_="+name); - continue; - } - } - catch(Exception e) - { - e.printStackTrace(); - } - } - - args.add(arg); - } - } - catch (IOException e) - { - usageExit(e,ERR_UNKNOWN); - } - finally - { - Main.close(buf); - Main.close(reader); - } - - return args; + usageExit(null,exit); } void addJvmArgs(List jvmArgs) { _jvmArgs.addAll(jvmArgs); } - + private void enable(final String module) { - final String mini=module+".ini"; - final String disable=module+".ini.disabled"; - final AtomicBoolean found=new AtomicBoolean(false); - FileFilter filter =new FileFilter() + final String mini = module + ".ini"; + final String disable = module + ".ini.disabled"; + final AtomicBoolean found = new AtomicBoolean(false); + FileFilter filter = new FileFilter() { public boolean accept(File path) { if (!path.isFile()) return false; - String n=path.getName(); - int i=n.indexOf(mini); - if (i<0) + String n = path.getName(); + int i = n.indexOf(mini); + if (i < 0) return false; - if (i>0 && i!=4 && n.charAt(i-1)!='-') + if (i > 0 && i != 4 && n.charAt(i - 1) != '-') return false; - + found.set(true); if (n.endsWith(mini)) { @@ -1343,41 +1209,41 @@ public class Main } else if (n.endsWith(disable)) { - String enabled=n.substring(0,n.length()-9); + String enabled = n.substring(0,n.length() - 9); System.err.printf("Enable %s in %s as %s%n",module,path(path.getParent()),enabled); path.renameTo(new File(path.getParentFile(),enabled)); } - else + else System.err.printf("Bad module %s in %s as %s%n",module,path(path.getParent()),n); - + return false; } }; - + for (File dir : _iniDirs) dir.listFiles(filter); - + if (!found.get()) for (File dir : _iniDirs) System.err.printf("Module %s not found in %s%n",module,path(dir)); } - + private void disable(final String module) { - final String mini=module+".ini"; - final String disable=module+".ini.disabled"; - final AtomicBoolean found=new AtomicBoolean(false); - FileFilter filter =new FileFilter() + final String mini = module + ".ini"; + final String disable = module + ".ini.disabled"; + final AtomicBoolean found = new AtomicBoolean(false); + FileFilter filter = new FileFilter() { public boolean accept(File path) { if (!path.isFile()) return false; - String n=path.getName(); - int i=n.indexOf(mini); - if (i<0) + String n = path.getName(); + int i = n.indexOf(mini); + if (i < 0) return false; - if (i>0 && i!=4 && n.charAt(i-1)!='-') + if (i > 0 && i != 4 && n.charAt(i - 1) != '-') return false; found.set(true); @@ -1387,20 +1253,20 @@ public class Main } else if (n.endsWith(mini)) { - String disabled=n+".disabled"; + String disabled = n + ".disabled"; System.err.printf("Disable %s in %s as %s%n",module,path(path.getParent()),disabled); path.renameTo(new File(path.getParentFile(),disabled)); } - else + else System.err.printf("Bad module %s in %s as %s%n",module,path(path.getParent()),n); - + return false; } }; - + for (File dir : _iniDirs) dir.listFiles(filter); - + if (!found.get()) for (File dir : _iniDirs) System.err.printf("Module %s not found in %s%n",module,path(dir)); diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/NaturalSort.java b/jetty-start/src/main/java/org/eclipse/jetty/start/NaturalSort.java new file mode 100644 index 00000000000..dc72712af2a --- /dev/null +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/NaturalSort.java @@ -0,0 +1,56 @@ +// +// ======================================================================== +// 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.text.CollationKey; +import java.text.Collator; +import java.util.Comparator; + +/** + * Natural Language Sorting + */ +public class NaturalSort +{ + public static class Strings implements Comparator + { + private final Collator collator = Collator.getInstance(); + + @Override + public int compare(String o1, String o2) + { + CollationKey key1 = collator.getCollationKey(o1); + CollationKey key2 = collator.getCollationKey(o2); + return key1.compareTo(key2); + } + } + + public static class Files implements Comparator + { + private final Collator collator = Collator.getInstance(); + + @Override + public int compare(File o1, File o2) + { + CollationKey key1 = collator.getCollationKey(o1.getAbsolutePath()); + CollationKey key2 = collator.getCollationKey(o2.getAbsolutePath()); + return key1.compareTo(key2); + } + } +} diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java b/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java new file mode 100644 index 00000000000..ab4c477191c --- /dev/null +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java @@ -0,0 +1,149 @@ +// +// ======================================================================== +// 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.LinkedList; +import java.util.List; +import java.util.regex.Pattern; + +/** + * Simple Start .INI handler + */ +public class StartIni implements Iterable +{ + private final File file; + private final LinkedList lines; + + public StartIni(File file) throws FileNotFoundException, IOException + { + this.file = file; + this.lines = new LinkedList<>(); + try (FileReader reader = new FileReader(file)) + { + try (BufferedReader buf = new BufferedReader(reader)) + { + String line; + while ((line = buf.readLine()) != null) + { + line = line.trim(); + if (line.length() == 0) + { + // skip (empty line) + continue; + } + if (line.charAt(0) == '#') + { + // skip (comment) + continue; + } + + // Smart Handling, split into multiple OPTIONS lines + if (line.startsWith("OPTIONS=")) + { + for (String part : line.split(",")) + { + lines.add("OPTIONS=" + part); + } + } + else + { + // Add line as-is + lines.add(line); + } + } + } + } + } + + public File getFile() + { + return file; + } + + public int lineIndexOf(int offset, Pattern pattern) + { + int len = lines.size(); + for (int i = offset; i < len; i++) + { + if (pattern.matcher(lines.get(i)).matches()) + { + return i; + } + } + return -1; + } + + public List getLineMatches(Pattern pattern) + { + List ret = new ArrayList<>(); + for (String line : lines) + { + if (pattern.matcher(line).matches()) + { + ret.add(line); + } + } + return ret; + } + + public List getLines() + { + return lines; + } + + @Override + public Iterator iterator() + { + return lines.iterator(); + } + + public int overlayAt(int index, StartIni child) + { + int idx = index; + int count = 0; + for (String line : child) + { + if (this.hasLine(line)) + { + // skip + continue; + } + lines.add(idx++,line); + count++; + } + return count; + } + + private boolean hasLine(String line) + { + return lines.contains(line); + } + + public void removeLine(String line) + { + lines.remove(line); + } +} diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/HomeBaseTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/HomeBaseTest.java index 5df9f12ea5f..2785a83cce3 100644 --- a/jetty-start/src/test/java/org/eclipse/jetty/start/HomeBaseTest.java +++ b/jetty-start/src/test/java/org/eclipse/jetty/start/HomeBaseTest.java @@ -77,6 +77,25 @@ public class HomeBaseTest assertFileList(hb,"Files found",expected,files); } + @Test + public void testListFiles_Filtered_OnlyHome() throws IOException + { + File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home"); + File baseDir = null; + + HomeBase hb = new HomeBase(homeDir,baseDir); + List files = hb.listFiles("/start.d", new FS.IniFilter()); + + List expected = new ArrayList<>(); + expected.add("${jetty.home}/start.d/jmx.ini"); + expected.add("${jetty.home}/start.d/jndi.ini"); + expected.add("${jetty.home}/start.d/jsp.ini"); + expected.add("${jetty.home}/start.d/logging.ini"); + expected.add("${jetty.home}/start.d/ssl.ini"); + + assertFileList(hb,"Files found",expected,files); + } + @Test public void testListFiles_Both() throws IOException { @@ -96,7 +115,7 @@ public class HomeBaseTest assertFileList(hb,"Files found",expected,files); } - + @Test public void testGetFile_Both() throws IOException { diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java index c4243260afe..69a5c6c5552 100644 --- a/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java +++ b/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java @@ -18,12 +18,8 @@ package org.eclipse.jetty.start; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; import java.io.File; import java.io.IOException; @@ -35,6 +31,7 @@ import java.util.Vector; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.hamcrest.Matchers; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -59,11 +56,17 @@ public class MainTest { Main main = new Main(); List xmls = main.processCommandLine(new String[] {}); - - assertEquals("etc/jetty.xml",xmls.get(0)); - assertEquals("etc/jetty-jmx.xml",xmls.get(1)); - assertEquals("start.d","etc/jetty-testrealm.xml",xmls.get(2)); - assertEquals("start.d","etc/jetty-contexts.xml",xmls.get(5)); + + List expectedXmls = new ArrayList(); + expectedXmls.add("etc/jetty.xml"); // from start.ini + expectedXmls.add("etc/jetty-jmx.xml"); // from start.d/10-jmx.ini + // nothing from start.d/20-websocket.xml + expectedXmls.add("etc/jetty-testrealm.xml"); // from start.d/90-testrealm.ini + expectedXmls.add("etc/jetty-deploy.xml"); // from start.ini + expectedXmls.add("etc/jetty-webapps.xml"); // from start.ini + expectedXmls.add("etc/jetty-contexts.xml"); // from start.ini + + Assert.assertThat("XML Resolution Order "+xmls, xmls, contains(expectedXmls.toArray())); Set options = main.getConfig().getOptions(); assertThat(options,Matchers.contains("Server","ext","jmx","jsp","newOption","resources","websocket")); diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/PropertyPassingTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/PropertyPassingTest.java index 9275957109d..a5a1f9972cd 100644 --- a/jetty-start/src/test/java/org/eclipse/jetty/start/PropertyPassingTest.java +++ b/jetty-start/src/test/java/org/eclipse/jetty/start/PropertyPassingTest.java @@ -190,6 +190,8 @@ public class PropertyPassingTest System.out.println("Command line: " + cline); ProcessBuilder builder = new ProcessBuilder(commands); + // Set PWD + builder.directory(MavenTestingUtils.getTestResourceDir("empty.home")); Process pid = builder.start(); ConsoleCapture stdOutPump = new ConsoleCapture("STDOUT",pid.getInputStream()).start(); diff --git a/jetty-start/src/test/resources/empty.home/start.ini b/jetty-start/src/test/resources/empty.home/start.ini new file mode 100644 index 00000000000..e751e99807d --- /dev/null +++ b/jetty-start/src/test/resources/empty.home/start.ini @@ -0,0 +1,3 @@ +#=========================================================== +# Empty start.ini +#=========================================================== From 07636dbe62e598eb0e50246c696669fce450a177 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sun, 18 Aug 2013 08:20:27 -0700 Subject: [PATCH 10/16] Fixing up confusion over OPTIONS vs OPTION --- .../java/org/eclipse/jetty/start/Main.java | 30 +++--- .../org/eclipse/jetty/start/StartIni.java | 91 ++++++++++--------- .../org/eclipse/jetty/start/MainTest.java | 35 +++++-- 3 files changed, 87 insertions(+), 69 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index 853c60ae7d7..b8fc9a8cd77 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -52,6 +52,8 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; +import org.eclipse.jetty.start.StartIni.IncludeListener; + /*-------------------------------------------*/ /** *

@@ -63,7 +65,7 @@ import java.util.regex.Pattern; * 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. *

*/ -public class Main +public class Main implements IncludeListener { private static final String START_LOG_FILENAME = "start.log"; private static final SimpleDateFormat START_LOG_ROLLOVER_DATEFORMAT = new SimpleDateFormat("yyyy_MM_dd-HHmmSSSSS.'" + START_LOG_FILENAME + "'"); @@ -212,20 +214,7 @@ public class Main { String name = arg.substring(6); File file = _config.getHomeBase().getFile(name); - StartIni startini = new StartIni(file); - int idx; - while ((idx = startini.lineIndexOf(0,Pattern.compile("^.*/$"))) >= 0) - { - String subPath = startini.getLines().get(idx); - startini.getLines().remove(idx); - // find the sub ini files (based on HomeBase) - List childInis = _config.getHomeBase().listFiles(subPath,new FS.IniFilter()); - for (File childIni : childInis) - { - StartIni cini = new StartIni(childIni); - idx += startini.overlayAt(idx,cini); - } - } + StartIni startini = new StartIni(file,this); arguments.addAll(i + 1,startini.getLines()); } @@ -380,6 +369,17 @@ public class Main return xmls; } + + @Override + public List onIniInclude(String path) throws IOException + { + List included = new ArrayList<>(); + for(File file: _config.getHomeBase().listFiles(path,new FS.IniFilter())) + { + included.add(new StartIni(file)); + } + return included; + } private void download(String arg) { diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java b/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java index ab4c477191c..59a574793cd 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java @@ -34,10 +34,20 @@ import java.util.regex.Pattern; */ public class StartIni implements Iterable { + public static interface IncludeListener + { + public List onIniInclude(String path) throws IOException; + } + private final File file; private final LinkedList lines; public StartIni(File file) throws FileNotFoundException, IOException + { + this(file,null); + } + + public StartIni(File file, IncludeListener listener) throws FileNotFoundException, IOException { this.file = file; this.lines = new LinkedList<>(); @@ -54,48 +64,68 @@ public class StartIni implements Iterable // skip (empty line) continue; } + if (line.charAt(0) == '#') { // skip (comment) continue; } - // Smart Handling, split into multiple OPTIONS lines + // Smart Handling, split into multiple OPTIONS lines (for dup check reasons) if (line.startsWith("OPTIONS=")) { - for (String part : line.split(",")) + int idx = line.indexOf('='); + String value = line.substring(idx + 1); + for (String part : value.split(",")) { - lines.add("OPTIONS=" + part); + addUniqueLine("OPTION=" + part); + } + } + // Smart Handling, includes + else if (line.endsWith("/")) + { + if (listener == null) + { + System.err.printf("Nested includes not supported: %s (found in %s)%n",line,file.getAbsolutePath()); + } + else + { + // Collect HomeBase resolved included StartIni's + for (StartIni included : listener.onIniInclude(line)) + { + // Merge each line with prior lines to prevent duplicates + for (String includedLine : included) + { + addUniqueLine(includedLine); + } + } } } else { // Add line as-is - lines.add(line); + addUniqueLine(line); } } } } } + private void addUniqueLine(String line) + { + if (lines.contains(line)) + { + // skip + return; + } + lines.add(line); + } + public File getFile() { return file; } - public int lineIndexOf(int offset, Pattern pattern) - { - int len = lines.size(); - for (int i = offset; i < len; i++) - { - if (pattern.matcher(lines.get(i)).matches()) - { - return i; - } - } - return -1; - } - public List getLineMatches(Pattern pattern) { List ret = new ArrayList<>(); @@ -119,31 +149,4 @@ public class StartIni implements Iterable { return lines.iterator(); } - - public int overlayAt(int index, StartIni child) - { - int idx = index; - int count = 0; - for (String line : child) - { - if (this.hasLine(line)) - { - // skip - continue; - } - lines.add(idx++,line); - count++; - } - return count; - } - - private boolean hasLine(String line) - { - return lines.contains(line); - } - - public void removeLine(String line) - { - lines.remove(line); - } } diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java index 69a5c6c5552..6d643258d34 100644 --- a/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java +++ b/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java @@ -25,13 +25,12 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Vector; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; -import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -56,7 +55,8 @@ public class MainTest { Main main = new Main(); List xmls = main.processCommandLine(new String[] {}); - + + // Order is important here List expectedXmls = new ArrayList(); expectedXmls.add("etc/jetty.xml"); // from start.ini expectedXmls.add("etc/jetty-jmx.xml"); // from start.d/10-jmx.ini @@ -65,11 +65,26 @@ public class MainTest expectedXmls.add("etc/jetty-deploy.xml"); // from start.ini expectedXmls.add("etc/jetty-webapps.xml"); // from start.ini expectedXmls.add("etc/jetty-contexts.xml"); // from start.ini - - Assert.assertThat("XML Resolution Order "+xmls, xmls, contains(expectedXmls.toArray())); + assertThat("XML Resolution Order " + xmls,xmls,contains(expectedXmls.toArray())); + + // Order is irrelevant here Set options = main.getConfig().getOptions(); - assertThat(options,Matchers.contains("Server","ext","jmx","jsp","newOption","resources","websocket")); + Set expectedOptions = new HashSet<>(); + // from start.ini + expectedOptions.add("Server"); + expectedOptions.add("jsp"); + expectedOptions.add("resources"); + expectedOptions.add("websocket"); + expectedOptions.add("ext"); + expectedOptions.add("newOption"); + // from start.d/10-jmx.ini + expectedOptions.add("jmx"); + // from start.d/20-websocket.ini + expectedOptions.add("websocket"); + // no options from start.d/90-testrealm.ini + + assertThat("Options " + options,options,containsInAnyOrder(expectedOptions.toArray())); } @Test @@ -99,14 +114,14 @@ public class MainTest hasItems("/jetty/home with spaces/somejar.jar:/jetty/home with spaces/someotherjar.jar")); assertThat("args does not contain --exec",commandArgs,hasItems("--exec")); assertThat("CommandLine should contain jvmArgs",commandArgs,hasItems("-Xms1024m")); - assertThat("CommandLine should contain jvmArgs", commandArgs, hasItems("-Xmx1024m")); + assertThat("CommandLine should contain jvmArgs",commandArgs,hasItems("-Xmx1024m")); assertThat("CommandLine should contain xmls",commandArgs,hasItems("jetty.xml")); assertThat("CommandLine should contain xmls",commandArgs,hasItems("jetty-jmx.xml")); - assertThat("CommandLine should contain xmls", commandArgs, hasItems("jetty-logging.xml")); + assertThat("CommandLine should contain xmls",commandArgs,hasItems("jetty-logging.xml")); String commandLine = cmd.toString(); - assertThat("cmd.toString() should be properly escaped",commandLine,containsString("-cp /jetty/home\\ with\\ " + - "spaces/somejar.jar:/jetty/home\\ with\\ spaces/someotherjar.jar")); + assertThat("cmd.toString() should be properly escaped",commandLine,containsString("-cp /jetty/home\\ with\\ " + + "spaces/somejar.jar:/jetty/home\\ with\\ spaces/someotherjar.jar")); assertThat("cmd.toString() doesn't contain xml config files",commandLine,containsString(" jetty.xml jetty-jmx.xml jetty-logging.xml")); } From 4e1a62b5c5a74863f615094de46d3d274a4b4e0a Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sun, 18 Aug 2013 08:27:45 -0700 Subject: [PATCH 11/16] Using try-with-resources more consistently --- .../java/org/eclipse/jetty/start/Config.java | 39 ++++--------------- .../org/eclipse/jetty/start/JarVersion.java | 2 +- .../java/org/eclipse/jetty/start/Main.java | 13 ++----- 3 files changed, 12 insertions(+), 42 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java index 751212651ae..72a02c2e110 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java @@ -27,8 +27,6 @@ import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.net.URL; -import java.text.CollationKey; -import java.text.Collator; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -292,16 +290,6 @@ public class Config } } - private void close(InputStream stream) - { - FS.close(stream); - } - - private void close(Reader reader) - { - FS.close(reader); - } - public static boolean isDebug() { return DEBUG; @@ -548,7 +536,10 @@ public class Config */ public void parse(CharSequence buf) throws IOException { - parse(new StringReader(buf.toString())); + try (StringReader reader = new StringReader(buf.toString())) + { + parse(reader); + } } /** @@ -559,28 +550,18 @@ public class Config */ public void parse(InputStream stream) throws IOException { - InputStreamReader reader = null; - try + try (InputStreamReader reader = new InputStreamReader(stream)) { - reader = new InputStreamReader(stream); parse(reader); } - finally - { - close(reader); - } } /** */ public void parse(Reader reader) throws IOException { - BufferedReader buf = null; - - try + try(BufferedReader buf = new BufferedReader(reader)) { - buf = new BufferedReader(reader); - List options = new ArrayList(); options.add(DEFAULT_SECTION); _classpaths.put(DEFAULT_SECTION,new Classpath()); @@ -853,10 +834,6 @@ public class Config } } } - finally - { - close(buf); - } } private List processDynamicSectionIdentifier(String dynamicPathId,List sections) throws IOException @@ -933,8 +910,8 @@ public class Config } finally { - close(reader); - close(stream); + FS.close(reader); + FS.close(stream); } } diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/JarVersion.java b/jetty-start/src/main/java/org/eclipse/jetty/start/JarVersion.java index efd11ea7d2d..029f7654522 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/JarVersion.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/JarVersion.java @@ -102,7 +102,7 @@ public class JarVersion } finally { - Main.close(stream); + FS.close(stream); } } diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index b8fc9a8cd77..609ede2f908 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -19,7 +19,6 @@ package org.eclipse.jetty.start; import java.io.BufferedReader; -import java.io.Closeable; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; @@ -50,7 +49,6 @@ import java.util.Locale; import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.regex.Pattern; import org.eclipse.jetty.start.StartIni.IncludeListener; @@ -525,7 +523,7 @@ public class Main implements IncludeListener } finally { - close(buf); + FS.close(buf); } System.exit(EXIT_USAGE); } @@ -583,11 +581,6 @@ public class Main implements IncludeListener main.invoke(null,method_params); } - public static void close(Closeable c) - { - FS.close(c); - } - public void start(List xmls) throws IOException, InterruptedException { // Load potential Config (start.config) @@ -1020,7 +1013,7 @@ public class Main implements IncludeListener } finally { - close(cfgstream); + FS.close(cfgstream); } } @@ -1068,7 +1061,7 @@ public class Main implements IncludeListener } finally { - close(cfgstream); + FS.close(cfgstream); } } From aed68112cee953900d6096b00a6261d149314294 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sun, 18 Aug 2013 10:22:25 -0700 Subject: [PATCH 12/16] Fixing enable/disable Conflicts: jetty-start/src/main/java/org/eclipse/jetty/start/Main.java --- .../main/java/org/eclipse/jetty/start/FS.java | 85 ++++++++-- .../org/eclipse/jetty/start/HomeBase.java | 51 +++--- .../java/org/eclipse/jetty/start/Main.java | 151 +++++++++--------- .../org/eclipse/jetty/start/StartIni.java | 2 +- 4 files changed, 177 insertions(+), 112 deletions(-) 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 9476f8425ed..abcaad75a32 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 @@ -26,6 +26,44 @@ import java.util.regex.Pattern; public class FS { + public static class AllFilter implements FileFilter + { + public static final AllFilter INSTANCE = new AllFilter(); + + @Override + public boolean accept(File pathname) + { + return true; + } + } + + public static class FileNamesFilter implements FileFilter + { + private final String filenames[]; + + public FileNamesFilter(String... names) + { + this.filenames = names; + } + + @Override + public boolean accept(File path) + { + if (!path.isFile()) + { + return false; + } + for (String name : filenames) + { + if (name.equalsIgnoreCase(path.getName())) + { + return true; + } + } + return false; + } + } + public static class FilenameRegexFilter implements FileFilter { private final Pattern pattern; @@ -38,7 +76,7 @@ public class FS @Override public boolean accept(File path) { - return pattern.matcher(path.getName()).matches(); + return path.isFile() && pattern.matcher(path.getName()).matches(); } } @@ -58,20 +96,6 @@ public class FS } } - public static boolean isXml(String filename) - { - return Pattern.compile(".xml$",Pattern.CASE_INSENSITIVE).matcher(filename).matches(); - } - - public static boolean isFile(File file) - { - if (file == null) - { - return false; - } - return file.exists() && file.isFile(); - } - public static void close(Closeable c) { if (c == null) @@ -86,4 +110,35 @@ public class FS /* ignore */ } } + + public static boolean isFile(File file) + { + if (file == null) + { + return false; + } + return file.exists() && file.isFile(); + } + + public static boolean isXml(String filename) + { + return Pattern.compile(".xml$",Pattern.CASE_INSENSITIVE).matcher(filename).matches(); + } + + public static String separators(String path) + { + StringBuilder ret = new StringBuilder(); + for (char c : path.toCharArray()) + { + if ((c == '/') || (c == '\\')) + { + ret.append(File.separatorChar); + } + else + { + ret.append(c); + } + } + return ret.toString(); + } } diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java index a7097c612ad..9e5096c72b3 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java @@ -43,23 +43,6 @@ public class HomeBase } } - public static String separators(String path) - { - StringBuilder ret = new StringBuilder(); - for (char c : path.toCharArray()) - { - if ((c == '/') || (c == '\\')) - { - ret.append(File.separatorChar); - } - else - { - ret.append(c); - } - } - return ret.toString(); - } - private File homeDir; private File baseDir; @@ -120,7 +103,7 @@ public class HomeBase */ public File getFile(String path) { - String rpath = separators(path); + String rpath = FS.separators(path); // Relative to Base Directory First if (baseDir != null) @@ -189,21 +172,21 @@ public class HomeBase { Objects.requireNonNull(filter,"FileFilter cannot be null"); - File homePath = new File(homeDir,separators(relPathToDirectory)); + File homePath = new File(homeDir,FS.separators(relPathToDirectory)); List homeFiles = new ArrayList<>(); homeFiles.addAll(Arrays.asList(homePath.listFiles(filter))); if (baseDir != null) { // merge - File basePath = new File(baseDir,separators(relPathToDirectory)); + File basePath = new File(baseDir,FS.separators(relPathToDirectory)); File baseFiles[] = basePath.listFiles(filter); List ret = new ArrayList<>(); for (File base : baseFiles) { String relpath = toRelativePath(baseDir,base); - File home = new File(homeDir,separators(relpath)); + File home = new File(homeDir,FS.separators(relpath)); if (home.exists()) { homeFiles.remove(home); @@ -224,6 +207,32 @@ public class HomeBase return homeFiles; } } + + /** + * Collect the list of files in both ${jetty.base} and ${jetty.home}, with + * , even if the same file shows up in both places. + */ + public List rawListFiles(String relPathToDirectory, FileFilter filter) + { + Objects.requireNonNull(filter,"FileFilter cannot be null"); + + List ret = new ArrayList<>(); + + // Home Dir + File homePath = new File(homeDir,FS.separators(relPathToDirectory)); + ret.addAll(Arrays.asList(homePath.listFiles(filter))); + + if (baseDir != null) + { + // Base Dir + File basePath = new File(baseDir,FS.separators(relPathToDirectory)); + ret.addAll(Arrays.asList(basePath.listFiles(filter))); + } + + // Sort + Collections.sort(ret, new NaturalSort.Files()); + return ret; + } private String toRelativePath(File dir, File path) { diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index 609ede2f908..86058bffb73 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -24,7 +24,6 @@ import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -48,7 +47,6 @@ import java.util.List; import java.util.Locale; import java.util.Properties; import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.jetty.start.StartIni.IncludeListener; @@ -85,8 +83,10 @@ public class Main implements IncludeListener private final List _jvmArgs = new ArrayList<>(); private final List _enable = new ArrayList<>(); private final List _disable = new ArrayList<>(); + // Actively being used ini files private final List _iniFiles = new ArrayList<>(); - private final List _iniDirs = new ArrayList<>(); + // Actively being referenced ini include paths + private final List _iniIncludePaths = new ArrayList<>(); private String _startConfig = null; public static void main(String[] args) @@ -122,10 +122,16 @@ public class Main implements IncludeListener ArrayList arguments = new ArrayList<>(Arrays.asList(args)); boolean ini = false; for (String arg : arguments) + { if (arg.startsWith("--ini=") || arg.equals("--ini")) + { ini = true; + } + } if (!ini) + { arguments.add(0,"--ini=start.ini"); + } // The XML Configuration Files to initialize with List xmls = new ArrayList(); @@ -213,6 +219,7 @@ public class Main implements IncludeListener String name = arg.substring(6); File file = _config.getHomeBase().getFile(name); StartIni startini = new StartIni(file,this); + _iniFiles.add(file); arguments.addAll(i + 1,startini.getLines()); } @@ -367,13 +374,21 @@ public class Main implements IncludeListener return xmls; } - + @Override public List onIniInclude(String path) throws IOException { List included = new ArrayList<>(); - for(File file: _config.getHomeBase().listFiles(path,new FS.IniFilter())) + + HomeBase hb = _config.getHomeBase(); + + // Allow --enable and --disable to work + _iniIncludePaths.add(path); + + // Scan for ini files + for (File file : hb.listFiles(path,new FS.IniFilter())) { + _iniFiles.add(file); included.add(new StartIni(file)); } return included; @@ -491,21 +506,15 @@ public class Main implements IncludeListener { for (File file : _iniFiles) { - String path = path(file); + String path = _config.getHomeBase().toShortForm(file); System.out.printf("%s%s%n",indent,path); if (Config.isDebug()) { - try (FileReader reader = new FileReader(file); BufferedReader in = new BufferedReader(reader);) + StartIni ini = new StartIni(file); + for (String arg : ini) { - String arg; - while ((arg = in.readLine()) != null) - { - arg = arg.trim(); - if (arg.length() == 0 || arg.startsWith("#")) - continue; - System.out.printf("%s +-- %s%n",indent,arg); - } + System.out.printf("%s +-- %s%n",indent,arg); } } } @@ -1181,87 +1190,79 @@ public class Main implements IncludeListener { final String mini = module + ".ini"; final String disable = module + ".ini.disabled"; - final AtomicBoolean found = new AtomicBoolean(false); - FileFilter filter = new FileFilter() + + FileFilter disabledModuleFilter = new FS.FileNamesFilter(mini, disable); + + HomeBase hb = _config.getHomeBase(); + + // walk all ini include paths that were used + boolean found = false; + for (String includedPath : _iniIncludePaths) { - public boolean accept(File path) + Config.debug("Searching ${jetty.home}/%s and ${jetty.base}/% for %s",includedPath,includedPath,mini); + for (File file : hb.rawListFiles(includedPath,disabledModuleFilter)) { - if (!path.isFile()) - return false; - String n = path.getName(); - int i = n.indexOf(mini); - if (i < 0) - return false; - if (i > 0 && i != 4 && n.charAt(i - 1) != '-') - return false; - - found.set(true); - if (n.endsWith(mini)) + String n = file.getName(); + if (n.equalsIgnoreCase(mini)) { - System.err.printf("Module %s already enabled in %s as %s%n",module,path(path.getParent()),n); + System.err.printf("Module %s already enabled in %s%n",module,hb.toShortForm(file.getParent())); + found = true; } - else if (n.endsWith(disable)) + else if (n.equals(disable)) { - String enabled = n.substring(0,n.length() - 9); - System.err.printf("Enable %s in %s as %s%n",module,path(path.getParent()),enabled); - path.renameTo(new File(path.getParentFile(),enabled)); + System.err.printf("Enabling Module %s in %s%n",module,hb.toShortForm(file.getParent())); + file.renameTo(new File(file.getParentFile(),mini)); + found = true; } - else - System.err.printf("Bad module %s in %s as %s%n",module,path(path.getParent()),n); - - return false; } - }; + } - for (File dir : _iniDirs) - dir.listFiles(filter); - - if (!found.get()) - for (File dir : _iniDirs) - System.err.printf("Module %s not found in %s%n",module,path(dir)); + if (!found) + { + for (String includedPath : _iniIncludePaths) + { + System.err.printf("Module %s not found in %s%n",module,includedPath); + } + } } private void disable(final String module) { final String mini = module + ".ini"; final String disable = module + ".ini.disabled"; - final AtomicBoolean found = new AtomicBoolean(false); - FileFilter filter = new FileFilter() + + FileFilter disabledModuleFilter = new FS.FileNamesFilter(mini, disable); + + HomeBase hb = _config.getHomeBase(); + + // walk all ini include paths that were used + boolean found = false; + for (String includedPath : _iniIncludePaths) { - public boolean accept(File path) + Config.debug("Searching ${jetty.home}/%s and ${jetty.base}/% for %s",includedPath,includedPath,mini); + for (File file : hb.rawListFiles(includedPath,disabledModuleFilter)) { - if (!path.isFile()) - return false; - String n = path.getName(); - int i = n.indexOf(mini); - if (i < 0) - return false; - if (i > 0 && i != 4 && n.charAt(i - 1) != '-') - return false; - - found.set(true); - if (n.endsWith(disable)) + String n = file.getName(); + if (n.equalsIgnoreCase(disable)) { - System.err.printf("Module %s already disabled in %s as %s%n",module,path(path.getParent()),n); + System.err.printf("Module %s already disabled in %s%n",module,hb.toShortForm(file.getParent())); + found = true; } - else if (n.endsWith(mini)) + else if (n.equals(mini)) { - String disabled = n + ".disabled"; - System.err.printf("Disable %s in %s as %s%n",module,path(path.getParent()),disabled); - path.renameTo(new File(path.getParentFile(),disabled)); + System.err.printf("Disabling Module %s in %s%n",module,hb.toShortForm(file.getParent())); + file.renameTo(new File(file.getParentFile(),disable)); + found = true; } - else - System.err.printf("Bad module %s in %s as %s%n",module,path(path.getParent()),n); - - return false; } - }; + } - for (File dir : _iniDirs) - dir.listFiles(filter); - - if (!found.get()) - for (File dir : _iniDirs) - System.err.printf("Module %s not found in %s%n",module,path(dir)); + if (!found) + { + for (String includedPath : _iniIncludePaths) + { + System.err.printf("Module %s not found in %s%n",module,includedPath); + } + } } } diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java b/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java index 59a574793cd..2772bec5f42 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java @@ -86,7 +86,7 @@ public class StartIni implements Iterable { if (listener == null) { - System.err.printf("Nested includes not supported: %s (found in %s)%n",line,file.getAbsolutePath()); + Config.debug("Nested include ignored: %s (found in %s)",line,file.getAbsolutePath()); } else { From 578613e901e06d4a2b1a86566d484ac2e5091b67 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sun, 18 Aug 2013 10:29:57 -0700 Subject: [PATCH 13/16] Consolidating filters --- .../java/org/eclipse/jetty/start/HomeBase.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java index 9e5096c72b3..8b4153515da 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java @@ -28,21 +28,10 @@ import java.util.List; import java.util.Objects; /** - * File access for ${jetty.home}, and optional ${jetty.base}, directories + * File access for ${jetty.home}, and optional ${jetty.base}, directories. */ public class HomeBase { - private static class AllFilter implements FileFilter - { - public static final AllFilter INSTANCE = new AllFilter(); - - @Override - public boolean accept(File pathname) - { - return true; - } - } - private File homeDir; private File baseDir; @@ -153,7 +142,7 @@ public class HomeBase */ public List listFiles(String relPathToDirectory) { - return listFiles(relPathToDirectory,AllFilter.INSTANCE); + return listFiles(relPathToDirectory,FS.AllFilter.INSTANCE); } /** From b1b394b4bfec0be964713f17c65400181be376b2 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Sun, 18 Aug 2013 10:40:15 -0700 Subject: [PATCH 14/16] jetty.base is always defined. --- .../java/org/eclipse/jetty/start/Config.java | 4 +- .../main/java/org/eclipse/jetty/start/FS.java | 3 +- .../org/eclipse/jetty/start/HomeBase.java | 43 ++++++++++--------- .../java/org/eclipse/jetty/start/Main.java | 12 +----- 4 files changed, 27 insertions(+), 35 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java index 72a02c2e110..1af85edaa97 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Config.java @@ -204,9 +204,7 @@ public class Config __instance=this; _homebase = new HomeBase(); setProperty("jetty.home",_homebase.getHome()); - if(_homebase.hasBase()) { - setProperty("jetty.base",_homebase.getBase()); - } + setProperty("jetty.base",_homebase.getBase()); } public HomeBase getHomeBase() 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 abcaad75a32..1a5999103d6 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 @@ -22,6 +22,7 @@ import java.io.Closeable; import java.io.File; import java.io.FileFilter; import java.io.IOException; +import java.util.Locale; import java.util.regex.Pattern; public class FS @@ -122,7 +123,7 @@ public class FS public static boolean isXml(String filename) { - return Pattern.compile(".xml$",Pattern.CASE_INSENSITIVE).matcher(filename).matches(); + return filename.toLowerCase(Locale.ENGLISH).endsWith(".xml"); } public static String separators(String path) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java index 8b4153515da..b225f2832b4 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java @@ -28,7 +28,13 @@ import java.util.List; import java.util.Objects; /** - * File access for ${jetty.home}, and optional ${jetty.base}, directories. + * File access for ${jetty.home}, ${jetty.base}, directories. + *

+ * By default, both ${jetty.home} and ${jetty.base} are the same directory, but they can point at different directories. + *

+ * The ${jetty.home} directory is where the main Jetty binaries and default configuration is housed. + *

+ * The ${jetty.base} directory is where the execution specific configuration and webapps are obtained from. */ public class HomeBase { @@ -39,11 +45,7 @@ public class HomeBase { String userDir = System.getProperty("user.dir"); this.homeDir = new File(System.getProperty("jetty.home",userDir)); - String base = System.getProperty("jetty.base"); - if (base != null) - { - this.baseDir = new File(base); - } + this.baseDir = new File(System.getProperty("jetty.base",homeDir.getAbsolutePath())); } public HomeBase(File homeDir, File baseDir) @@ -51,12 +53,12 @@ public class HomeBase this.homeDir = homeDir; this.baseDir = baseDir; } - - public boolean hasBase() + + public boolean isBaseDifferent() { - return this.baseDir != null; + return homeDir.compareTo(baseDir) != 0; } - + public void setBaseDir(File dir) { this.baseDir = dir; @@ -95,7 +97,7 @@ public class HomeBase String rpath = FS.separators(path); // Relative to Base Directory First - if (baseDir != null) + if (isBaseDifferent()) { File file = new File(baseDir,rpath); if (file.exists()) @@ -114,7 +116,7 @@ public class HomeBase // Finally, as an absolute path return new File(rpath); } - + public void setHomeDir(File dir) { this.homeDir = dir; @@ -165,7 +167,7 @@ public class HomeBase List homeFiles = new ArrayList<>(); homeFiles.addAll(Arrays.asList(homePath.listFiles(filter))); - if (baseDir != null) + if (isBaseDifferent()) { // merge File basePath = new File(baseDir,FS.separators(relPathToDirectory)); @@ -186,20 +188,19 @@ public class HomeBase // add any remaining home files. ret.addAll(homeFiles); - Collections.sort(ret, new NaturalSort.Files()); + Collections.sort(ret,new NaturalSort.Files()); return ret; } else { // simple return - Collections.sort(homeFiles, new NaturalSort.Files()); + Collections.sort(homeFiles,new NaturalSort.Files()); return homeFiles; } } - + /** - * 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}, with , even if the same file shows up in both places. */ public List rawListFiles(String relPathToDirectory, FileFilter filter) { @@ -211,7 +212,7 @@ public class HomeBase File homePath = new File(homeDir,FS.separators(relPathToDirectory)); ret.addAll(Arrays.asList(homePath.listFiles(filter))); - if (baseDir != null) + if (isBaseDifferent()) { // Base Dir File basePath = new File(baseDir,FS.separators(relPathToDirectory)); @@ -219,7 +220,7 @@ public class HomeBase } // Sort - Collections.sort(ret, new NaturalSort.Files()); + Collections.sort(ret,new NaturalSort.Files()); return ret; } @@ -265,7 +266,7 @@ public class HomeBase return "${jetty.home}" + path.substring(value.length()); } - if (baseDir != null) + if (isBaseDifferent()) { value = baseDir.getAbsolutePath(); if (path.startsWith(value)) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index 86058bffb73..c4bb917a944 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -775,10 +775,7 @@ public class Main implements IncludeListener cmd.addArg(x); } cmd.addRawArg("-Djetty.home=" + _config.getHomeBase().getHome()); - if (_config.getHomeBase().hasBase()) - { - cmd.addRawArg("-Djetty.base=" + _config.getHomeBase().getBase()); - } + cmd.addRawArg("-Djetty.base=" + _config.getHomeBase().getBase()); // Special Stop/Shutdown properties ensureSystemPropertySet("STOP.PORT"); @@ -901,12 +898,7 @@ public class Main implements IncludeListener + "then overlapping entries will not be repeated in the eventual classpath."); System.out.println(); System.out.printf("${jetty.home} = %s%n",_config.getHomeBase().getHome()); - String base = ""; - if (_config.getHomeBase().hasBase()) - { - base = _config.getHomeBase().getBase(); - } - System.out.printf("${jetty.base} = %s%n",base); + System.out.printf("${jetty.base} = %s%n",_config.getHomeBase().getBase()); System.out.println(); for (String sectionId : sectionIds) From c0402dec4ab7ee986ff142b0bbae8121f66b4561 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 19 Aug 2013 16:29:01 +1000 Subject: [PATCH 15/16] 414635 Modular start.d and jetty.base property Merged branch jetty-9.1-altstart with cherry picks of ecf30e4 72f8143 998f95b 46a9495 fe4b922 3443593 2b40990 07636db 4e1a62b aed6811 578613e b1b394b --- .../org/eclipse/jetty/start/HomeBase.java | 2 +- .../java/org/eclipse/jetty/start/Main.java | 45 ++++++++++++++++++- .../org/eclipse/jetty/start/MainTest.java | 2 +- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java index b225f2832b4..383a42a54cc 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/HomeBase.java @@ -51,7 +51,7 @@ public class HomeBase public HomeBase(File homeDir, File baseDir) { this.homeDir = homeDir; - this.baseDir = baseDir; + this.baseDir = baseDir==null?homeDir:baseDir; } public boolean isBaseDifferent() diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index c4bb917a944..afc6231739c 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -47,6 +47,8 @@ import java.util.List; import java.util.Locale; import java.util.Properties; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.jetty.start.StartIni.IncludeListener; @@ -65,6 +67,7 @@ public class Main implements IncludeListener { private static final String START_LOG_FILENAME = "start.log"; private static final SimpleDateFormat START_LOG_ROLLOVER_DATEFORMAT = new SimpleDateFormat("yyyy_MM_dd-HHmmSSSSS.'" + START_LOG_FILENAME + "'"); + private static final Pattern NNN_MODULE_INI = Pattern.compile("^(\\d\\d\\d-)(.*?\\.ini)(\\.disabled)?$"); private static final int EXIT_USAGE = 1; private static final int ERR_LOGGING = -1; @@ -1183,7 +1186,7 @@ public class Main implements IncludeListener final String mini = module + ".ini"; final String disable = module + ".ini.disabled"; - FileFilter disabledModuleFilter = new FS.FileNamesFilter(mini, disable); + FileFilter disabledModuleFilter = new FS.FilenameRegexFilter("(\\d\\d\\d-)?"+Pattern.quote(module)+"\\.ini(\\.disabled)?"); HomeBase hb = _config.getHomeBase(); @@ -1206,6 +1209,25 @@ public class Main implements IncludeListener file.renameTo(new File(file.getParentFile(),mini)); found = true; } + else + { + Matcher matcher = NNN_MODULE_INI.matcher(n); + if (matcher.matches()) + { + if (matcher.group(3)==null) + { + System.err.printf("Module %s already enabled in %s as %s%n",module,hb.toShortForm(file.getParent()),n); + found = true; + } + else + { + String enabled=matcher.group(1)+mini; + System.err.printf("Enabling Module %s in %s as %s%n",module,hb.toShortForm(file.getParent()),enabled); + file.renameTo(new File(file.getParentFile(),enabled)); + found = true; + } + } + } } } @@ -1223,7 +1245,7 @@ public class Main implements IncludeListener final String mini = module + ".ini"; final String disable = module + ".ini.disabled"; - FileFilter disabledModuleFilter = new FS.FileNamesFilter(mini, disable); + FileFilter disabledModuleFilter = new FS.FilenameRegexFilter("(\\d\\d\\d-)?"+Pattern.quote(module)+"\\.ini(\\.disabled)?"); HomeBase hb = _config.getHomeBase(); @@ -1246,6 +1268,25 @@ public class Main implements IncludeListener file.renameTo(new File(file.getParentFile(),disable)); found = true; } + else + { + Matcher matcher = NNN_MODULE_INI.matcher(n); + if (matcher.matches()) + { + if (matcher.group(3)!=null) + { + System.err.printf("Module %s already disabled in %s as %s%n",module,hb.toShortForm(file.getParent()),n); + found = true; + } + else + { + 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; + } + } + } } } diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java index 6d643258d34..c7a277e1912 100644 --- a/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java +++ b/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java @@ -108,7 +108,7 @@ public class MainTest assertThat("CommandLineBuilder shouldn't be null",cmd,notNullValue()); List commandArgs = cmd.getArgs(); - assertThat("commandArgs should contain 11 elements",commandArgs.size(),equalTo(11)); + assertThat("commandArgs elements",commandArgs.size(),equalTo(12)); assertThat("args does not contain -cp",commandArgs,hasItems("-cp")); assertThat("Classpath should be correctly quoted and match expected value",commandArgs, hasItems("/jetty/home with spaces/somejar.jar:/jetty/home with spaces/someotherjar.jar")); From ad8db51ed5c9db5819b9860b05a4760e805607bb Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Mon, 19 Aug 2013 17:52:13 +1000 Subject: [PATCH 16/16] 415314 Jetty should not commit response on output if < Response.setBufferSize() bytes are written --- .../java/org/eclipse/jetty/server/HttpOutput.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java index 4d87aa01b8c..2c7254ce1a9 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java @@ -57,6 +57,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable private long _written; private ByteBuffer _aggregate; private int _bufferSize; + private int _commitSize; private WriteListener _writeListener; private volatile Throwable _onError; @@ -79,6 +80,7 @@ write completed - - - ASYNC READY->owp { _channel = channel; _bufferSize = _channel.getHttpConfiguration().getOutputBufferSize(); + _commitSize=_bufferSize/4; } public boolean isWritten() @@ -231,7 +233,7 @@ write completed - - - ASYNC READY->owp // Should we aggregate? int capacity = getBufferSize(); - if (!complete && len<=capacity/4) + if (!complete && len<=_commitSize) { if (_aggregate == null) _aggregate = _channel.getByteBufferPool().acquire(capacity, false); @@ -271,7 +273,7 @@ write completed - - - ASYNC READY->owp // Should we aggregate? int capacity = getBufferSize(); - if (!complete && len<=capacity/4) + if (!complete && len<=_commitSize) { if (_aggregate == null) _aggregate = _channel.getByteBufferPool().acquire(capacity, false); @@ -294,7 +296,7 @@ write completed - - - ASYNC READY->owp _channel.write(_aggregate, complete && len==0); // should we fill aggregate again from the buffer? - if (len>0 && !complete && len<=_aggregate.capacity()/4) + if (len>0 && !complete && len<=_commitSize) { BufferUtil.append(_aggregate, b, off, len); return; @@ -596,7 +598,8 @@ write completed - - - ASYNC READY->owp public void setBufferSize(int size) { - this._bufferSize = size; + _bufferSize = size; + _commitSize = size; } public void resetBuffer() @@ -704,12 +707,10 @@ write completed - - - ASYNC READY->owp return false; } - // TODO write comments - if (!_complete && _len0 && !_flushed) { _flushed=true;