Based on the error message and code you've shared, I can identify the issue and provide some suggestions for fixing it. Let me analyze what's happening.
The error you're seeing is a java.nio.file.FileSystemNotFoundException that occurs when JabRef tries to load an internal style. Looking at the stack trace and code, here's what's happening:
JStyle.java at line 285 in the reload() method, specifically at the call to Path.of(resUrl.toURI()).The problem is in the reload() method of JStyle.java when it tries to handle resources from inside a JAR file. Java's Path.of() method can't directly work with JAR URIs (which have the format jar:file:/path/to/file.jar!/internal/path) without a proper FileSystem provider.
When JabRef tries to load an internal style from a resource in the JAR using Path.of(resUrl.toURI()), it fails because the default file system doesn't know how to handle JAR URIs.
You need to modify the reload() method in JStyle.java to correctly handle resources inside JARs. Here's a suggested fix:
private void reload() throws IOException {
if (styleFile != null) {
if (fromResource) {
try {
URL resUrl = JStyle.class.getResource(path);
if (resUrl != null) {
// Don't try to convert JAR URLs directly to Path objects
try (InputStream stream = resUrl.openStream()) {
initialize(stream);
// Update the modification time to current time for resources
this.styleFileModificationTime = System.currentTimeMillis();
}
return; // Return early after handling the resource
}
} catch (Exception ex) {
LOGGER.error("Couldn't resolve resource path for style {}", path, ex);
}
}
// Handle files on disk (non-resources)
Path resourcePath = styleFile;
this.styleFileModificationTime = Files.getLastModifiedTime(resourcePath).toMillis();
try (InputStream stream = Files.newInputStream(resourcePath)) {
initialize(stream);
}
}
}This approach:
openStream() to get a direct stream from the URL rather than trying to convert it to a PathIf you prefer to maintain a structure closer to the original, you could also use the ZipFileSystem approach to properly handle JAR URIs:
private void reload() throws IOException {
if (styleFile != null) {
if (fromResource) {
try {
URL resUrl = JStyle.class.getResource(path);
if (resUrl != null) {
URI uri = resUrl.toURI();
// If it's a JAR URI, open it with the appropriate FileSystem
if ("jar".equals(uri.getScheme())) {
try {
FileSystem fs = FileSystems.getFileSystem(uri);
Path resourcePath = fs.getPath(uri.getPath());
this.styleFileModificationTime = System.currentTimeMillis();
try (InputStream stream = Files.newInputStream(resourcePath)) {
initialize(stream);
}
return;
} catch (FileSystemNotFoundException e) {
// FileSystem doesn't exist yet, need to create it
Map<String, String> env = new HashMap<>();
String[] parts = uri.toString().split("!");
try (FileSystem fs = FileSystems.newFileSystem(URI.create(parts[0]), env)) {
Path resourcePath = fs.getPath(parts[1]);
this.styleFileModificationTime = System.currentTimeMillis();
try (InputStream stream = Files.newInputStream(resourcePath)) {
initialize(stream);
}
return;
}
}
} else {
// Regular file URI
Path resourcePath = Path.of(uri);
this.styleFileModificationTime = Files.getLastModifiedTime(resourcePath).toMillis();
try (InputStream stream = Files.newInputStream(resourcePath)) {
initialize(stream);
}
return;
}
}
} catch (URISyntaxException ex) {
LOGGER.error("Couldn't resolve resource path for style {}", path, ex);
}
}
// Fall back to direct file access if it's not a resource or resource loading failed
this.styleFileModificationTime = Files.getLastModifiedTime(styleFile).toMillis();
try (InputStream stream = Files.newInputStream(styleFile)) {
initialize(stream);
}
}
}If you want the simplest possible fix, just modify the current code to avoid using Path.of() for resource URLs:
private void reload() throws IOException {
if (styleFile != null) {
if (fromResource) {
URL resUrl = JStyle.class.getResource(path);
if (resUrl != null) {
// Don't use Path.of() for resources
try (InputStream stream = resUrl.openStream()) {
initialize(stream);
this.styleFileModificationTime = System.currentTimeMillis();
return;
}
}
}
// Original code for non-resource files
this.styleFileModificationTime = Files.getLastModifiedTime(styleFile).toMillis();
try (InputStream stream = Files.newInputStream(styleFile)) {
initialize(stream);
}
}
}This should resolve the issue by using the appropriate method to access resources inside JARs, while maintaining the existing behavior for files on disk.