Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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 @@ -16,6 +16,7 @@
import java.util.logging.Logger;

import org.phoebus.framework.jobs.JobManager;
import org.phoebus.framework.util.ResourceParser;
import org.phoebus.ui.javafx.ImageCache;

import javafx.application.Platform;
Expand Down Expand Up @@ -61,7 +62,7 @@

private String current_resource;

public Viewer3dPane(final URI resource, final Consumer<URI> setInput) throws Exception

Check failure on line 65 in app/3d-viewer/src/main/java/org/phoebus/applications/viewer3d/Viewer3dPane.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 18 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yzOL2-Wr-htaSMr&open=AZ8U1yzOL2-Wr-htaSMr&pullRequest=3861
{
super();

Expand Down Expand Up @@ -95,7 +96,10 @@
{
if (current_resource.startsWith("file:"))
{
final File file = new File(URI.create(current_resource));
final URI uri = URI.create(current_resource);
File file = ResourceParser.getFile(uri);
if (file == null)
file = new File(uri.getPath());
fileChooser.setInitialDirectory(file.getParentFile());
fileChooser.setInitialFileName(file.getName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ void loadDisplay(final URI resource)
// Set input ASAP to prevent opening another instance for same input
dock_item.setInput(resource);

final File file = new File(resource);
final File file = Objects.requireNonNull(ResourceParser.getFile(resource));
modification_marker = file.lastModified();

editor_gui.loadModel(file);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@
path = splitPath[1];
}

// Detect UNC paths BEFORE backslash conversion.
// UNC paths start with "//" (Unix-style) or "\\" (Windows-style).
final boolean isUNC = path.startsWith("//") || path.startsWith("\\\\");

path = path.replaceAll("\\\\(?!\\\\)", "/");

// Collapse "something/../" into "something/"
Expand All @@ -135,7 +139,17 @@
// Pattern: '\(?!\)', i.e. backslash _not_ followed by another one.
// Each \ is doubled as \\ to get one '\' into the string,
// then doubled once more to tell regex that we want a '\'
return protocol + path.replaceAll("\\\\(?!\\\\)", "/");
path = protocol + path.replaceAll("\\\\(?!\\\\)", "/");

// Restore UNC prefix after Paths.get().normalize() and backslash conversion.
// On Linux, "//host/share" normalizes to "/host/share", so need to add "/".
// On Windows, "//host/share" normalizes to "\\host\share", so regex converts
// only the second \ (not followed by \), leaving "\/host/share", so need to
// strip leading separators and re-add "//".
if (isUNC && !path.startsWith("//"))
path = "//" + path.replaceFirst("^[/\\\\]+", "");

Check warning on line 150 in app/display/model/src/main/java/org/csstudio/display/builder/model/util/ModelResourceUtil.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this hard-coded path-delimiter.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yuwL2-Wr-htaSMc&open=AZ8U1yuwL2-Wr-htaSMc&pullRequest=3861

return path;
}

/** Obtain directory of file. For URL, this is the path up to the last element
Expand Down Expand Up @@ -399,8 +413,12 @@
}
}
// To get a file, strip query information,
// because new File("file://xxxx?with_query") will throw exception
return ResourceParser.getFile(new URI(resource.getScheme(), null, null, -1, resource.getPath(), null, null));
// because new File("file://xxxx?with_query") will throw exception.
// Preserve host/userInfo/port so UNC/network paths like
// file://wsl.localhost/share/path are handled correctly.
return ResourceParser.getFile(new URI(resource.getScheme(), resource.getUserInfo(),
resource.getHost(), resource.getPort(),
resource.getPath(), null, null));
}

/** Open a file, web location, ..
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;

/** JUnit test of the {@link ModelResourceUtil}
* @author Kay Kasemir
Expand All @@ -38,4 +39,108 @@
final File file = ModelResourceUtil.getFile(URI.create("examples:/monitors_textupdate.bob"));
assertThat(file.canRead(), equalTo(true));
}

@Test
public void testNormalizeUNC() throws Exception
{
// UNC path with forward slashes should be preserved
String normalized = ModelResourceUtil.normalize("//wsl.localhost/AlmaLinux-9/home/user/display.bob");
assertTrue(normalized.startsWith("//wsl.localhost/"),
"Normalized UNC path should start with //wsl.localhost/: " + normalized);
assertTrue(normalized.endsWith("/home/user/display.bob"),
"Normalized UNC path should keep full path: " + normalized);

// UNC path with backslashes (Windows-style) should convert to forward slashes
// and preserve the // prefix
normalized = ModelResourceUtil.normalize("\\\\wsl.localhost\\AlmaLinux-9\\home\\user\\display.bob");
assertTrue(normalized.startsWith("//wsl.localhost/"),
"Normalized Windows UNC path should start with //: " + normalized);
assertTrue(normalized.contains("AlmaLinux-9/home/user/display.bob"),
"Normalized Windows UNC path should convert backslashes: " + normalized);

// UNC path with ".." should collapse parent references but keep //
normalized = ModelResourceUtil.normalize("//server/share/dir/../file.bob");
assertTrue(normalized.startsWith("//server/"),
"Normalized UNC with .. should keep //: " + normalized);
assertTrue(normalized.contains("/share/file.bob") || normalized.endsWith("/share/file.bob"),
"Normalized UNC with .. should collapse ..: " + normalized);

// Regular absolute path should not gain a // prefix
normalized = ModelResourceUtil.normalize("/home/user/display.bob");
assertThat(normalized, equalTo("/home/user/display.bob"));

// Regular Windows path should not gain a // prefix
normalized = ModelResourceUtil.normalize("C:\\Users\\test\\display.bob");
assertThat(normalized, equalTo("C:/Users/test/display.bob"));

// URL should not be affected by UNC handling
normalized = ModelResourceUtil.normalize("http://server.example/path/display.bob");
assertThat(normalized, equalTo("http://server.example/path/display.bob"));
}

@Test
public void testCombineDisplayPathsUNC() throws Exception
{
// Relative display path resolved against UNC parent
final String parent = "//wsl.localhost/AlmaLinux-9/home/user/displays/main.bob";
String combined = ModelResourceUtil.combineDisplayPaths(parent, "child.bob");
assertTrue(combined.startsWith("//wsl.localhost/"),
"Combined with UNC parent should keep //: " + combined);
assertTrue(combined.endsWith("/displays/child.bob"),
"Combined should resolve relative child: " + combined);

// Relative display path with subdirectory
combined = ModelResourceUtil.combineDisplayPaths(parent, "subdir/other.bob");
assertTrue(combined.startsWith("//wsl.localhost/"),
"Combined with subdir should keep //: " + combined);
assertTrue(combined.endsWith("/displays/subdir/other.bob"),
"Combined should include subdir: " + combined);

// Relative display path with parent reference (..)
combined = ModelResourceUtil.combineDisplayPaths(parent, "../sibling/other.bob");
assertTrue(combined.startsWith("//wsl.localhost/"),
"Combined with .. should keep //: " + combined);
assertTrue(combined.contains("/home/user/sibling/other.bob"),
"Combined with .. should resolve correctly: " + combined);

// Absolute display path should not be affected by parent
combined = ModelResourceUtil.combineDisplayPaths(parent, "//other.server/share/abs.bob");
assertThat(combined, equalTo("//other.server/share/abs.bob"));

// Null parent should just return the display path
combined = ModelResourceUtil.combineDisplayPaths(null, "//wsl.localhost/share/file.bob");
assertThat(combined, equalTo("//wsl.localhost/share/file.bob"));
}

@Test
public void testGetFileUNC() throws Exception
{
// getFile with UNC URI (host in authority) should produce File with host in path
final URI unc_uri = new URI("file", "wsl.localhost", "/AlmaLinux-9/home/user/display.bob", null);

Check warning on line 119 in app/display/model/src/test/java/org/csstudio/display/builder/model/util/ModelResourceUtilTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yx1L2-Wr-htaSMd&open=AZ8U1yx1L2-Wr-htaSMd&pullRequest=3861
final File unc_file = ModelResourceUtil.getFile(unc_uri);

Check warning on line 120 in app/display/model/src/test/java/org/csstudio/display/builder/model/util/ModelResourceUtilTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yx1L2-Wr-htaSMe&open=AZ8U1yx1L2-Wr-htaSMe&pullRequest=3861
assertTrue(unc_file != null);
assertTrue(unc_file.getPath().contains("wsl.localhost"),
"getFile should preserve UNC host: " + unc_file.getPath());

// getFile with UNC URI that also has a query parameter
final URI unc_query = new URI("file", "server.example", "/share/displays/main.bob", "X=1&Y=2");

Check warning on line 126 in app/display/model/src/test/java/org/csstudio/display/builder/model/util/ModelResourceUtilTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yx1L2-Wr-htaSMf&open=AZ8U1yx1L2-Wr-htaSMf&pullRequest=3861
final File query_file = ModelResourceUtil.getFile(unc_query);

Check warning on line 127 in app/display/model/src/test/java/org/csstudio/display/builder/model/util/ModelResourceUtilTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yx1L2-Wr-htaSMg&open=AZ8U1yx1L2-Wr-htaSMg&pullRequest=3861
assertTrue(query_file != null);
assertTrue(query_file.getPath().contains("server.example"),
"getFile with query should preserve UNC host: " + query_file.getPath());
// Query should be stripped from the file path
assertTrue(!query_file.getPath().contains("X=1"),
"getFile should strip query from path: " + query_file.getPath());
}

@Test
public void testGetDirectoryUNC() throws Exception
{
// getDirectory on a UNC path should preserve the // prefix
final String dir = ModelResourceUtil.getDirectory("//wsl.localhost/AlmaLinux-9/home/user/file.bob");
assertTrue(dir.startsWith("//wsl.localhost/"),
"getDirectory should keep UNC //: " + dir);
assertTrue(dir.endsWith("/home/user"),
"getDirectory should return parent directory: " + dir);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,21 @@
// Get basic file or http 'path' from path
final String path;
if (uri.getScheme() == null || uri.getScheme().equals("file"))
path = uri.getPath();
{
// Preserve URI host for UNC/network paths, e.g.
// file://wsl.localhost/share/path -> //wsl.localhost/share/path
final String host = uri.getHost();
if (host != null && !host.isEmpty())
path = "//" + host + uri.getPath();

Check warning on line 67 in app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/app/DisplayInfo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this hard-coded path-delimiter.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yyNL2-Wr-htaSMh&open=AZ8U1yyNL2-Wr-htaSMh&pullRequest=3861
else
{
// On Windows, File.toURI() for UNC paths may produce URIs
// with the host embedded in the path (file:////host/share).
// In that case getHost() is null but getPath() starts with "//".
// Preserve the double-slash so it's treated as a UNC path.
path = uri.getPath();
}
}
else
{
final StringBuilder buf = new StringBuilder();
Expand Down Expand Up @@ -118,7 +132,12 @@
{
String userDataInputFile = model.getUserData(DisplayModel.USER_DATA_INPUT_FILE);
String userDataInputFile_lowerCase = userDataInputFile.toLowerCase(Locale.ROOT);
if ( !userDataInputFile_lowerCase.startsWith("/")
if (userDataInputFile.startsWith("\\\\")) {
// UNC path like \\wsl.localhost\share\... -> //wsl.localhost/share/...
// Don't prepend '/' — the double slash IS the leading path indicator for UNC
path = userDataInputFile.replace('\\', '/');
}
else if ( !userDataInputFile_lowerCase.startsWith("/")
&& !userDataInputFile_lowerCase.startsWith("examples:")
&& !userDataInputFile_lowerCase.startsWith("file:")
&& !userDataInputFile_lowerCase.startsWith("http:")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*******************************************************************************/
package org.csstudio.display.builder.runtime.test;

import org.csstudio.display.builder.model.DisplayModel;
import org.csstudio.display.builder.runtime.app.DisplayInfo;
import org.junit.jupiter.api.Test;
import org.phoebus.framework.macros.Macros;
Expand All @@ -17,6 +18,7 @@
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;

/** JUnit test of the {@link DisplayInfo}
* @author Kay Kasemir
Expand Down Expand Up @@ -113,4 +115,124 @@
assertThat(info1.toURI().toString(), equalTo(info2.toURI().toString()));
assertThat(info2.toURI().toString(), equalTo("file:/some/path/xx.bob?X=Fred+Harvey+Newman&Y=2&Z=1"));
}

@Test
public void testForURI_UNC() throws Exception
{
// UNC URI with host in authority: file://wsl.localhost/share/path
final URI unc = new URI("file", "wsl.localhost", "/AlmaLinux-9/home/user/display.bob", null);
final DisplayInfo info = DisplayInfo.forURI(unc);
System.out.println("UNC forURI: " + info);

// Path should have // prefix with host
assertThat(info.getPath(), equalTo("//wsl.localhost/AlmaLinux-9/home/user/display.bob"));
assertThat(info.getName(), equalTo("display.bob"));

// UNC URI with macros
final URI unc_macros = new URI("file://wsl.localhost/share/path/test.bob?X=1&Y=hello");

Check warning on line 132 in app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/DisplayInfoTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yyeL2-Wr-htaSMi&open=AZ8U1yyeL2-Wr-htaSMi&pullRequest=3861
final DisplayInfo info_macros = DisplayInfo.forURI(unc_macros);

Check warning on line 133 in app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/DisplayInfoTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yyeL2-Wr-htaSMj&open=AZ8U1yyeL2-Wr-htaSMj&pullRequest=3861
System.out.println("UNC forURI with macros: " + info_macros);

assertThat(info_macros.getPath(), equalTo("//wsl.localhost/share/path/test.bob"));
assertThat(info_macros.getMacros().getValue("X"), equalTo("1"));
assertThat(info_macros.getMacros().getValue("Y"), equalTo("hello"));

// UNC URI with no host but path starting with // (file:////host/share)
final URI unc_no_host = URI.create("file:////server/share/path/file.bob");

Check warning on line 141 in app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/DisplayInfoTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yyeL2-Wr-htaSMk&open=AZ8U1yyeL2-Wr-htaSMk&pullRequest=3861
final DisplayInfo info_no_host = DisplayInfo.forURI(unc_no_host);

Check warning on line 142 in app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/DisplayInfoTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yyeL2-Wr-htaSMl&open=AZ8U1yyeL2-Wr-htaSMl&pullRequest=3861
System.out.println("UNC forURI no host: " + info_no_host);

// getPath() on such a URI gives "//server/share/path/file.bob"
assertTrue(info_no_host.getPath().startsWith("//server/"),
"No-host UNC should preserve //: " + info_no_host.getPath());
}

@Test
public void testToURI_UNC() throws Exception
{
// UNC path with // prefix -> toURI should produce file://host/path
final DisplayInfo info = new DisplayInfo("//wsl.localhost/AlmaLinux-9/home/user/display.bob",
null, new Macros(), false);
final URI uri = info.toURI();
System.out.println("UNC toURI: " + uri);

// toURI prepends "file:" to path, so the result should be
// file://wsl.localhost/AlmaLinux-9/home/user/display.bob
assertThat(uri.toString(), equalTo("file://wsl.localhost/AlmaLinux-9/home/user/display.bob"));
assertThat(uri.getScheme(), equalTo("file"));
assertThat(uri.getHost(), equalTo("wsl.localhost"));
assertThat(uri.getPath(), equalTo("/AlmaLinux-9/home/user/display.bob"));

// Round-trip: forURI(toURI()) should give back original path
final DisplayInfo round_trip = DisplayInfo.forURI(uri);

Check warning on line 167 in app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/DisplayInfoTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yyeL2-Wr-htaSMm&open=AZ8U1yyeL2-Wr-htaSMm&pullRequest=3861
assertThat(round_trip.getPath(), equalTo("//wsl.localhost/AlmaLinux-9/home/user/display.bob"));

// UNC path with macros
final Macros macros = new Macros();
macros.add("SYS", "BL1");
final DisplayInfo info_macros = new DisplayInfo("//server/share/displays/main.bob",

Check warning on line 173 in app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/DisplayInfoTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yyeL2-Wr-htaSMn&open=AZ8U1yyeL2-Wr-htaSMn&pullRequest=3861
null, macros, false);
final URI uri_macros = info_macros.toURI();

Check warning on line 175 in app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/DisplayInfoTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yyeL2-Wr-htaSMo&open=AZ8U1yyeL2-Wr-htaSMo&pullRequest=3861
System.out.println("UNC toURI with macros: " + uri_macros);

assertThat(uri_macros.getScheme(), equalTo("file"));
assertThat(uri_macros.getHost(), equalTo("server"));
assertTrue(uri_macros.toString().contains("SYS=BL1"),
"URI should contain macro: " + uri_macros);

// Round-trip with macros
final DisplayInfo round_macros = DisplayInfo.forURI(uri_macros);

Check warning on line 184 in app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/DisplayInfoTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yyeL2-Wr-htaSMp&open=AZ8U1yyeL2-Wr-htaSMp&pullRequest=3861
assertThat(round_macros.getPath(), equalTo("//server/share/displays/main.bob"));
assertThat(round_macros.getMacros().getValue("SYS"), equalTo("BL1"));
}

@Test
public void testForModel_UNC() throws Exception
{
// Simulate what happens when a model has USER_DATA_INPUT_FILE set to a
// Windows UNC absolute path (from File.getAbsolutePath() on Windows)
final DisplayModel model = new DisplayModel();
model.propMacros().getValue().add("DEVICE", "Motor1");

// Windows UNC path: \\wsl.localhost\AlmaLinux-9\home\<user>\display.bob
model.setUserData(DisplayModel.USER_DATA_INPUT_FILE,
"\\\\wsl.localhost\\AlmaLinux-9\\home\\" + "user\\display.bob");
DisplayInfo info = DisplayInfo.forModel(model);
System.out.println("forModel UNC backslash: " + info);

// Should produce //wsl.localhost/... (not /wsl.localhost/...)
assertThat(info.getPath(), equalTo("//wsl.localhost/AlmaLinux-9/home/user/display.bob"));
assertThat(info.getMacros().getValue("DEVICE"), equalTo("Motor1"));

// Verify full round-trip: forModel -> toURI -> forURI gives same path
final URI uri = info.toURI();
System.out.println("forModel -> toURI: " + uri);
assertThat(uri.getHost(), equalTo("wsl.localhost"));

final DisplayInfo round_trip = DisplayInfo.forURI(uri);

Check warning on line 212 in app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/DisplayInfoTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ8U1yyeL2-Wr-htaSMq&open=AZ8U1yyeL2-Wr-htaSMq&pullRequest=3861
assertThat(round_trip.getPath(), equalTo("//wsl.localhost/AlmaLinux-9/home/user/display.bob"));

// Unix-style UNC path (already forward slashes)
model.setUserData(DisplayModel.USER_DATA_INPUT_FILE,
"//wsl.localhost/AlmaLinux-9/home/user/display.bob");
info = DisplayInfo.forModel(model);
System.out.println("forModel UNC forward slash: " + info);

// Starts with "/" so goes through else branch, should be unchanged
assertThat(info.getPath(), equalTo("//wsl.localhost/AlmaLinux-9/home/user/display.bob"));

// Regular Windows path (not UNC) should still get "/" prepended
model.setUserData(DisplayModel.USER_DATA_INPUT_FILE,
"C:\\Users\\test\\display.bob");
info = DisplayInfo.forModel(model);
System.out.println("forModel Windows: " + info);
assertThat(info.getPath(), equalTo("/C:/Users/test/display.bob"));

// Regular Unix path should pass through unchanged
model.setUserData(DisplayModel.USER_DATA_INPUT_FILE,
"/home/user/displays/main.bob");
info = DisplayInfo.forModel(model);
System.out.println("forModel Unix: " + info);
assertThat(info.getPath(), equalTo("/home/user/displays/main.bob"));
}
}
Loading