From 973f37c787956cdfb48e2e14ce57f56d6c3cbade Mon Sep 17 00:00:00 2001 From: Dan Cunningham Date: Fri, 17 Dec 2021 10:10:19 -0800 Subject: [PATCH] [jsscripting] Support non unix file paths Lets try this again, Fixes #11801 Signed-off-by: Dan Cunningham --- .../internal/OpenhabGraalJSScriptEngine.java | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/OpenhabGraalJSScriptEngine.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/OpenhabGraalJSScriptEngine.java index c3bdce81a46b4..b22c2793b304b 100644 --- a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/OpenhabGraalJSScriptEngine.java +++ b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/OpenhabGraalJSScriptEngine.java @@ -14,7 +14,6 @@ import static org.openhab.core.automation.module.script.ScriptEngineFactory.*; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.channels.SeekableByteChannel; @@ -66,7 +65,7 @@ public class OpenhabGraalJSScriptEngine extends InvocationInterceptingScriptEngi private static final String GLOBAL_REQUIRE = "require(\"@jsscripting-globals\");"; private static final String REQUIRE_WRAPPER_NAME = "__wraprequire__"; // final CommonJS search path for our library - private static final Path LOCAL_NODE_PATH = Paths.get(File.separator + "node_modules"); + private static final Path NODE_DIR = Paths.get("node_modules"); // these fields start as null because they are populated on first use private @NonNullByDefault({}) String engineIdentifier; @@ -116,10 +115,11 @@ public SeekableByteChannel newByteChannel(Path path, Set o if (scriptDependencyListener != null) { scriptDependencyListener.accept(path.toString()); } + if (path.toString().endsWith(".js")) { SeekableByteChannel sbc = null; - if (path.startsWith(LOCAL_NODE_PATH)) { - InputStream is = getClass().getResourceAsStream(path.toString()); + if (isRootNodePath(path)) { + InputStream is = getClass().getResourceAsStream(nodeFileToResource(path)); if (is == null) { throw new IOException("Could not read " + path.toString()); } @@ -137,8 +137,8 @@ public SeekableByteChannel newByteChannel(Path path, Set o @Override public void checkAccess(Path path, Set modes, LinkOption... linkOptions) throws IOException { - if (path.startsWith(LOCAL_NODE_PATH)) { - if (getClass().getResource(path.toString()) == null) { + if (isRootNodePath(path)) { + if (getClass().getResource(nodeFileToResource(path)) == null) { throw new NoSuchFileException(path.toString()); } } else { @@ -149,7 +149,7 @@ public void checkAccess(Path path, Set modes, @Override public Map readAttributes(Path path, String attributes, LinkOption... options) throws IOException { - if (path.startsWith(LOCAL_NODE_PATH)) { + if (path.startsWith(path.getRoot().resolve(NODE_DIR))) { return Collections.singletonMap("isRegularFile", true); } return super.readAttributes(path, attributes, options); @@ -157,7 +157,7 @@ public Map readAttributes(Path path, String attributes, @Override public Path toRealPath(Path path, LinkOption... linkOptions) throws IOException { - if (path.startsWith(LOCAL_NODE_PATH)) { + if (isRootNodePath(path)) { return path; } return super.toRealPath(path, linkOptions); @@ -210,4 +210,24 @@ protected void beforeInvocation() { LOGGER.error("Could not inject global script", e); } } + + /** + * Tests if this is a root node directory, `/node_modules`, `C:\node_modules`, etc... + * + * @param path + * @return + */ + private boolean isRootNodePath(Path path) { + return path.startsWith(path.getRoot().resolve(NODE_DIR)); + } + + /** + * Converts a root node path to a class resource path for loading local modules + * + * @param path + * @return + */ + private String nodeFileToResource(Path path) { + return "/" + NODE_DIR + "/" + path.getFileName(); + } }