Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #11847 implement environment context xml #11859

Merged
merged 8 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
Expand Down Expand Up @@ -341,32 +342,42 @@ public ContextHandler createContextHandler(final App app) throws Exception

// prepare properties
Map<String, String> properties = new HashMap<>();

//add in properties from start mechanism
properties.putAll(getProperties());
properties.putAll(app.getProperties());

// Handle a context XML file
if (FileID.isXml(path))
Object context = null;
janbartel marked this conversation as resolved.
Show resolved Hide resolved

//add in environment-specific properties
String env = app.getEnvironmentName() == null ? "" : app.getEnvironmentName();
Path envProperties = app.getPath().getParent().resolve(env + ".properties");
if (Files.exists(envProperties))
{
XmlConfiguration xmlc = new XmlConfiguration(ResourceFactory.of(this).newResource(path), null, properties)
try (InputStream stream = Files.newInputStream(envProperties))
{
@Override
public void initializeDefaults(Object context)
{
super.initializeDefaults(context);
ContextProvider.this.initializeContextHandler(context, path, properties);
}
};
Properties p = new Properties();
p.load(stream);
p.stringPropertyNames().forEach(k -> properties.put(k, p.getProperty(k)));
}

xmlc.getIdMap().put("Environment", environment);
xmlc.setJettyStandardIdsAndProperties(getDeploymentManager().getServer(), path);
String str = properties.get(Deployable.ENVIRONMENT_XML);
if (!StringUtil.isEmpty(str))
{
Path envXmlPath = Paths.get(str);
if (!envXmlPath.isAbsolute())
envXmlPath = getMonitoredDirResource().getPath().getParent().resolve(envXmlPath);

// If it is a core context environment, then look for a classloader
ClassLoader coreContextClassLoader = Environment.CORE.equals(environment) ? findCoreContextClassLoader(path) : null;
if (coreContextClassLoader != null)
Thread.currentThread().setContextClassLoader(coreContextClassLoader);
context = applyXml(null, envXmlPath, env, properties);
}
}

// Create the context by running the configuration
Object context = xmlc.configure();
//add in properties specific to the deployable
properties.putAll(app.getProperties());

// Handle a context XML file
if (FileID.isXml(path))
{
context = applyXml(context, path, env, properties);

// Look for the contextHandler itself
ContextHandler contextHandler = null;
Expand All @@ -382,27 +393,33 @@ else if (context instanceof Supplier<?> supplier)
throw new IllegalStateException("Unknown context type of " + context);

// Set the classloader if we have a coreContextClassLoader
ClassLoader coreContextClassLoader = Environment.CORE.equals(environment) ? findCoreContextClassLoader(path) : null;
if (coreContextClassLoader != null)
contextHandler.setClassLoader(coreContextClassLoader);

return contextHandler;
}

// Otherwise it must be a directory or an archive
else if (!Files.isDirectory(path) && !FileID.isWebArchive(path))
{
throw new IllegalStateException("unable to create ContextHandler for " + app);
}

// Build the web application
String contextHandlerClassName = (String)environment.getAttribute("contextHandlerClass");
if (StringUtil.isBlank(contextHandlerClassName))
throw new IllegalStateException("No ContextHandler classname for " + app);
Class<?> contextHandlerClass = Loader.loadClass(contextHandlerClassName);
if (contextHandlerClass == null)
throw new IllegalStateException("Unknown ContextHandler class " + contextHandlerClassName + " for " + app);

Object context = contextHandlerClass.getDeclaredConstructor().newInstance();
properties.put(Deployable.WAR, path.toString());
// Build the web application if necessary
if (context == null)
{
String contextHandlerClassName = (String)environment.getAttribute("contextHandlerClass");
if (StringUtil.isBlank(contextHandlerClassName))
throw new IllegalStateException("No ContextHandler classname for " + app);
Class<?> contextHandlerClass = Loader.loadClass(contextHandlerClassName);
if (contextHandlerClass == null)
throw new IllegalStateException("Unknown ContextHandler class " + contextHandlerClassName + " for " + app);

context = contextHandlerClass.getDeclaredConstructor().newInstance();
properties.put(Deployable.WAR, path.toString());
}

return initializeContextHandler(context, path, properties);
}
finally
Expand All @@ -411,6 +428,39 @@ else if (!Files.isDirectory(path) && !FileID.isWebArchive(path))
}
}

protected Object applyXml(Object context, Path xml, String environment, Map<String, String> properties) throws Exception
{
if (!FileID.isXml(xml))
return null;


XmlConfiguration xmlc = new XmlConfiguration(ResourceFactory.of(this).newResource(xml), null, properties)
{
@Override
public void initializeDefaults(Object context)
{
super.initializeDefaults(context);
ContextProvider.this.initializeContextHandler(context, xml, properties);
}
};

xmlc.getIdMap().put("Environment", environment);
xmlc.setJettyStandardIdsAndProperties(getDeploymentManager().getServer(), xml);

// If it is a core context environment, then look for a classloader
ClassLoader coreContextClassLoader = Environment.CORE.equals(environment) ? findCoreContextClassLoader(xml) : null;
if (coreContextClassLoader != null)
Thread.currentThread().setContextClassLoader(coreContextClassLoader);

// Create or configure the context
if (context == null)
return xmlc.configure();

return xmlc.configure(context);


}

protected ClassLoader findCoreContextClassLoader(Path path) throws IOException
{
Path webapps = path.getParent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.time.Duration;
import java.util.HashMap;
import java.util.List;
Expand All @@ -26,10 +28,12 @@
import org.eclipse.jetty.deploy.AppProvider;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.deploy.test.XmlConfiguredJetty;
import org.eclipse.jetty.server.Deployable;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenPaths;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.eclipse.jetty.util.Scanner;
Expand All @@ -43,6 +47,7 @@

import static org.awaitility.Awaitility.await;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -77,7 +82,10 @@ public void setupEnvironment() throws Exception

// Should not throw an Exception
jetty.load();
}

public void startJetty() throws Exception
{
// Start it
jetty.start();
}
Expand All @@ -89,9 +97,46 @@ public void teardownEnvironment() throws Exception
}

@Test
public void testStartupContext()
public void testStartupContext() throws Exception
{
startJetty();

// Check Server for Handlers
jetty.assertContextHandlerExists("/bar");

}

@Test
public void testStartupWithRelativeEnvironmentContext() throws Exception
{
Path jettyBase = jetty.getJettyBasePath();
Path propsFile = Files.writeString(jettyBase.resolve("webapps/core.properties"), Deployable.ENVIRONMENT_XML + " = etc/core-context.xml", StandardOpenOption.CREATE_NEW);
assertTrue(Files.exists(propsFile));
Files.copy(MavenPaths.findTestResourceFile("etc/core-context.xml"), jettyBase.resolve("etc/core-context.xml"), StandardCopyOption.REPLACE_EXISTING);

startJetty();

//check environment context xml was applied to the produced context
ContextHandler context = jetty.getContextHandler("/bar");
assertNotNull(context);
assertThat(context.getAttribute("somename"), equalTo("somevalue"));

}

@Test
public void testStartupWithAbsoluteEnvironmentContext() throws Exception
{
Path jettyBase = jetty.getJettyBasePath();
Path propsFile = Files.writeString(jettyBase.resolve("webapps/core.properties"), Deployable.ENVIRONMENT_XML + " = " +
MavenPaths.findTestResourceFile("etc/core-context.xml"), StandardOpenOption.CREATE_NEW);
assertTrue(Files.exists(propsFile));
Files.copy(MavenPaths.findTestResourceFile("etc/core-context.xml"), jettyBase.resolve("etc/core-context.xml"), StandardCopyOption.REPLACE_EXISTING);

startJetty();

//check environment context xml was applied to the produced context
ContextHandler context = jetty.getContextHandler("/bar");
assertNotNull(context);
assertThat(context.getAttribute("somename"), equalTo("somevalue"));
}
}
22 changes: 22 additions & 0 deletions jetty-core/jetty-deploy/src/test/resources/etc/core-context.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- // -->
<!-- // ======================================================================== -->
<!-- // Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. -->
<!-- // -->
<!-- // This program and the accompanying materials are made available under the -->
<!-- // terms of the Eclipse Public License v. 2.0 which is available at -->
<!-- // https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -->
<!-- // which is available at https://www.apache.org/licenses/LICENSE-2.0. -->
<!-- // -->
<!-- // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -->
<!-- // ======================================================================== -->
<!-- // -->

<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://eclipse.dev/jetty/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
<Set name="contextPath">/global</Set>
<Call name="setAttribute">
<Arg>somename</Arg>
<Arg>somevalue</Arg>
</Call>
</Configure>
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public interface Deployable
String CONTEXT_PATH = "jetty.deploy.contextPath";
String DEFAULTS_DESCRIPTOR = "jetty.deploy.defaultsDescriptor";
String ENVIRONMENT = "environment";
String ENVIRONMENT_XML = "jetty.deploy.environmentXml";
String EXTRACT_WARS = "jetty.deploy.extractWars";
String PARENT_LOADER_PRIORITY = "jetty.deploy.parentLoaderPriority";
String SCI_EXCLUSION_PATTERN = "jetty.deploy.servletContainerInitializerExclusionPattern";
Expand Down
Loading