Call a personal Java method from eXistdb XQuery Processor - java

I have noticed i can call from eXistdb XQuery processor any Java classes, i need just to declare a namespace like the following:
declare namespace string="java:java.lang.String";
I've imported all the methods from the class String.
Now comes the question: is there a way to import my own classes? For example, if i made that class:
package example.model.A
class A1 {
public static example() { ... }
}
Is there a way to use the method example inside my xquery? Can i point the namespace to my personal class?
Thank you very much.

Related

How to prefer package-local class over library class's inner class?

Given this code:
package my.pkg;
import com.google.common.util.concurrent.Service;
class Test implements Service {
public static void main(String... a) {
System.out.println(Listener.class);
}
// method implementations omitted for brevity
}
And given there's one Listener class in my.pkg, and one as an inner class in the Service class I'm importing.
I would expect the package local class to 'win' here, since I'm not referring to Service.Listener.class or explicitly importing the inner class. Apparently, IntelliJ expects the same thing, since if I explicitly add import my.pkg.Listener;, it is automatically removed as being redundant. However, when compiling and running this code (Gradle 2.14.1 and openjdk 1.8.0_91, if that matters), it's very clear the inner class is winning.
How do I get this code to use the class in my.pkg? Explicitly adding the import doesn't work, since my IDE removes it. I'd also prefer not to use full class names (my.pkg.Listener) everywhere in the class.

Java refers to lib java.lang.String not my java.lang.String

I have created a class with the same name and package as the String java class.
package java.lang;
public class String {
public String() {
System.out.println("This is my string ");
}
public void show() {
System.out.println("From show mathod .");
}
}
When I try to invoke this show method it gives error for no such method. It refers to API class. why.?
import java.lang.*;
public class Test {
public static void main(String[] args) {
String str = new String();
str.show();
}
}
I know that I am violating the rule of unique package and class name. But I want to know if I add two jars in my class-path and they have same structure. In such case is there any behaviour defined by Java which class will be loaded.
And why java does not load my class instead of Java API classes? (I also tried this with other api defined classes)
#Please do not give answer like I am violating the rule or work arounds.
Java comes shipped with classes. One of these classes is java.lang.String.
These pre-shipped classes take precedence in the classpath over any class that you might write that have the same package and name.
Whenever you do a new java.lang.String(), regardless if you have a class with the same package and name, the runtime class shipped by Oracle will take precedence.
Since java.lang.String is also a final class, there's no way you will be able to add new methods to it. The best solution is for you to create a new class in a different package or under a different name.
classes can not be redefined after the VM has started and the class has been loaded. As java.lang.String is being used way before your code, it would already be loaded.
I am not sure that you could even achieve this using a byte code enhancement library like javassist
Just tried to write custom ClassLoader to load my class named java.lang.String. Ran out of luck here:
Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:658)
at java.lang.ClassLoader.defineClass(ClassLoader.java:794)
at java.lang.ClassLoader.defineClass(ClassLoader.java:643)
at temp.TempLoader.findClass(TempLoader.java:20)
at temp.TempLoader.main(TempLoader.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Offending code in JRE java.lang.ClassLoader:
if ((name != null) && name.startsWith("java.")) {
throw new SecurityException
("Prohibited package name: " +
name.substring(0, name.lastIndexOf('.')));
}
It would be interesting to see any "pure Java" solution (not involving out-of-JVM changes to runtime) which can workaround this.
You may wonder how JVM itself loads java.* classes? Well, they loaded by so called bootstrap loader, during initialization of JVM instance. I assume, there's no public API to that classloader.
I don't know what you are trying to do exactly, but I can suggest a different approach.
In java String class is final, so, it can't be extended. Create a wrapper class which has your additional methods and a String field.. Now you can define and call show() on your class (You can't do it on the String directly..) If split() is called on your class, then just delegate the call to String class's split().
expose a method getInstance() in your wrapper . Whenever myWrapper.getInstance() is called, call new String() from there..

