parseClass loadClass groovy - groovy

When using the GroovyClassLoader, when should I use loadClass and when should I call parseClass?
If I understand it, the first call to loadClass() will compile the script, and subsequent calls will use the cached class file rather than recompiling it.
But what about parseClass then?

The documentation for parseClass shows that it takes a File or a String containing Groovy code, and converts it into a class.
If the function is passed a File, then the GroovyClassLoader will cache this generated class, but if it is passed a String, it will not cache it.
The function loadClass (from the documentation) says:
loads a class from a file or a parent classloader.
What it basically does, is looks for the class already existing in the classLoader, and if it fails to find it, look for the script file on disk with the matching name.
Once this class is loaded, it will be cached. The next time you call loadClass, it will use this cached class unless you pass false for the preferClassOverScript. If you pass false, it will attempt locate the script on disk again, recompile the class if necessary.

Related

Instancing classes from dynamically loaded modules

What is the best way to load classes from python source code files on disk, dynamically? (Meaning I cannot just import className)
So far, I was able to load the source code into memory and make a python module object out of it using the following:
spec = importlib.util.spec_from_file_location(modname, sourcepath)
module = importlib.util.module_from_spec(spec)
So far, the code works. What I did next is use the inspect.getmembers() function to extract only classes from the loaded module, but, and this is the issue, the function returns an empty list.
classes = inspect.getmembers(module, inspect.isclass)
This code actually worked in Python 2, where the only difference was that I loaded the source file into a module form using the imp library and the imp.load_source(modname, modpath)) function.
What I need this code is for the inspect.getmembers call to return a list of classes of the specific module, or, to implement this dynamic class lookup in another way.
The reason I'm doing this is that I'm writing a small program that loads plugins, in the form of python classes, that it then interfaces with using predefined function calls.
After a lot of messing around, I found that the solution was pretty simple.
I only had to change the way the module gets loaded into a spec like so:
loader = importlib.machinery.SourceFileLoader(filename, dirpath+"/"+filename)
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
This approached lead to the inspect.getmembers to return valid classes from the module.

Groovy injecting a trait at compile-time results in indeterministic byte code?

I have observed that the domain class compile output file(.class file) keep changing without modification to the source file(.groovy) in grails.
see:https://github.com/grails/grails-core/issues/10868 .
And grails domain class compiled output file keep changing without modification .
I doubt it's something related to groovy AST injecting.
I have tested normal groovy class(without any AST), the compiled byte code is identical every time. Anyone can explain this symptom?

Groovy - extensions structure

I'd like to extend String's asType method to handle LocalDateTime. I know how to override this method, however I've no idea where should I put it in project structure to work globally - for all strings in my project. Is it enough to put such extension wherever in the classpath? I know that there's a special convention for extensions (META-INF/services), how does it work for method overriding?
All documentation regarding this topic can be found here. And here exactly the relevant part can be found.
Module extension and module descriptor
For Groovy to be able to load your extension methods, you must declare
your extension helper classes. You must create a file named
org.codehaus.groovy.runtime.ExtensionModule into the META-INF/services
directory:
org.codehaus.groovy.runtime.ExtensionModule moduleName=Test module for
specifications moduleVersion=1.0-test
extensionClasses=support.MaxRetriesExtension
staticExtensionClasses=support.StaticStringExtension The module
descriptor requires 4 keys:
moduleName : the name of your module
moduleVersion: the version of your module. Note that version number is
only used to check that you don’t load the same module in two
different versions.
extensionClasses: the list of extension helper classes for instance
methods. You can provide several classes, given that they are comma
separated.
staticExtensionClasses: the list of extension helper classes for
static methods. You can provide several classes, given that they are
comma separated.
Note that it is not required for a module to define both static
helpers and instance helpers, and that you may add several classes to
a single module. You can also extend different classes in a single
module without problem. It is even possible to use different classes
in a single extension class, but it is recommended to group extension
methods into classes by feature set.
Module extension and classpath
It’s worth noting that you can’t use an extension which is compiled at
the same time as code using it. That means that to use an extension,
it has to be available on classpath, as compiled classes, before the
code using it gets compiled. Usually, this means that you can’t have
the test classes in the same source unit as the extension class
itself. Since in general, test sources are separated from normal
sources and executed in another step of the build, this is not an
issue.

Reserved Class Names in Groovy

If I have a class named Character.groovy (with no explicit constructors) and try to instantiate it, I get a message that says:
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.lang.Character()
But if I change the class name to Characterr.groovy, then I am able to instantiate an object and use it as expected. So are there reserved words I can't use in Groovy classes? If so, why is Character one of them?
It's not a reserved class name, but there already is a class with that name (java.lang.Character) imported as the package java.lang gets imported automatically in java.
This can happen all the time, especially if you are a java developer and not used to get e.g. java.io package etc. autoimported for you by groovy (e.g. File) (see also What packages does 1) Java and 2) Groovy automatically import?)
There are three ways around it:
the java way: address your class with the full name, that is package and class name. e.g. org.myrpg.Character.
the groovy way: import the class with a new name. e.g. import org.myrgp.Character as RPGChar and use then RPGChar instead.
the zen way: more often than not, it is not worth the hastle and easier to just rename your class. if you tripped over this once, then the chance very high you will trip over this again and only things like #CompileStatic or an IDE may make notice you this at compile time or while writing it.
http://groovy.codehaus.org/Reserved+Words
Those are the reserved keywords
http://docs.oracle.com/javase/8/docs/api/java/lang/Character.html
Character I believe is a object wrapper class in java which is why you can't use it. You can't use any name of java classes that are autoincluded in java

Linux library code injection & calls to identically named functions in SOs

I have built a linux shared object which I inject into a 3rd party program to intercept some dynamic function calls using LD_PRELOAD.
The 3rd party program uses a SO "libabc.so" located at some path. My injected SO uses another SO, also called "libabc.so" located at another path (essentially identical but slight code differences).
My problem is now, that calls to a function "def" which appear in both libabc.so are always resolved by the first. (Presumably because it is loaded first?!) How can I get them to be resolved with the second libabc.so?
Many thanks!
Unless something changed since I used to do this, you will need to dlopen() the library you want to pass calls on to and call the function manually, something like;
handle = dlopen("/path/to/libabc.so", RTLD_LAZY);
otherDef = dlsym(handle, "def");
orderDef(parameter);
There is a complete example how to do this very thing at LinuxJournal.
If you only want to use one libabc.so version, you can always use LD_PRELOAD to load it along with your own shared object before anything else.
If you want to use multiple versions, you have a few alternatives:
Use dlopen() in your shared object to load that library. Since you have created a function injection object you should be familiar with this procedure. This is the more generic and powerful way - you could even mix & match functions from different library versions.
Use a different DT_SONAME for the library version your shared object links against. Unfortunately this requires (slightly) changing the build system of that library and recompiling.
Link your shared object statically against the library in question. Not always possible but it does not require modifying the library in question. The main issue with this alternative is that any change in the library should be followed by a relinking of your shared object for the changes to be pulled in.
Warning: you may need to use a custom linker script or specific linker options to avoid symbol conflicts.

Resources