From 77f7135feb4ef2f645b461dc4e3c1312e776cff3 Mon Sep 17 00:00:00 2001 From: Simon Oakes Date: Thu, 30 Jul 2026 12:08:30 +0100 Subject: [PATCH 1/2] Fix velocity path resolution --- .../renderers/velocity/VelocityRendering.java | 55 +++++----- .../lda/restlets/RouterRestlet.java | 2 +- .../velocity/VelocityRenderingTest.java | 102 ++++++++++++++++++ 3 files changed, 133 insertions(+), 26 deletions(-) create mode 100644 elda-lda/src/test/java/com/epimorphics/lda/renderers/velocity/VelocityRenderingTest.java diff --git a/elda-lda/src/main/java/com/epimorphics/lda/renderers/velocity/VelocityRendering.java b/elda-lda/src/main/java/com/epimorphics/lda/renderers/velocity/VelocityRendering.java index 67db97e87..e8fa134ec 100644 --- a/elda-lda/src/main/java/com/epimorphics/lda/renderers/velocity/VelocityRendering.java +++ b/elda-lda/src/main/java/com/epimorphics/lda/renderers/velocity/VelocityRendering.java @@ -39,6 +39,7 @@ import java.io.*; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Properties; @@ -205,7 +206,7 @@ protected void render(OutputStream os) { * @return A new Velocity engine */ public VelocityEngine createVelocityEngine() { - List velocityPath = expandVelocityPath(bindings); + List velocityPath = expandVelocityPath(bindings, System.getenv(VELOCITY_PATH_ENV_VAR)); Properties p = getProperties(velocityPath); VelocityEngine ve = new VelocityEngine(); @@ -232,51 +233,55 @@ public VelocityEngine createVelocityEngine() { * * @return An array of expanded file paths or other URLs where we will search for Velocity assets */ - protected List expandVelocityPath(Bindings b) { + public static List expandVelocityPath(Bindings b, String envRoot) { List roots = new ArrayList<>(); - String userRootPath = b.getAsString(VELOCITY_PATH_CONFIG_PARAM, null); - - String rootPath = - (userRootPath == null ? "" : userRootPath + ",") - + etcPath() - + webappPath() - + defaultVelocityRoot(); - - for (String pathEntry : StringUtils.split(rootPath, ",")) { - pathEntry = StringUtils.trim(pathEntry); - String pathURL = b.pathAsURL(pathEntry).toString(); - roots.add(pathURL + (pathURL.endsWith("/") ? "" : "/")); + String velocityPath = b.getAsString(VELOCITY_PATH_CONFIG_PARAM, null); + + List rawRoots = new ArrayList<>(); + if (velocityPath != null) { + Collections.addAll(rawRoots, StringUtils.split(velocityPath, ",")); + } + rawRoots.add(etcPath(b)); + rawRoots.add(webappPath()); + rawRoots.addAll(defaultVelocityRoots(envRoot)); + + for (String rawRoot : rawRoots) { + rawRoot = StringUtils.trim(rawRoot); + if (!rawRoot.isEmpty()) { + String pathURL = b.pathAsURL(rawRoot).toString(); + roots.add(pathURL + (pathURL.endsWith("/") ? "" : "/")); + } } - log.debug("rootPath '{}'", rootPath); + log.debug("rootPath '{}'", String.join(",", rawRoots)); log.debug("complete expanded path '{}'", roots); return roots; } - private String webappPath() { + private static String webappPath() { return "_error_pages/"; } - private String etcPath() { + private static String etcPath(Bindings bindings) { String context = bindings .getAsString("_rootPath", "NO_ROOTPATH") .replaceAll("/([^/]*)/.*", "$1"); String appPath = "/etc/elda/conf.d/REPLACE/_error_pages".replace("REPLACE", context); List files = new Glob().filesMatching(appPath); - return (files.size() == 0 ? "" : files.get(0)) + ","; + return (files.isEmpty() ? "" : files.getFirst().toString()); } /** * @return The default Velocity root directory, which may set by an environment variable */ - protected String defaultVelocityRoot() { - String envRoot = null; - try { - envRoot = System.getenv(VELOCITY_PATH_ENV_VAR); - } catch (SecurityException ignore) { - // not allowed to read the environment, no biggie + protected static List defaultVelocityRoots(String envRoot) { + List roots = new ArrayList<>(); + if (envRoot == null) { + roots.add(DEFAULT_VELOCITY_ROOT_PATH); + } else { + Collections.addAll(roots, envRoot.split(",")); } - return (envRoot == null) ? DEFAULT_VELOCITY_ROOT_PATH : envRoot; + return roots; } /** diff --git a/elda-lda/src/main/java/com/epimorphics/lda/restlets/RouterRestlet.java b/elda-lda/src/main/java/com/epimorphics/lda/restlets/RouterRestlet.java index b189fb236..9f8c83330 100755 --- a/elda-lda/src/main/java/com/epimorphics/lda/restlets/RouterRestlet.java +++ b/elda-lda/src/main/java/com/epimorphics/lda/restlets/RouterRestlet.java @@ -595,7 +595,7 @@ public static URI makeRequestURI(UriInfo ui, Boolean enableForwardHeaders, Strin private static final String STARTS_WITH_SCHEME = "^" + MATCHES_SCHEME + ".*"; - private static URLforResource pathAsURLFactory(final ServletContext servCon) { + public static URLforResource pathAsURLFactory(final ServletContext servCon) { return new URLforResource() { @Override public URL asResourceURL(String ePath) { diff --git a/elda-lda/src/test/java/com/epimorphics/lda/renderers/velocity/VelocityRenderingTest.java b/elda-lda/src/test/java/com/epimorphics/lda/renderers/velocity/VelocityRenderingTest.java new file mode 100644 index 000000000..5c48a3900 --- /dev/null +++ b/elda-lda/src/test/java/com/epimorphics/lda/renderers/velocity/VelocityRenderingTest.java @@ -0,0 +1,102 @@ +package com.epimorphics.lda.renderers.velocity; + +import com.epimorphics.lda.bindings.Bindings; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Files; +import java.util.List; + +import static org.junit.Assert.*; + +public class VelocityRenderingTest { + + @Test + public void expandVelocityPath_default() { + List result = new VelocityPathScenario().run(); + List expected = List.of("http://_error_pages/", "http:/velocity/"); + assertEquals(expected, result); + } + + @Test + public void expandVelocityPath_withVelocityPath_singleValue() { + List result = new VelocityPathScenario().withVelocityPath("elda/test").run(); + List expected = List.of("http://elda/test/", "http://_error_pages/", "http:/velocity/"); + assertEquals(expected, result); + } + + @Test + public void expandVelocityPath_withVelocityPath_multipleValues() { + List result = new VelocityPathScenario().withVelocityPath("elda/test,/var/velocity").run(); + List expected = List.of("http://elda/test/", "http:/var/velocity/", "http://_error_pages/", "http:/velocity/"); + assertEquals(expected, result); + } + + @Test + public void expandVelocityPath_withVelocityPath_multipleValues_withWhitespace() { + List result = new VelocityPathScenario().withVelocityPath("elda/test , /var/velocity, elda/void ").run(); + List expected = List.of("http://elda/test/", "http:/var/velocity/", "http://elda/void/", "http://_error_pages/", "http:/velocity/"); + assertEquals(expected, result); + } + + @Test + public void expandVelocityPath_withVelocityPath_multipleValues_withEmpty() { + List result = new VelocityPathScenario().withVelocityPath(", elda/test,,/var/velocity, ,elda/void").run(); + List expected = List.of("http://elda/test/", "http:/var/velocity/", "http://elda/void/", "http://_error_pages/", "http:/velocity/"); + assertEquals(expected, result); + } + + @Test + public void expandVelocityPath_withEnvVar_singleValue() { + List result = new VelocityPathScenario().withEnvVar("elda/test").run(); + List expected = List.of("http://_error_pages/", "http://elda/test/"); + assertEquals(expected, result); + } + + @Test + public void expandVelocityPath_withEnvVar_multipleValues() { + List result = new VelocityPathScenario().withEnvVar("elda/test,/var/velocity").run(); + List expected = List.of("http://_error_pages/", "http://elda/test/", "http:/var/velocity/"); + assertEquals(expected, result); + } + + @Test + public void expandVelocityPath_withEnvVar_multipleValues_withWhitespace() { + List result = new VelocityPathScenario().withEnvVar("elda/test , /var/velocity, elda/void ").run(); + List expected = List.of("http://_error_pages/", "http://elda/test/", "http:/var/velocity/", "http://elda/void/"); + assertEquals(expected, result); + } + + @Test + public void expandVelocityPath_withEnvVar_multipleValues_withEmpty() { + List result = new VelocityPathScenario().withEnvVar(", elda/test,,/var/velocity, ,elda/void").run(); + List expected = List.of("http://_error_pages/", "http://elda/test/", "http:/var/velocity/", "http://elda/void/"); + assertEquals(expected, result); + } + + private class VelocityPathScenario { + private Bindings b = new Bindings(u -> { + try { + return new URL("http://" + u); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + }); + private String envRoot; + + public VelocityPathScenario withVelocityPath(String value) { + b.put("_velocityPath", value); return this; + } + + public VelocityPathScenario withEnvVar(String value) { + envRoot = value; return this; + } + + public List run() { + return VelocityRendering.expandVelocityPath(b, envRoot); + } + } +} \ No newline at end of file From cedca2ed575546b0399cb952ab25a7d69a75ece2 Mon Sep 17 00:00:00 2001 From: Simon Oakes Date: Fri, 31 Jul 2026 10:10:19 +0100 Subject: [PATCH 2/2] Fix velocity path env var resolution --- .../java/com/epimorphics/lda/Version.java | 2 +- .../renderers/velocity/VelocityRendering.java | 5 ++-- .../velocity/VelocityRenderingTest.java | 23 ++++++++----------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/elda-lda/src/main/java/com/epimorphics/lda/Version.java b/elda-lda/src/main/java/com/epimorphics/lda/Version.java index ca2e433ef..76cd109be 100644 --- a/elda-lda/src/main/java/com/epimorphics/lda/Version.java +++ b/elda-lda/src/main/java/com/epimorphics/lda/Version.java @@ -17,5 +17,5 @@ * */ public interface Version { - public final String string = "3.0.2"; + public final String string = "3.0.4-SNAPSHOT"; } diff --git a/elda-lda/src/main/java/com/epimorphics/lda/renderers/velocity/VelocityRendering.java b/elda-lda/src/main/java/com/epimorphics/lda/renderers/velocity/VelocityRendering.java index e8fa134ec..e70fccb41 100644 --- a/elda-lda/src/main/java/com/epimorphics/lda/renderers/velocity/VelocityRendering.java +++ b/elda-lda/src/main/java/com/epimorphics/lda/renderers/velocity/VelocityRendering.java @@ -63,7 +63,7 @@ public class VelocityRendering /** * The default place we look for Velocity files */ - public static final String DEFAULT_VELOCITY_ROOT_PATH = "/velocity/"; + public static final String DEFAULT_VELOCITY_ROOT_PATH = "velocity/"; /** * The configuration parameter which sets an alternative location for Velocity templates etc @@ -242,7 +242,6 @@ public static List expandVelocityPath(Bindings b, String envRoot) { Collections.addAll(rawRoots, StringUtils.split(velocityPath, ",")); } rawRoots.add(etcPath(b)); - rawRoots.add(webappPath()); rawRoots.addAll(defaultVelocityRoots(envRoot)); for (String rawRoot : rawRoots) { @@ -276,7 +275,7 @@ private static String etcPath(Bindings bindings) { protected static List defaultVelocityRoots(String envRoot) { List roots = new ArrayList<>(); if (envRoot == null) { - roots.add(DEFAULT_VELOCITY_ROOT_PATH); + roots.add(webappPath() + DEFAULT_VELOCITY_ROOT_PATH); } else { Collections.addAll(roots, envRoot.split(",")); } diff --git a/elda-lda/src/test/java/com/epimorphics/lda/renderers/velocity/VelocityRenderingTest.java b/elda-lda/src/test/java/com/epimorphics/lda/renderers/velocity/VelocityRenderingTest.java index 5c48a3900..9feded025 100644 --- a/elda-lda/src/test/java/com/epimorphics/lda/renderers/velocity/VelocityRenderingTest.java +++ b/elda-lda/src/test/java/com/epimorphics/lda/renderers/velocity/VelocityRenderingTest.java @@ -3,11 +3,8 @@ import com.epimorphics.lda.bindings.Bindings; import org.junit.Test; -import java.io.File; -import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.nio.file.Files; import java.util.List; import static org.junit.Assert.*; @@ -17,70 +14,70 @@ public class VelocityRenderingTest { @Test public void expandVelocityPath_default() { List result = new VelocityPathScenario().run(); - List expected = List.of("http://_error_pages/", "http:/velocity/"); + List expected = List.of("file:_error_pages/velocity/"); assertEquals(expected, result); } @Test public void expandVelocityPath_withVelocityPath_singleValue() { List result = new VelocityPathScenario().withVelocityPath("elda/test").run(); - List expected = List.of("http://elda/test/", "http://_error_pages/", "http:/velocity/"); + List expected = List.of("file:elda/test/", "file:_error_pages/velocity/"); assertEquals(expected, result); } @Test public void expandVelocityPath_withVelocityPath_multipleValues() { List result = new VelocityPathScenario().withVelocityPath("elda/test,/var/velocity").run(); - List expected = List.of("http://elda/test/", "http:/var/velocity/", "http://_error_pages/", "http:/velocity/"); + List expected = List.of("file:elda/test/", "file:/var/velocity/", "file:_error_pages/velocity/"); assertEquals(expected, result); } @Test public void expandVelocityPath_withVelocityPath_multipleValues_withWhitespace() { List result = new VelocityPathScenario().withVelocityPath("elda/test , /var/velocity, elda/void ").run(); - List expected = List.of("http://elda/test/", "http:/var/velocity/", "http://elda/void/", "http://_error_pages/", "http:/velocity/"); + List expected = List.of("file:elda/test/", "file:/var/velocity/", "file:elda/void/", "file:_error_pages/velocity/"); assertEquals(expected, result); } @Test public void expandVelocityPath_withVelocityPath_multipleValues_withEmpty() { List result = new VelocityPathScenario().withVelocityPath(", elda/test,,/var/velocity, ,elda/void").run(); - List expected = List.of("http://elda/test/", "http:/var/velocity/", "http://elda/void/", "http://_error_pages/", "http:/velocity/"); + List expected = List.of("file:elda/test/", "file:/var/velocity/", "file:elda/void/", "file:_error_pages/velocity/"); assertEquals(expected, result); } @Test public void expandVelocityPath_withEnvVar_singleValue() { List result = new VelocityPathScenario().withEnvVar("elda/test").run(); - List expected = List.of("http://_error_pages/", "http://elda/test/"); + List expected = List.of("file:elda/test/"); assertEquals(expected, result); } @Test public void expandVelocityPath_withEnvVar_multipleValues() { List result = new VelocityPathScenario().withEnvVar("elda/test,/var/velocity").run(); - List expected = List.of("http://_error_pages/", "http://elda/test/", "http:/var/velocity/"); + List expected = List.of("file:elda/test/", "file:/var/velocity/"); assertEquals(expected, result); } @Test public void expandVelocityPath_withEnvVar_multipleValues_withWhitespace() { List result = new VelocityPathScenario().withEnvVar("elda/test , /var/velocity, elda/void ").run(); - List expected = List.of("http://_error_pages/", "http://elda/test/", "http:/var/velocity/", "http://elda/void/"); + List expected = List.of("file:elda/test/", "file:/var/velocity/", "file:elda/void/"); assertEquals(expected, result); } @Test public void expandVelocityPath_withEnvVar_multipleValues_withEmpty() { List result = new VelocityPathScenario().withEnvVar(", elda/test,,/var/velocity, ,elda/void").run(); - List expected = List.of("http://_error_pages/", "http://elda/test/", "http:/var/velocity/", "http://elda/void/"); + List expected = List.of("file:elda/test/", "file:/var/velocity/", "file:elda/void/"); assertEquals(expected, result); } private class VelocityPathScenario { private Bindings b = new Bindings(u -> { try { - return new URL("http://" + u); + return new URL("file:" + u); } catch (MalformedURLException e) { throw new RuntimeException(e); }