How to access package via Package.getPackage(...)?

In my current project I would like to store some configuration data in a package annotation and to access it by some CDI producers. If the annotation is not found in the current package the producers will search for it upward in the package hierarchy.
So far so good. Unfortunately it seems so that I can access an existing package via Package.getPackage("my.package") only after the first access to one of its classes or interfaces.
The following example illustrates this behaviour:
Class in package a.b
package a.b;
public class ClassInMitte {
}
Example programm to access the package oben.mitte
package other;
public class Refl {
public static void main(String[] args)
{
Package viaName = Package.getPackage("a.b");
System.out.println(viaName.getName());
System.out.println(viaName.hashCode());
}
}
Running Refl results in a NullPointerException. But if I add new ClassInMitte() as first statement I can access the package information. Somehow I must access the content of a package before I can access the package information itself. This makes sense since otherwise the classloaders must scan the whole classpath while starting.
But netherless is there an easy way to access package information without accessing the content of the package before? I know I could use frameworks like reflections but a 'lightweight' solution would be my prefered solution.
Package.getPackage only returns packages that are already known to the current class loader, and the only way to do that is by loading a class from that package. It's basically a wrapper for ClassLoader.getPackage.

Dynamic class load in Java - refer classes

I am just testing dynamic class load and am doing this:
package P1;
public class Class1
{
public static void main(String[] args)
{
Bird myBird = null;
String myClassName = "P2.Bird";
Class x = Class.forName(myClassName);
myBird = (Bird)x.newInstance();
}
}
Bird is a class from package P2, and Class1 is from P1. What should I add in the code to make this work, as the String myClassName... line shows an error (class not found). I tried the same code after moving Bird in package P1, even then it doesn't work.
Related question: Why would someone use dynamic class load, does it have any advantages? It's much simpler(at least for me at first glance) to just use the "new" operator for static class loading, and in that case I know how to refer the class from a different package. Many thanks!
For the answer to your first question try mentioning full Package name. I have tried it and it works
Your Bird class provides a default public constructor with no arguments?
Dynamic class loading can be useful for example to specify the class you want to use in a configuration file (you will come across that if you ever use log4j, or other libraries that allow the use of your own implementation to one of their interfaces). In that case, the library does not know about which class you will use, and you don't have to write code to initialise the library (which would be the alternative to dynamic class loading, but which is less convenient)

In java how do you refer to a class that is in the default package of a third party library?

I have downloaded a third party library and they have classes I need to refer to in the default package? How do I import these classes?
It's not possible directly with the compiler. Sun removed this capability. If something is in the default namespace, everything must be in the default namespace.
However, you can do it using the ClassLoader. Assuming the class is called Thirdparty, and it has a static method call doSomething(), you can execute it like this:
Class clazz = ClassLoader.getSystemClassLoader().loadClass("Thirdparty");
java.lang.reflect.Method method = clazz.getMethod("doSomething");
method.invoke(null);
This is tedious to say the least...
Long ago, sometime before Java 1.5, you used to be able to import Thirdparty; (a class from the unnamed/default namespace), but no longer. See this Java bug report. A bug report asking for a workaround to not being able to use classes from the default namespace suggests to use the JDK 1.3.1 compiler.
To avoid the tedious method.invoke() calls, I adapted the above solution:
Write an interface for the desired functionality in your desired my.package
package my.package;
public interface MyAdaptorInterface{
public void function1();
...
}
Write an adaptor in the default package:
public class MyAdaptor implements my.package.MyAdaptorInterface{
public void function1(){thirdparty.function1();}
...
}
Use ClassLoader/Typecast to access object from my.package
package my.package;
Class clazz = ClassLoader.getSystemClassLoader().loadClass("MyAdaptor");
MyAdaptorInterface myObj = (MyAdaptorInterface)clazz.newInstance();
myObj.function1();

Categories

Resources