-
Notifications
You must be signed in to change notification settings - Fork 4
Compile(Reader) and Compile(String) #3
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
Conversation
I think it makes most sense to do it that way.
Yes!
"Needed for annotation processing" now... we don't use Sezpoz anymore. And actually, as far as |
Oh, and a very fundamental comment: the way to prevent frequent recompiling would be to remember intermediate compilations of the identical source code. To this end, it might make sense to turn the logic around, from passing a |
Thank you for reviewing! I'll fix the issues you mentioned tomorrow, I don't know if I'll be able to do the recompilation checking though (timewise), I'll will try, though. |
JavaEngine provides the possibility to evaluate Java code from a Reader, sometimes one might not want to have that code immediately executed. For a Java File, the compile(File,Writer) method was provided already, this commit adds such a method for compiling from Reader.
A convenience method to compile from String, analog to eval(String).
@dscho I did not do the recompilation checking. I might do in the future, but in a separate pull request. |
Not in too near future, but yes. This is related to a task I am doing for Knip/@dietzc , which is currently on hold for another, so I cannot promise that this will be done too soon. Is there any specific reason you ask? |
@Squareys I was just going back through all the pending PRs, trying to resolve as many as possible, and categorizing those that remain. In this case, I just wanted to make sure we were all on the same page that the ball is currently in your court. Let us know if you need any help with it! |
@dietzc what's missing is discussed in previous comments: |
@Squareys an example for checksumming a string: private final static Charset utf8 = Charset.fromName("UTF-8");
private final static MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
private static String hash(final String code) {
final InputStream input = new ByteArrayInputStream(code.getBytes(utf8));
synchronized (sha1) {
sha1.reset();
final InputStream digestStream = new DigestInputStream(input, sha1);
while (digestStream.read(buffer) >= 0); /* do nothing */
digestStream.close();
final byte[] bytes = sha1.digest();
return String.format("%0" + (bytes.length << 1) + "x", new BigInteger(1, bytes));
}
} (This is not even compile-tested; I trust that you can get it to work, though.) |
@Squareys See also org.scijava.util.DigestUtils, which will save you the effort of @dscho's example above. |
D'oh. Thanks, @ctrueden, for setting my head straight. |
So, I need to compute the hash for the code input and then check, whether a entry for this hash already exists in the weak hash map. |
That's what I referred to when I said this:
|
@Squareys I wouldn't bother "prematurely optimizing" here. For the intended use cases, the |
While I'm at it: Is there a Eclipse code formatter .xml somewhere I can use? |
@Squareys Please import the whole |
Thank you for mentioning that, I wouldn't have done so otherwise. |
Needed in future recompilation avoidance for hash calculation. TODO: Move to a utility class? Signed-off-by: Squareys <Squareys@googlemail.com>
Regarding avoiding recompilation; after trying to cram this in for a few hours, my oppinion on how to go about this changed: I do not think, eval(..) nor compile(..) should support extra measures for avoiding recompilation. When compiling from a String or a Reader, a temporary maven project is created which is dependent on engine scope bindings (values assigned to "verbose" and "debug" keys). Therefore storing only the temporary directory in the hash map wont do it. So, what if you still want to avoid recompilation? After having my problems understanding the compile(File, Writer) method, I realized, that this method merely compiles an existing file without doing all the other fancy stuff the compile(String/Reader) methods do. For this method to be useful, you will need to get the main class or whatever yourself. This also means the project files of the existing project probably won't change and minimaven can handle avoiding recompilation for multiple compile(File) calls (I am kinda assuming that for minimaven. Is this actually true?). My suggestion would be to improve the "workflow" around compile(File), maybe expose Builder after some more refactoring to provide simpler ways of getting the main class/running the project via JavaRunner etc, in another issue (This issue never meant to be about avoiding recompilation). |
@Squareys Feel free to file issues along the lines of your thinking. FYI, realistically, no one at LOCI will be able to work on the |
Regarding your questions, I am not an expert on the code. But personally, I would like to move away from any MiniMaven dependencies across the board. It is one more wrinkly component that we do not really have time to maintain. Rather, we should lean on the JRE's built-in infrastructure as much as possible, even if it means end users have to install a JDK. Maybe we could consolidate Java compilation logic into the |
Alright, I will merge my changes into master of my fork tomorrow, they will not contain recompilation avoidance (for wich I will not create a separate issue since I came to the conclusion that it is not necessary), but contains a few improvements to documentation, readability and consistency. I will notify you after, when I believe this PR could be ready for merge. |
This allows us to compute a hash on the script as a String even if it was input via the gererating Reader. We need to compute the hash for future recompilation avoidance. Signed-off-by: Squareys <Squareys@googlemail.com>
This order is much more efficient with the recently swapped execution order of compile(String) and compile(Reader). See e663151. Signed-off-by: Squareys <Squareys@googlemail.com>
compile(File, Writer) now uses the context error writer if the specified writer is null. compile(file) calls compile(File, null), therefore compiles a given file and writes errors to the context error writer. This maintains the consistency througout the compile(..) and eval(..) methods.
There are now two constructors which clearly differentiate between creating a project for a File and creating a project for a Reader. This makes the calling code easier to read. To avoid code duplication, two small private methods were added to Builder.
When a valid filename is specified by the ScriptEngine.FILENAME key in the engine scope bindings, the given script will be ignored and the file described by the filename will be compiled (and run) instead. Signed-off-by: Squareys <Squareys@googlemail.com>
Alright. There is one last thing, which may or not be an issue: I switched up the order of execution from The issue one could possibly see here is that this causes additional overhead when executing scripts from Readers. I don't believe this overhead is really significant though, I can't imagine reading from a StringReader to be too costly. |
@ctrueden if this is an issue for you, I will see what I can do, otherwise I declare this PR ready for merge from my side. |
@ctrueden I'm guessing time is sparse at the moment, just wanted to make sure you got the message that this is pull request is ready to be merged. |
Thanks @Squareys. FWIW, 4913afd has failing tests:
And 040383e has unrelated formatting changes. But really, those are nitpicks. I'm gonna merge it in the interest of time. |
Compile(Reader) and Compile(String)
For what's new, see: scijava/scripting-java#3
Hello @dscho, @ctrueden, hello all!
I am currently working on a scripting node for KNIME and very happy to be able to use scijava and scripting-java.
Current goal is to execute one Command Plugin for every row in an input table.
This requires the Plugins Java code (as String) to be compiled once and then be reused for every row.
Until now there was no way to do this (except use eval(String) for the first row and the load the class manually to run the command on the following rows). Since there is an compile(File, Writer) already, I suggest adding compile(String) and compile(Reader) aswell.
I replaced the code which does the compilation in eval(Reader) with a call to the new compile(Reader) method.
Open for discussion:
What are your thoughts?
Greetings,
Jonathan