433563 - Jetty fails to startup on windows - InvalidPathException
+ PathMatchers.isAbsolute() and .getSearchRoot() adjusted to not rely on Path object behavior differences between Unix and Windows + Updated StartArgs processing of --lib to automatically expand extra lib references prior to submitting them to the internal BaseHome for processing as pattern for paths. + Updated test cases for new behavior.
This commit is contained in:
parent
1de043d6c3
commit
5cc6833f50
|
@ -59,7 +59,7 @@ public class PathMatchers
|
|||
* the raw pattern (can contain "glob:" or "regex:" syntax indicator)
|
||||
* @return the Path version of the pattern provided.
|
||||
*/
|
||||
private static Path asPath(String pattern)
|
||||
private static Path asPath(final String pattern)
|
||||
{
|
||||
String test = pattern;
|
||||
if (test.startsWith("glob:"))
|
||||
|
@ -119,43 +119,89 @@ public class PathMatchers
|
|||
*/
|
||||
public static Path getSearchRoot(final String pattern)
|
||||
{
|
||||
Path path = asPath(pattern);
|
||||
Path test = path.getRoot();
|
||||
StringBuilder root = new StringBuilder();
|
||||
|
||||
boolean isSyntaxed = pattern.startsWith("glob:") || pattern.startsWith("regex:");
|
||||
|
||||
int len = path.getNameCount();
|
||||
for (int i = 0; i < len; i++)
|
||||
int start = 0;
|
||||
boolean syntaxed = false;
|
||||
if (pattern.startsWith("glob:"))
|
||||
{
|
||||
Path part = path.getName(i);
|
||||
if (isGlob(part.toString(),isSyntaxed))
|
||||
start = "glob:".length();
|
||||
syntaxed = true;
|
||||
}
|
||||
else if (pattern.startsWith("regex:"))
|
||||
{
|
||||
start = "regex:".length();
|
||||
syntaxed = true;
|
||||
}
|
||||
int len = pattern.length();
|
||||
int lastSep = 0;
|
||||
for (int i = start; i < len; i++)
|
||||
{
|
||||
int cp = pattern.codePointAt(i);
|
||||
if (cp < 127)
|
||||
{
|
||||
// found a glob part, return prior parts now
|
||||
break;
|
||||
}
|
||||
char c = (char)cp;
|
||||
|
||||
// is this the last entry?
|
||||
if (i == (len - 1))
|
||||
{
|
||||
// always return prior entries
|
||||
break;
|
||||
}
|
||||
// unix path case
|
||||
if (c == '/')
|
||||
{
|
||||
root.append(c);
|
||||
lastSep = root.length();
|
||||
}
|
||||
else if (c == '\\')
|
||||
{
|
||||
root.append("\\");
|
||||
lastSep = root.length();
|
||||
|
||||
if (test == null)
|
||||
{
|
||||
test = part;
|
||||
// possible escaped sequence.
|
||||
// only really interested in windows escape sequences "\\"
|
||||
int count = countChars(pattern,i+1,'\\');
|
||||
if (count > 0)
|
||||
{
|
||||
// skip extra slashes
|
||||
i += count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isGlob(c,syntaxed))
|
||||
{
|
||||
break;
|
||||
}
|
||||
root.append(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
test = test.resolve(part);
|
||||
root.appendCodePoint(cp);
|
||||
}
|
||||
}
|
||||
|
||||
if (test == null)
|
||||
String rootPath = root.substring(0,lastSep);
|
||||
if (rootPath.length() <= 0)
|
||||
{
|
||||
return EMPTY_PATH;
|
||||
}
|
||||
return test;
|
||||
|
||||
return asPath(rootPath);
|
||||
}
|
||||
|
||||
private static int countChars(String pattern, int offset, char c)
|
||||
{
|
||||
int count = 0;
|
||||
int len = pattern.length();
|
||||
for (int i = offset; i < len; i++)
|
||||
{
|
||||
if (pattern.charAt(i) == c)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,29 +230,24 @@ public class PathMatchers
|
|||
* true if overall pattern is syntaxed with <code>"glob:"</code> or <code>"regex:"</code>
|
||||
* @return true if part has glob characters
|
||||
*/
|
||||
private static boolean isGlob(String part, boolean syntaxed)
|
||||
private static boolean isGlob(char c, boolean syntaxed)
|
||||
{
|
||||
int len = part.length();
|
||||
for (int i = 0; i < len; i++)
|
||||
for (char g : GLOB_CHARS)
|
||||
{
|
||||
char c = part.charAt(i);
|
||||
for (char g : GLOB_CHARS)
|
||||
if (c == g)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (syntaxed)
|
||||
{
|
||||
for (char g : SYNTAXED_GLOB_CHARS)
|
||||
{
|
||||
if (c == g)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (syntaxed)
|
||||
{
|
||||
for (char g : SYNTAXED_GLOB_CHARS)
|
||||
{
|
||||
if (c == g)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -361,7 +361,10 @@ public class StartArgs
|
|||
StartLog.debug("rawlibref = " + rawlibref);
|
||||
String libref = properties.expand(rawlibref);
|
||||
StartLog.debug("expanded = " + libref);
|
||||
|
||||
|
||||
// perform path escaping (needed by windows)
|
||||
libref = libref.replaceAll("\\\\([^\\\\])","\\\\\\\\$1");
|
||||
|
||||
for (Path libpath : baseHome.getPaths(libref))
|
||||
{
|
||||
classpath.addComponent(libpath.toFile());
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
package org.eclipse.jetty.start;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
@ -38,7 +38,7 @@ public class MainTest
|
|||
System.setProperty("jetty.home","");
|
||||
System.setProperty("jetty.base","");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBasicProcessing() throws Exception
|
||||
{
|
||||
|
@ -69,12 +69,12 @@ public class MainTest
|
|||
StartArgs args = main.processCommandLine(cmdLineArgs.toArray(new String[cmdLineArgs.size()]));
|
||||
System.err.println(args);
|
||||
|
||||
//Assert.assertEquals("--stop should not build module tree", 0, args.getEnabledModules().size());
|
||||
// Assert.assertEquals("--stop should not build module tree", 0, args.getEnabledModules().size());
|
||||
Assert.assertEquals("--stop missing port","10000",args.getProperties().getString("STOP.PORT"));
|
||||
Assert.assertEquals("--stop missing key","foo",args.getProperties().getString("STOP.KEY"));
|
||||
Assert.assertEquals("--stop missing wait","300",args.getProperties().getString("STOP.WAIT"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore("Just a bit noisy for general testing")
|
||||
public void testListConfig() throws Exception
|
||||
|
@ -90,7 +90,7 @@ public class MainTest
|
|||
StartArgs args = main.processCommandLine(cmdLineArgs.toArray(new String[cmdLineArgs.size()]));
|
||||
main.listConfig(args);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore("Just a bit noisy for general testing")
|
||||
public void testHelp() throws Exception
|
||||
|
@ -107,12 +107,12 @@ public class MainTest
|
|||
File homePath = MavenTestingUtils.getTestResourceDir("usecases/home").getAbsoluteFile();
|
||||
cmdLineArgs.add("jetty.home=" + homePath);
|
||||
cmdLineArgs.add("user.dir=" + homePath);
|
||||
|
||||
|
||||
// JVM args
|
||||
cmdLineArgs.add("--exec");
|
||||
cmdLineArgs.add("-Xms1024m");
|
||||
cmdLineArgs.add("-Xmx1024m");
|
||||
|
||||
|
||||
// Arbitrary Libs
|
||||
File extraJar = MavenTestingUtils.getTestResourceFile("extra-libs/example.jar");
|
||||
File extraDir = MavenTestingUtils.getTestResourceDir("extra-resources");
|
||||
|
@ -127,9 +127,9 @@ public class MainTest
|
|||
|
||||
StartArgs args = main.processCommandLine(cmdLineArgs.toArray(new String[cmdLineArgs.size()]));
|
||||
BaseHome baseHome = main.getBaseHome();
|
||||
|
||||
Assert.assertThat("jetty.home", baseHome.getHome(), is(homePath.getAbsolutePath()));
|
||||
Assert.assertThat("jetty.base", baseHome.getBase(), is(homePath.getAbsolutePath()));
|
||||
|
||||
Assert.assertThat("jetty.home",baseHome.getHome(),is(homePath.getAbsolutePath()));
|
||||
Assert.assertThat("jetty.base",baseHome.getBase(),is(homePath.getAbsolutePath()));
|
||||
|
||||
ConfigurationAssert.assertConfiguration(baseHome,args,"assert-home-with-jvm.txt");
|
||||
}
|
||||
|
@ -146,10 +146,10 @@ public class MainTest
|
|||
Main main = new Main();
|
||||
StartArgs args = main.processCommandLine(cmdLineArgs.toArray(new String[cmdLineArgs.size()]));
|
||||
BaseHome baseHome = main.getBaseHome();
|
||||
|
||||
Assert.assertThat("jetty.home", baseHome.getHome(), is(homePath.getAbsolutePath()));
|
||||
Assert.assertThat("jetty.base", baseHome.getBase(), is(homePath.getAbsolutePath()));
|
||||
|
||||
|
||||
Assert.assertThat("jetty.home",baseHome.getHome(),is(homePath.getAbsolutePath()));
|
||||
Assert.assertThat("jetty.base",baseHome.getBase(),is(homePath.getAbsolutePath()));
|
||||
|
||||
ConfigurationAssert.assertConfiguration(baseHome,args,"assert-home-with-spaces.txt");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.start;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.OS;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameter;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class PathMatchersAbsoluteTest
|
||||
{
|
||||
@Parameters(name="{0} -> {1}")
|
||||
public static List<Object[]> data()
|
||||
{
|
||||
List<Object[]> cases = new ArrayList<>();
|
||||
|
||||
if(OS.IS_UNIX)
|
||||
{
|
||||
cases.add(new Object[]{"/opt/app",true});
|
||||
cases.add(new Object[]{"/opt/app",true});
|
||||
cases.add(new Object[]{"/opt/florb",true});
|
||||
cases.add(new Object[]{"/home/user/benfranklin",true});
|
||||
cases.add(new Object[]{"glob:/home/user/benfranklin/*.jar",true});
|
||||
cases.add(new Object[]{"glob:/**/*.jar",true});
|
||||
cases.add(new Object[]{"regex:/*-[^dev].ini",true});
|
||||
}
|
||||
|
||||
if(OS.IS_WINDOWS)
|
||||
{
|
||||
// normal declaration
|
||||
cases.add(new Object[]{"D:\\code\\jetty\\jetty-start\\src\\test\\resources\\extra-libs\\example.jar",true});
|
||||
// escaped declaration
|
||||
cases.add(new Object[]{"C:\\\\System32",true});
|
||||
cases.add(new Object[]{"C:\\\\Program Files",true});
|
||||
}
|
||||
|
||||
cases.add(new Object[]{"etc",false});
|
||||
cases.add(new Object[]{"lib",false});
|
||||
cases.add(new Object[]{"${user.dir}",false});
|
||||
cases.add(new Object[]{"**/*.jar",false});
|
||||
cases.add(new Object[]{"glob:*.ini",false});
|
||||
cases.add(new Object[]{"regex:*-[^dev].ini",false});
|
||||
|
||||
return cases;
|
||||
}
|
||||
|
||||
@Parameter(value=0)
|
||||
public String pattern;
|
||||
@Parameter(value=1)
|
||||
public boolean expected;
|
||||
|
||||
@Test
|
||||
public void testIsAbsolute()
|
||||
{
|
||||
Assert.assertThat("isAbsolute(\""+pattern+"\")",PathMatchers.isAbsolute(pattern),is(expected));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.start;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.OS;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameter;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class PathMatchersSearchRootTest
|
||||
{
|
||||
@Parameters(name="{0}")
|
||||
public static List<String[]> data()
|
||||
{
|
||||
List<String[]> cases = new ArrayList<>();
|
||||
|
||||
if (OS.IS_UNIX)
|
||||
{
|
||||
// absolute first
|
||||
cases.add(new String[]{"/opt/app/*.jar","/opt/app"});
|
||||
cases.add(new String[]{"/lib/jvm/**/jre/lib/*.jar","/lib/jvm"});
|
||||
cases.add(new String[]{"glob:/var/lib/*.xml","/var/lib"});
|
||||
cases.add(new String[]{"glob:/var/lib/*.{xml,java}","/var/lib"});
|
||||
cases.add(new String[]{"glob:/opt/corporate/lib-{dev,prod}/*.ini","/opt/corporate"});
|
||||
cases.add(new String[]{"regex:/opt/jetty/.*/lib-(dev|prod)/*.ini","/opt/jetty"});
|
||||
|
||||
cases.add(new String[]{"/*.ini","/"});
|
||||
cases.add(new String[]{"/etc/jetty.conf","/etc"});
|
||||
cases.add(new String[]{"/common.conf","/"});
|
||||
}
|
||||
|
||||
if (OS.IS_WINDOWS)
|
||||
{
|
||||
// absolute declaration
|
||||
cases.add(new String[]{"D:\\code\\jetty\\jetty-start\\src\\test\\resources\\extra-libs\\example.jar",
|
||||
"D:\\code\\jetty\\jetty-start\\src\\test\\resources\\extra-libs"});
|
||||
// escaped declaration
|
||||
// absolute patterns (complete with required windows slash escaping)
|
||||
cases.add(new String[]{"C:\\\\corp\\\\lib\\\\*.jar","C:\\corp\\lib"});
|
||||
cases.add(new String[]{"D:\\\\lib\\\\**\\\\jre\\\\lib\\\\*.jar","D:\\lib"});
|
||||
}
|
||||
|
||||
// some relative paths
|
||||
cases.add(new String[]{"lib/*.jar","lib"});
|
||||
cases.add(new String[]{"etc/jetty.xml","etc"});
|
||||
cases.add(new String[]{"start.ini","."});
|
||||
cases.add(new String[]{"start.d/","start.d"});
|
||||
return cases;
|
||||
}
|
||||
|
||||
@Parameter(value=0)
|
||||
public String pattern;
|
||||
@Parameter(value=1)
|
||||
public String expectedSearchRoot;
|
||||
|
||||
@Test
|
||||
public void testSearchRoot()
|
||||
{
|
||||
Path actual = PathMatchers.getSearchRoot(pattern);
|
||||
String expectedNormal = FS.separators(expectedSearchRoot);
|
||||
Assert.assertThat(".getSearchRoot(\"" + pattern + "\")",actual.toString(),is(expectedNormal));
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.start;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.OS;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PathMatchersTest
|
||||
{
|
||||
private void assertIsAbsolute(String pattern, boolean expected)
|
||||
{
|
||||
Assert.assertThat("isAbsolute(\"" + pattern + "\")",PathMatchers.isAbsolute(pattern),is(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAbsolute()
|
||||
{
|
||||
if (OS.IS_UNIX)
|
||||
{
|
||||
assertIsAbsolute("/opt/app",true);
|
||||
assertIsAbsolute("/opt/florb",true);
|
||||
assertIsAbsolute("/home/user/benfranklin",true);
|
||||
assertIsAbsolute("glob:/home/user/benfranklin/*.jar",true);
|
||||
assertIsAbsolute("glob:/**/*.jar",true);
|
||||
assertIsAbsolute("regex:/*-[^dev].ini",true);
|
||||
}
|
||||
|
||||
if (OS.IS_WINDOWS)
|
||||
{
|
||||
assertIsAbsolute("C:\\\\System32",true);
|
||||
assertIsAbsolute("C:\\\\Program Files",true);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotAbsolute()
|
||||
{
|
||||
assertIsAbsolute("etc",false);
|
||||
assertIsAbsolute("lib",false);
|
||||
assertIsAbsolute("${user.dir}",false);
|
||||
assertIsAbsolute("**/*.jar",false);
|
||||
assertIsAbsolute("glob:*.ini",false);
|
||||
assertIsAbsolute("regex:*-[^dev].ini",false);
|
||||
}
|
||||
|
||||
private void assertSearchRoot(String pattern, String expectedSearchRoot)
|
||||
{
|
||||
Path actual = PathMatchers.getSearchRoot(pattern);
|
||||
String expectedNormal = FS.separators(expectedSearchRoot);
|
||||
Assert.assertThat(".getSearchRoot(\"" + pattern + "\")",actual.toString(),is(expectedNormal));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSearchRoot()
|
||||
{
|
||||
if (OS.IS_UNIX)
|
||||
{
|
||||
// absolute first
|
||||
assertSearchRoot("/opt/app/*.jar","/opt/app");
|
||||
assertSearchRoot("/lib/jvm/**/jre/lib/*.jar","/lib/jvm");
|
||||
assertSearchRoot("glob:/var/lib/*.xml","/var/lib");
|
||||
assertSearchRoot("glob:/var/lib/*.{xml,java}","/var/lib");
|
||||
assertSearchRoot("glob:/opt/corporate/lib-{dev,prod}/*.ini","/opt/corporate");
|
||||
assertSearchRoot("regex:/opt/jetty/.*/lib-(dev|prod)/*.ini","/opt/jetty");
|
||||
|
||||
assertSearchRoot("/*.ini","/");
|
||||
assertSearchRoot("/etc/jetty.conf","/etc");
|
||||
assertSearchRoot("/common.conf","/");
|
||||
}
|
||||
|
||||
if (OS.IS_WINDOWS)
|
||||
{
|
||||
// absolute patterns (complete with required windows slash escaping)
|
||||
assertSearchRoot("C:\\\\corp\\\\lib\\\\*.jar","C:\\corp\\lib");
|
||||
assertSearchRoot("D:\\\\lib\\\\**\\\\jre\\\\lib\\\\*.jar","C:\\lib");
|
||||
}
|
||||
|
||||
// some relative paths
|
||||
assertSearchRoot("lib/*.jar","lib");
|
||||
assertSearchRoot("etc/jetty.xml","etc");
|
||||
assertSearchRoot("start.ini",".");
|
||||
assertSearchRoot("start.d/",".");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue