-
Notifications
You must be signed in to change notification settings - Fork 10
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
Suggestion - Library download #4
Comments
Hi EpiCanard. Yes this feature is very useful and yes it is also achievable. ScalaLoader can make use of Eclipse Aether to resolve and download maven artifacts. But I really want to do this right, that means the following:
This feature might also cause some source-incompatible changes since libraries need to be downloaded and loaded before the plugin's main class load, but I can make it binary-backwards compatible since ScalaLoader already does bytecode transformations at class-load time. All the TASTy-related stuff will be the hardest to implement because I might have to depend on the dotty compiler or create a tasty reader in Java myself. So yes, the feature is on the TODO list (it literally has been on the roadmap in the readme for years) and I do have plans for what I want it to look like, but I haven't been able do implement this because of real life work and the ConfigurationSerializable feature that is still not completely done. The reason I decided to work on that first is that I would rather wait till Scala 3 is fully released before I start on auto-downloading maven artefacts. Thanks anyway for the suggestion and for thinking along with the project! Kind regards, |
Hi :) Thanks a lot for all the details. It's awesome to see you thinking so far the design and the quality of work for your features. No problem I will continue to shade the libraries I need. Best Regards ps: Sorry I didn't see the line in Readme for this feature, but I don't regret you gave so many interesting details. |
Don't worry about the Readme. This issue has allowed me to really dive deep into this and strucuture my thoughts. I'm leaving the issue open as it can serve as documentation for a future me when I start to implement this, and for others who stumble upon this project. |
Hey there, I recently came across this thread on SpigotMC where one person linked to two other projects which can load dependencies at runtime. They seem to work at the 'javaplugin-level' meaning that the dependencies are loaded as javaplugins and so when used in combination with ScalaLoader they are accessible to all ScalaPlugins. This can be a problem if the library is specific to a certain version of Scala and your ScalaPlugin is a publicly available, but if your plugin is private or the library is a java library then you could already use it. Here's the thread: Suggestion - Including Scala Runtime |
It looks like you can use a relocation system. So if you relocate it in your plugin package, it shouldn't have problem of conflict with other plugins. |
Edit: now that I've taken a deeper look at PDM, it checks whether the classloader is actually a PluginClassLoader from bukkit, so PDM isn't usable either without modifications. I'm sorry. |
A contribution to remove this restriction or change it to support ScalaPluginClassLoader can be a quick win. :) |
well yes but you could just do the same thing yourself in your plugin. val url: Url = new URL("https://location/of/cats_2.13.jar")
val classLoader: ScalaPluginClassLoader = getClassLoader();
val method: Method = classOf[URLClassLoader].getDeclaredMethod("addUrl", classOf[URL])
method.setAccessible(true)
method.invoke(classLoader, url) The only caveat being that you must make sure none of the library classes are classloaded before that point or you will get a NoClassDefFoundError. Admittedly you don't get all the caching and other niceties that PDM offers, but I don't have the time to fork PDM right now and adjust its behaviour, test that it actually works for ScalaPlugins and create a pull request. |
I made it work using standard PDM, a demo can be found here: https://github.com/Jannyboy11/CatsPlugin. The only reason why this works is that the classloader check is only used in the factory method Note that this only works on java 8 or 9 till 16 with illegal access enabled (can be enabled on jdk9-16 using Edit2: |
It sounds awesome. I didn't found the time to try yet but it seems to be a perfect solution to resolve the issue of dependencies and keep my plugin light.
It will no longer work because he use reflection ? |
Indeed. Though in my testing it only went wrong for transitive dependencies, so I think it is possible to patch pdm to address this. |
As you said I think I have the time before everyone is on Java 17 or higher. It's already hard to make them move from Java 8 ^^" (bstats javaversion) |
I thought I'd just share this here since it's related to loading libraries at runtime: Since this will likely mean changes to bukkit's class-loading scheme, I am going to see this feature as a blocker for my own dependency loader - meaning I won't work on it before bukkit's own dependency loader is implemented. I might not even need to implement a dependency loader after all in the best case. |
Interesting. |
Yes that's what I was thinking. I'll have to query this feature for availability in a backwards-compatible way though. Currently ScalaLoader works on all CraftBukkit versions since Minecraft 1.8 and I don't intend to break compatibility because of new features in Bukkit. That won't mean I won't utilize new features from Bukkit, it just means the behaviour will be slightly different. Take for example bukkit's bytecode transformation compatibility layer; The ScalaPluginClassLoader will use it if it's available (1.13 and up), and on lower versions a transformation is only attempted once, and once it fails it's never even attempted again. |
Even if the dependency download feature will only be available in a future version (maybe 1.17, who knows). |
Yes, in the ideal case I would, but it's got lower priority. I'm just currently very stressed by work on my master thesis so I find it hard to make any long term planning right now. If you need your plugin to work on older versions you can still use PDM or just use shading. |
Ok :) |
Although it's not the fully-fledged solution I sketched earler, it's now possible to define dependencies in the plugin.yml because I want to keep feature parity with bukkit's JavaPluginLoader. Some differences in my implementation:
See https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/plugin/PluginDescriptionFile.html#getLibraries(). |
It's so cool ! Thank you a lot, you are awesome ! I guess that since the library loader is really new, it will not be available for previous versions of Minecraft. |
That is correct, however for ScalaPlugins it will work on older versions of minecraft. I tested the Scala 3 example plugin on Spigot 1.8.8 and there were no issues. |
Awesome 😁 |
Hello :)
I was thinking about a feature.
Currently ScalaPluginLoader download and load Scala in classpath. Would it be possible to do the same with libraries, to reduce the size of scala plugins ?
For example, if I want to use Cats in a plugin. Ask to ScalaPluginLoader to download Cats with a specific version and load it into the plugin's classpath.
Hope you will find this idea useful and achievable ^^
Have a good day :)
The text was updated successfully, but these errors were encountered: