* Support root base or home for quickstart #2446 Signed-off-by: Greg Wilkins <gregw@webtide.com> * Issue #2446 - Root as base for quickstart + Adding more tests for differences we have to resolve with windows vs linux root path differences. and URI's that have an authority vs those without an authority. without authority examples: file:/code/ file:/C:/code/ with authority examples: file:///code/ file:///C:/code/ Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com> * Using the canonical URI passes all the tests on linux, but I still have some concerns with the whole approach Signed-off-by: Greg Wilkins <gregw@webtide.com> * minor cleanups Signed-off-by: Greg Wilkins <gregw@webtide.com> * Handle windows URIs Because a windows like `file:///F:/` has a path of `/F:/`, then it is OK to strip the trailing `/`, so the expected normalized value can be `file:///F:`. Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
parent
5515e13649
commit
e59d6fa2c0
|
@ -63,7 +63,7 @@ public class AttributeNormalizer
|
||||||
{
|
{
|
||||||
private static final Logger LOG = Log.getLogger(AttributeNormalizer.class);
|
private static final Logger LOG = Log.getLogger(AttributeNormalizer.class);
|
||||||
private static final Pattern __propertyPattern = Pattern.compile("(?<=[^$]|^)\\$\\{([^}]*)\\}");
|
private static final Pattern __propertyPattern = Pattern.compile("(?<=[^$]|^)\\$\\{([^}]*)\\}");
|
||||||
|
|
||||||
private static class Attribute
|
private static class Attribute
|
||||||
{
|
{
|
||||||
final String key;
|
final String key;
|
||||||
|
@ -78,14 +78,15 @@ public class AttributeNormalizer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static URI toCanonicalURI(URI uri)
|
public static URI toCanonicalURI(URI uri)
|
||||||
{
|
{
|
||||||
uri = uri.normalize();
|
uri = uri.normalize();
|
||||||
String ascii = uri.toASCIIString();
|
String path = uri.getPath();
|
||||||
if (ascii.endsWith("/"))
|
if (path!=null && path.length()>1 && path.endsWith("/"))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
String ascii = uri.toASCIIString();
|
||||||
uri = new URI(ascii.substring(0,ascii.length()-1));
|
uri = new URI(ascii.substring(0,ascii.length()-1));
|
||||||
}
|
}
|
||||||
catch(URISyntaxException e)
|
catch(URISyntaxException e)
|
||||||
|
@ -96,7 +97,16 @@ public class AttributeNormalizer
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Path toCanonicalPath(String path)
|
public static String toCanonicalURI(String uri)
|
||||||
|
{
|
||||||
|
if (uri!=null && uri.length()>1 && uri.endsWith("/"))
|
||||||
|
{
|
||||||
|
return uri.substring(0,uri.length()-1);
|
||||||
|
}
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Path toCanonicalPath(String path)
|
||||||
{
|
{
|
||||||
if (path == null)
|
if (path == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -148,8 +158,8 @@ public class AttributeNormalizer
|
||||||
|
|
||||||
public URIAttribute(String key, URI uri, int weight)
|
public URIAttribute(String key, URI uri, int weight)
|
||||||
{
|
{
|
||||||
super(key,uri.toASCIIString(),weight);
|
super(key,toCanonicalURI(uri.toASCIIString()),weight);
|
||||||
this.uri = uri;
|
this.uri = toCanonicalURI(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -198,17 +208,6 @@ public class AttributeNormalizer
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void add(List<PathAttribute>paths,List<URIAttribute> uris,String key,int weight)
|
|
||||||
{
|
|
||||||
String value = System.getProperty(key);
|
|
||||||
if (value!=null)
|
|
||||||
{
|
|
||||||
Path path = toCanonicalPath(value);
|
|
||||||
paths.add(new PathAttribute(key,path,weight));
|
|
||||||
uris.add(new URIAttribute(key+".uri",toCanonicalURI(path.toUri()),weight));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private URI warURI;
|
private URI warURI;
|
||||||
private Map<String,Attribute> attributes = new HashMap<>();
|
private Map<String,Attribute> attributes = new HashMap<>();
|
||||||
private List<PathAttribute> paths = new ArrayList<>();
|
private List<PathAttribute> paths = new ArrayList<>();
|
||||||
|
@ -223,10 +222,10 @@ public class AttributeNormalizer
|
||||||
if (!warURI.isAbsolute())
|
if (!warURI.isAbsolute())
|
||||||
throw new IllegalArgumentException("WAR URI is not absolute: " + warURI);
|
throw new IllegalArgumentException("WAR URI is not absolute: " + warURI);
|
||||||
|
|
||||||
add(paths,uris,"jetty.base",9);
|
addSystemProperty("jetty.base", 9);
|
||||||
add(paths,uris,"jetty.home",8);
|
addSystemProperty("jetty.home", 8);
|
||||||
add(paths,uris,"user.home",7);
|
addSystemProperty("user.home", 7);
|
||||||
add(paths,uris,"user.dir",6);
|
addSystemProperty("user.dir", 6);
|
||||||
|
|
||||||
if (warURI.getScheme().equalsIgnoreCase("file"))
|
if (warURI.getScheme().equalsIgnoreCase("file"))
|
||||||
paths.add(new PathAttribute("WAR.path",toCanonicalPath(new File(warURI).toString()),10));
|
paths.add(new PathAttribute("WAR.path",toCanonicalPath(new File(warURI).toString()),10));
|
||||||
|
@ -244,6 +243,17 @@ public class AttributeNormalizer
|
||||||
{
|
{
|
||||||
LOG.debug(attr.toString());
|
LOG.debug(attr.toString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSystemProperty(String key, int weight)
|
||||||
|
{
|
||||||
|
String value = System.getProperty(key);
|
||||||
|
if (value!=null)
|
||||||
|
{
|
||||||
|
Path path = toCanonicalPath(value);
|
||||||
|
paths.add(new PathAttribute(key,path,weight));
|
||||||
|
uris.add(new URIAttribute(key+".uri",path.toUri(),weight));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,35 +334,33 @@ public class AttributeNormalizer
|
||||||
{
|
{
|
||||||
for (URIAttribute a : uris)
|
for (URIAttribute a : uris)
|
||||||
{
|
{
|
||||||
try
|
if (uri.compareTo(a.uri)==0)
|
||||||
{
|
return String.format("${%s}",a.key);
|
||||||
if (uri.compareTo(a.uri)==0)
|
|
||||||
return String.format("${%s}",a.key);
|
|
||||||
|
|
||||||
if (!a.uri.getScheme().equalsIgnoreCase(uri.getScheme()))
|
if (!a.uri.getScheme().equalsIgnoreCase(uri.getScheme()))
|
||||||
continue;
|
continue;
|
||||||
if (a.uri.getHost()==null && uri.getHost()!=null)
|
if (a.uri.getHost()==null && uri.getHost()!=null)
|
||||||
continue;
|
continue;
|
||||||
if (a.uri.getHost()!=null && !a.uri.getHost().equals(uri.getHost()))
|
if (a.uri.getHost()!=null && !a.uri.getHost().equals(uri.getHost()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (a.uri.getPath().equals(uri.getPath()))
|
String aPath = a.uri.getPath();
|
||||||
return a.value;
|
String uPath = uri.getPath();
|
||||||
|
if (aPath.equals(uPath))
|
||||||
|
return a.value;
|
||||||
|
|
||||||
if (!uri.getPath().startsWith(a.uri.getPath()))
|
if (!uPath.startsWith(aPath))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
String s = uri.getPath().substring(a.uri.getPath().length());
|
if (uPath.length()==aPath.length())
|
||||||
|
return String.format("${%s}",a.key);
|
||||||
|
|
||||||
|
String s = uPath.substring(aPath.length());
|
||||||
|
if (s.length()>0 && s.charAt(0)!='/')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return String.format("${%s}%s",a.key,s);
|
||||||
|
|
||||||
if (s.charAt(0)!='/')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return String.format("${%s}%s",a.key,new URI(s).toASCIIString());
|
|
||||||
}
|
|
||||||
catch(URISyntaxException e)
|
|
||||||
{
|
|
||||||
LOG.ignore(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return uri.toASCIIString();
|
return uri.toASCIIString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,16 @@ public class AttributeNormalizerTest
|
||||||
|
|
||||||
data.add(new Object[]{arch, title, env});
|
data.add(new Object[]{arch, title, env});
|
||||||
|
|
||||||
|
// ------
|
||||||
|
title = "Old Setup";
|
||||||
|
|
||||||
|
env = new HashMap<>();
|
||||||
|
env.put("jetty.home", asTargetPath(title,"jetty-distro"));
|
||||||
|
env.put("jetty.base", asTargetPath(title,"jetty-distro"));
|
||||||
|
env.put("WAR", asTargetPath(title,"jetty-distro/webapps/FOO"));
|
||||||
|
|
||||||
|
data.add(new Object[]{arch, title, env});
|
||||||
|
|
||||||
// ------
|
// ------
|
||||||
// This puts the jetty.home inside of the jetty.base
|
// This puts the jetty.home inside of the jetty.base
|
||||||
title = "Overlap Setup";
|
title = "Overlap Setup";
|
||||||
|
@ -82,6 +92,17 @@ public class AttributeNormalizerTest
|
||||||
env.put("WAR", asTargetPath(title,"app%2Fnasty/base/webapps/FOO"));
|
env.put("WAR", asTargetPath(title,"app%2Fnasty/base/webapps/FOO"));
|
||||||
|
|
||||||
data.add(new Object[]{arch, title, env});
|
data.add(new Object[]{arch, title, env});
|
||||||
|
|
||||||
|
// ------
|
||||||
|
title = "Root Path Setup";
|
||||||
|
env = new HashMap<>();
|
||||||
|
Path rootPath = MavenTestingUtils.getTargetPath().getRoot();
|
||||||
|
env.put("jetty.home", rootPath.toString());
|
||||||
|
env.put("jetty.base", rootPath.toString());
|
||||||
|
env.put("WAR", rootPath.resolve("webapps/root").toString());
|
||||||
|
|
||||||
|
data.add(new Object[]{arch, title, env});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,8 +117,8 @@ public class AttributeNormalizerTest
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> oldValues = new HashMap<>();
|
private Map<String, String> oldValues = new HashMap<>();
|
||||||
private final String jettyHome;
|
private final Path jettyHome;
|
||||||
private final String jettyBase;
|
private final Path jettyBase;
|
||||||
private final String war;
|
private final String war;
|
||||||
private final String arch;
|
private final String arch;
|
||||||
private final String title;
|
private final String title;
|
||||||
|
@ -118,8 +139,8 @@ public class AttributeNormalizerTest
|
||||||
});
|
});
|
||||||
|
|
||||||
// Grab specific values of interest in general
|
// Grab specific values of interest in general
|
||||||
jettyHome = env.get("jetty.home");
|
jettyHome = new File(env.get("jetty.home")).toPath().toAbsolutePath();
|
||||||
jettyBase = env.get("jetty.base");
|
jettyBase = new File(env.get("jetty.base")).toPath().toAbsolutePath();
|
||||||
war = env.get("WAR");
|
war = env.get("WAR");
|
||||||
|
|
||||||
// Set environment (skipping null and WAR)
|
// Set environment (skipping null and WAR)
|
||||||
|
@ -176,42 +197,79 @@ public class AttributeNormalizerTest
|
||||||
public void testNormalizeJettyBaseAsFile()
|
public void testNormalizeJettyBaseAsFile()
|
||||||
{
|
{
|
||||||
// Normalize jetty.base as File path
|
// Normalize jetty.base as File path
|
||||||
assertNormalize(new File(jettyBase), "${jetty.base}");
|
assertNormalize(jettyBase.toFile(), "${jetty.base}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNormalizeJettyHomeAsFile()
|
public void testNormalizeJettyHomeAsFile()
|
||||||
{
|
{
|
||||||
// Normalize jetty.home as File path
|
// Normalize jetty.home as File path
|
||||||
assertNormalize(new File(jettyHome), "${jetty.home}");
|
String expected = jettyBase.equals(jettyHome)?"${jetty.base}":"${jetty.home}";
|
||||||
|
assertNormalize(jettyHome.toFile(), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNormalizeJettyBaseAsPath()
|
||||||
|
{
|
||||||
|
// Normalize jetty.base as File path
|
||||||
|
assertNormalize(jettyBase, "${jetty.base}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNormalizeJettyHomeAsPath()
|
||||||
|
{
|
||||||
|
// Normalize jetty.home as File path
|
||||||
|
String expected = jettyBase.equals(jettyHome)?"${jetty.base}":"${jetty.home}";
|
||||||
|
assertNormalize(jettyHome, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNormalizeJettyBaseAsURI()
|
public void testNormalizeJettyBaseAsURI_WithAuthority()
|
||||||
{
|
{
|
||||||
// Normalize jetty.base as URI path
|
// Normalize jetty.base as URI path
|
||||||
assertNormalize(new File(jettyBase).toURI(), "${jetty.base.uri}");
|
// Path.toUri() typically includes an URI authority
|
||||||
|
assertNormalize(jettyBase.toUri(), "${jetty.base.uri}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNormalizeJettyBaseAsURI_WithoutAuthority()
|
||||||
|
{
|
||||||
|
// Normalize jetty.base as URI path
|
||||||
|
// File.toURI() typically DOES NOT include an URI authority
|
||||||
|
assertNormalize(jettyBase.toFile().toURI(), "${jetty.base.uri}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNormalizeJettyHomeAsURI()
|
public void testNormalizeJettyHomeAsURI_WithAuthority()
|
||||||
|
{
|
||||||
|
// Normalize jetty.home as URI path
|
||||||
|
String expected = jettyBase.equals(jettyHome)?"${jetty.base.uri}":"${jetty.home.uri}";
|
||||||
|
|
||||||
|
// Path.toUri() typically includes an URI authority
|
||||||
|
assertNormalize(jettyHome.toUri(), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNormalizeJettyHomeAsURI_WithoutAuthority()
|
||||||
{
|
{
|
||||||
// Normalize jetty.home as URI path
|
// Normalize jetty.home as URI path
|
||||||
assertNormalize(new File(jettyHome).toURI(), "${jetty.home.uri}");
|
String expected = jettyBase.equals(jettyHome)?"${jetty.base.uri}":"${jetty.home.uri}";
|
||||||
|
// File.toURI() typically DOES NOT include an URI authority
|
||||||
|
assertNormalize(jettyHome.toFile().toURI(), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandJettyBase()
|
public void testExpandJettyBase()
|
||||||
{
|
{
|
||||||
// Expand jetty.base
|
// Expand jetty.base
|
||||||
assertExpandPath("${jetty.base}", jettyBase);
|
assertExpandPath("${jetty.base}", jettyBase.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandJettyHome()
|
public void testExpandJettyHome()
|
||||||
{
|
{
|
||||||
// Expand jetty.home
|
// Expand jetty.home
|
||||||
assertExpandPath("${jetty.home}", jettyHome);
|
assertExpandPath("${jetty.home}", jettyHome.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2018 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.quickstart;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
|
public class AttributeNormalizer_ToCanonicalUriTest
|
||||||
|
{
|
||||||
|
@Parameterized.Parameters(name = "[{index}] {0} - {1}")
|
||||||
|
public static List<Object[]> data()
|
||||||
|
{
|
||||||
|
List<Object[]> data = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
// root without authority
|
||||||
|
data.add(new String[]{ "file:/", "file:/" });
|
||||||
|
data.add(new String[]{ "file:/F:/", "file:/F:" });
|
||||||
|
|
||||||
|
// root with empty authority
|
||||||
|
data.add(new String[]{ "file:///", "file:///" });
|
||||||
|
data.add(new String[]{ "file:///F:/", "file:///F:" });
|
||||||
|
|
||||||
|
// deep directory - no authority
|
||||||
|
data.add(new String[]{ "file:/home/user/code/", "file:/home/user/code" });
|
||||||
|
data.add(new String[]{ "file:/C:/code/", "file:/C:/code" });
|
||||||
|
|
||||||
|
// deep directory - with authority
|
||||||
|
data.add(new String[]{ "file:///home/user/code/", "file:///home/user/code" });
|
||||||
|
data.add(new String[]{ "file:///C:/code/", "file:///C:/code" });
|
||||||
|
|
||||||
|
// Some non-file tests
|
||||||
|
data.add(new String[]{ "http://webtide.com/", "http://webtide.com/" });
|
||||||
|
data.add(new String[]{ "http://webtide.com/cometd/", "http://webtide.com/cometd" });
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parameterized.Parameter
|
||||||
|
public String input;
|
||||||
|
|
||||||
|
@Parameterized.Parameter(1)
|
||||||
|
public String expected;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCanonicalURI()
|
||||||
|
{
|
||||||
|
URI inputURI = URI.create(input);
|
||||||
|
URI actual = AttributeNormalizer.toCanonicalURI(inputURI);
|
||||||
|
assertThat(input, actual.toASCIIString(), is(expected));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue