Skip to content

Commit

Permalink
Fix #6565 Deploy Symlinked applications
Browse files Browse the repository at this point in the history
Fix #6565 Deploy Symlinked applications by treating extracting context name (which becomes the default context path) from the base resource and then following aliases, so that base resource will not be an alias.   Added warning in ContextHandler if the base resource is an alias that we may not support this in future releases.

Signed-off-by: Greg Wilkins <gregw@webtide.com>
  • Loading branch information
gregw committed Aug 2, 2021
1 parent 6201d3b commit e8fe135
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 41 deletions.
Expand Up @@ -22,6 +22,7 @@
import org.eclipse.jetty.deploy.util.FileID;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
Expand Down Expand Up @@ -265,8 +266,18 @@ public ContextHandler createContextHandler(final App app) throws Exception
if (!resource.exists())
throw new IllegalStateException("App resource does not exist " + resource);

String context = file.getName();
final String contextName = file.getName();

// Resource aliases (after getting name) to ensure baseResource is not an alias
if (resource.isAlias())
{
resource = Resource.newResource(resource.getAlias());
file = resource.getFile().toPath().toRealPath().toFile();
if (!resource.exists())
throw new IllegalStateException("App resource does not exist " + resource);
}

// Handle a context XML file
if (resource.exists() && FileID.isXmlFile(file))
{
XmlConfiguration xmlc = new XmlConfiguration(resource)
Expand All @@ -276,11 +287,15 @@ public void initializeDefaults(Object context)
{
super.initializeDefaults(context);

// If the XML created object is a ContextHandler
if (context instanceof ContextHandler)
// Initialize the context path prior to running context XML
initializeContextPath((ContextHandler)context, contextName, true);

// If it is a webapp
if (context instanceof WebAppContext)
{
WebAppContext webapp = (WebAppContext)context;
initializeWebAppContextDefaults(webapp);
}
// initialize other defaults prior to running context XML
initializeWebAppContextDefaults((WebAppContext)context);
}
};

Expand All @@ -290,54 +305,62 @@ public void initializeDefaults(Object context)
xmlc.getProperties().putAll(getConfigurationManager().getProperties());
return (ContextHandler)xmlc.configure();
}
else if (file.isDirectory())
{
// must be a directory
}
else if (FileID.isWebArchiveFile(file))
{
// Context Path is the same as the archive.
context = context.substring(0, context.length() - 4);
}
else
// Otherwise it must be a directory or an archive
else if (!file.isDirectory() && !FileID.isWebArchiveFile(file))
{
throw new IllegalStateException("unable to create ContextHandler for " + app);
}

// Ensure "/" is Not Trailing in context paths.
if (context.endsWith("/") && context.length() > 0)
{
context = context.substring(0, context.length() - 1);
}

// Start building the webapplication
// Build the web application
WebAppContext webAppContext = new WebAppContext();
webAppContext.setDisplayName(context);
webAppContext.setWar(file.getAbsolutePath());
initializeContextPath(webAppContext, contextName, !file.isDirectory());
initializeWebAppContextDefaults(webAppContext);

return webAppContext;
}

protected void initializeContextPath(ContextHandler context, String contextName, boolean stripExtension)
{
String contextPath = contextName;

// Strip any 3 char extension from non directories
if (stripExtension && contextPath.length() > 4 && contextPath.charAt(contextPath.length() - 4) == '.')
contextPath = contextPath.substring(0, contextPath.length() - 4);

// Ensure "/" is Not Trailing in context paths.
if (contextPath.endsWith("/") && contextPath.length() > 1)
contextPath = contextPath.substring(0, contextPath.length() - 1);

// special case of archive (or dir) named "root" is / context
if (context.equalsIgnoreCase("root"))
if (contextPath.equalsIgnoreCase("root"))
{
context = URIUtil.SLASH;
contextPath = URIUtil.SLASH;
}
else if (context.toLowerCase(Locale.ENGLISH).startsWith("root-"))
// handle root with virtual host form
else if (StringUtil.startsWithIgnoreCase(contextPath, "root-"))
{
int dash = context.toLowerCase(Locale.ENGLISH).indexOf('-');
String virtual = context.substring(dash + 1);
webAppContext.setVirtualHosts(new String[]{virtual});
context = URIUtil.SLASH;
int dash = contextPath.indexOf('-');
String virtual = contextPath.substring(dash + 1);
context.setVirtualHosts(virtual.split(","));
contextPath = URIUtil.SLASH;
}

// Ensure "/" is Prepended to all context paths.
if (context.charAt(0) != '/')
if (contextPath.charAt(0) != '/')
contextPath = "/" + contextPath;

// Set the display name and context Path
context.setDisplayName(contextName);
if (context instanceof WebAppContext)
{
context = "/" + context;
WebAppContext webAppContext = (WebAppContext)context;
webAppContext.setDefaultContextPath(contextPath);
}
else
{
context.setContextPath(contextPath);
}

webAppContext.setDefaultContextPath(context);
webAppContext.setWar(file.getAbsolutePath());
initializeWebAppContextDefaults(webAppContext);

return webAppContext;
}

@Override
Expand Down
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.jetty.deploy.test.XmlConfiguredJetty;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
Expand Down Expand Up @@ -124,9 +125,12 @@ public void testStartupSymlinkContext()
// Check Server for expected Handlers
jetty.assertWebAppContextsExists("/bar", "/foo", "/bob");

// Check that baseResources are not aliases
jetty.getServer().getContainedBeans(ContextHandler.class).forEach(h -> assertFalse(h.getBaseResource().isAlias()));

// Test for expected work/temp directory behaviour
File workDir = jetty.getJettyDir("workish");
assertTrue(hasJettyGeneratedPath(workDir, "bar_war"), "Should have generated directory in work directory: " + workDir);
assertTrue(hasJettyGeneratedPath(workDir, "_war-_bar"), "Should have generated directory in work directory: " + workDir);
}

@Test
Expand Down
Expand Up @@ -853,11 +853,15 @@ public void setLogger(Logger logger)
@Override
protected void doStart() throws Exception
{
_availability.set(Availability.STARTING);

if (_contextPath == null)
throw new IllegalStateException("Null contextPath");

if (getBaseResource() != null && getBaseResource().isAlias())
LOG.warn("BaseResource {} is aliased to {} in {}. May not be supported in future releases.",
getBaseResource(), getBaseResource().getAlias(), this);

_availability.set(Availability.STARTING);

if (_logger == null)
_logger = LoggerFactory.getLogger(ContextHandler.class.getName() + getLogNameSuffix());

Expand Down

0 comments on commit e8fe135

Please sign in to comment.