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

Java.addToClasspath() doesn't allow class resource loading inside of a jar #413

Closed
Phillipus opened this issue Jan 22, 2021 · 7 comments
Closed
Assignees
Labels
bug Something isn't working

Comments

@Phillipus
Copy link

We're accessing a Java plantuml.jar[1] in JS like this:

Java.addToClasspath("path_to/plantuml.jar");

Now we are able to access the classes in this jar.

However, within this jar there are various *.PNG files in a directory, "sprites". The plantuml Java code is loading these image resources from within the jar file like this[2]:

InputStream is = SpriteImage.class.getResourceAsStream(path);

And this is failing, because the resource is not being loaded.

I suspect that Java.addToClasspath() is somehow not sufficient for this. Is there anther setting I need to make so that the resources in the jar can be loaded or is this an issue with how jars are accessed?

[1] https://plantuml.com/download
[2] https://github.com/plantuml/plantuml/blob/master/src/net/sourceforge/plantuml/sprite/SpriteImage.java

@Phillipus
Copy link
Author

I extracted the contents of plantuml.jar to a directory plantuml and set the classpath as:

Java.addToClasspath("path_to/plantuml");

and it works perfectly.

So, it's a problem accessing resources within a jar.

@woess woess self-assigned this Jan 25, 2021
@woess
Copy link
Member

woess commented Jan 25, 2021

Thanks for the report. I've been able to reproduce this bug using the following script:

Java.addToClasspath("./plantuml.jar");

var SpriteImage = Java.type("net.sourceforge.plantuml.sprite.SpriteImage");
console.log(SpriteImage.fromInternal("archimate/access"));

This seems to happen when a class is loaded from the same jar while a resource stream is open and still being read, because the streams share state that they shouldn't. This only happens with jar files as you discovered.

@woess woess added the bug Something isn't working label Jan 25, 2021
@Phillipus
Copy link
Author

This seems to happen when a class is loaded from the same jar while a resource stream is open and still being read, because the streams share state that they shouldn't. This only happens with jar files as you discovered.

Yes. Loading the class net.sourceforge.plantuml.security.ImageIO first leads to success:

Java.addToClasspath("./plantuml.jar");
var SpriteImage = Java.type("net.sourceforge.plantuml.sprite.SpriteImage");
var ImageIO = Java.type("net.sourceforge.plantuml.security.ImageIO"); // dummy load of class here
console.log(SpriteImage.fromInternal("archimate/access"));

new SpriteImage(ImageIO.read(is)); is the pain point. Creating a new SpriteImage with ImageIO in the constructor with a stream.

@woess
Copy link
Member

woess commented Feb 3, 2021

Should be fixed now (oracle/graal@9e83f61 @master).
Would be great if you could confirm it with one of the next nightly builds (https://github.com/graalvm/graalvm-ce-dev-builds/releases) (after 20210203 - this version does not have the fix yet).

@woess woess closed this as completed Feb 3, 2021
@Phillipus
Copy link
Author

Phillipus commented Feb 3, 2021

@woess Wow that was quick!

Would be great if you could confirm it with one of the next nightly builds

I will try to do this. However, I'm not sure how to get the particular jar files for my Eclipse-based RCP application. I manually download the following jar files from Maven Central and add them to our plug-in:

graal-sdk-20.3.0.jar
js-20.3.0.jar
js-scriptengine-20.3.0.jar
regex-20.3.0.jar
truffle-api-20.3.0.jar
icu4j-67.1

@Phillipus
Copy link
Author

Phillipus commented Feb 6, 2021

I don't know how to get the correct updated jar files in the list in my previous comment to test this. But I'll add a test case here in case someone can test it.

Requirements:

plantuml.jar [1]
Archimate.puml [2]

JavaScript example:

Java.addToClasspath("./plantuml.jar");

var plantUMLText = "@startuml\n";
plantUMLText += "!include ./Archimate.puml\n";
plantUMLText += "Application_Component(Service, Service)\n";
plantUMLText += "@enduml\n";

var fileOutputStream = new Packages.java.io.FileOutputStream("./PlantUMLDemo.png");
var reader = new Packages.net.sourceforge.plantuml.SourceStringReader(plantUMLText);
console.log("Generation result : " + reader.outputImage(fileOutputStream).getDescription());
fileOutputStream.close();

[1] https://plantuml.com/download
[2] https://github.com/plantuml-stdlib/Archimate-PlantUML/blob/master/Archimate.puml

@Phillipus
Copy link
Author

Phillipus commented Sep 6, 2022

Sorry for the long delay in getting back to this one. I tested the above cases in 22.2 and can confirm the problem is fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants