I am wondering if using loadjava to load the Java package called JSch.jar in an Oracle database and then loading another .java file, that utilizes the JSch package to connect over SSH, would be able to be executed within an Oracle database through a function or procedure.
I ask this before trying because I need to reach out to a DBA to try and load everything. I want to make sure it is doable because I am not very skilled in java as of yet and wouldn't know if something was impossible or if it just needs fixed.
Thanks.
Yes
Use something like:
loadjava -user USERNAME/PASSWORD#SID JSch.jar
Then create a static class method which uses the classes loaded from the Jar file:
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED MyJavaSource AS
import org.millea9805.jsch.JSchSomething;
public class MyClass {
public static String function_name()
{
JSchSomething.doSomething();
return "Something";
}
}
/
Then you can create a PL/SQL wrapper around the static Java method:
CREATE OR REPLACE FUNCTION DO_SOMETHING()
RETURN VARCHAR2
AS LANGUAGE JAVA
NAME 'MyClass.function_name() return java.lang.String';
/
A more detailed example using the XZ library to unzip BLOBs is here.
Related
While the referenced question is similar it speaks to putting the source code into the database not the class, also I would like to use the TOAD utilities to accomplish this.
So as proof of concept I have been attempting to load a java class into an Oracle 12c Database and access it via an Oracle function.
I opened Eclipse and created new project Hello with class Hello:
public class Hello {
public static String world()
{
return "Hello world";
}
}
I compiled it and now on my client I have
C:\Users\me\workspaces\Hello\bin\Hello.class
I opened up TOAD for an oracle 12c database, then I went to utilities / Java Manager and loaded my class:
TOAD says it successfully loaded. However, I'm not sure if it did.
Next, I went into the TOAD editor and created a function:
CREATE OR REPLACE function "DIR\KBD0010".helloworld RETURN VARCHAR2 AS
LANGUAGE JAVA NAME 'Hello.world () return java.lang.string';
Then I attempted to select it with a sql query:
select helloworld()
from dual;
And then I am getting:
ORA-29540: class Hello does not exist
I want to check that a filesystem is ntfs or fat32 and so on, and when i want to run it i get this:
java.lang.UnsatisfiedLinkError: Unable to load library 'Kernel32': Native library (linux-x86-64/libKernel32.so) not found in resource path ([file:/home/nszabo/workspace/Vidux/bin/, file:/home/nszabo/workspace/Vidux/external/common/org-json-2010-12-28.jar, and so on...
I tried this:
java -Djava.library.path="VolumeInformation.java"> -jar /usr/share/java/jna.jar
Error: Could not find or load main class .usr.share.java.jna.jar
What can be a problem? Thanks all for the help!
UPDATE:
here is my code where drop the error.
Kernel32.INSTANCE.GetVolumeInformation(
"C:\\",
lpVolumeNameBuffer,
nVolumeNameSize,
lpVolumeSerialNumber,
lpMaximumComponentLength,
lpFileSystemFlags,
lpFileSystemNameBuffer,
nFileSystemNameSize);
next one:
public static void main(String[] args) {
getFileSystemName();
}
and the final in Kernel32.java:
public Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("Kernel32", Kernel32.class, WIN32API_OPTIONS);
In Linux you can run the mount command with Runtime.exec() and parse the output to check which filesystems are mounted and which type they have.
You are trying to run Windows API functions on linux. You need to call filesystem inspection functions appropriate to linux instead.
To do so requires either a separate mapping (getfsfile("/path/to/fs") and look at the fs_vfstype field within the returned structure), or you can invoke the mount command as a process and parse its results as suggested by #ralf-m-petter.
I'm working on a project where there's the need to call some methods from dll files.
These two dlls are
EasySign.dll
EasySignJNI
EasySignJNI depends on EasySign.
I wrote the class to load EasySignJNI as follows:
package easysign;
class EasySign {
EasySign(){}
public native String EasyHashFile(String filename);
public native int EasySign(String pkcs11_driver,String pin, int type, String file_data, int out_format, String signed_file, String cert_out, int cert_format);
public native int EasyVerify(String cert_user, String file_data, String signed_file, String crl_file, String ca_file, String out_document);
static {
System.loadLibrary("EasySignJNI");
}
}
Now I would call these method from my main method like this:
public class Test {
public static void main(String[] args) throws IOException{
EasySign es = new EasySign();
System.out.println("EasyHashFile : " + es.EasyHashFile("test.txt"));
}
}
What I have to specify in the -Djava.library.path ? Only the path where my EasySignJNI.dll is located? It is possible to call native method in this way?
I'm using NetBeans for completeness.
EDIT:
I have noticed that the third party dll provided to me (the JNI dll in particular) defines method names without any package, so I'm forced to put the class that loads the dll in the default package. Is there any way to change only the dll method names including my own package name?
EDIT 2:
What I mean is that both EasySign.dll and EasySignJNI.dll are provided me as they are and I can't modify them (I have not the source code). The EasySignJNI is the JNI portion but inspecting it I have noticed thath the method sign is in the form: _java_EasySign_MethodName. When I load the dll in Java from my Easysign class (this class must reside in the "mypackage" package), I receive the jni unsatisfiedlinkerror because, if I understood right, I'm calling the "_java_mypackage_EasySign_MethodName" method, i.e the sign is different from the dll's one. So the only way to make it work is to rewrite the JNI part and build it to have the correct sign of the JNI method?
What I have to specify in the -Djava.library.path ? Only the path where my EasySignJNI.dll is located?
Correct, the operating system will locate the dependent EasySign.dll for you as long as it is available where the OS expects it to be.
It is possible to call native method in this way? I'm using NetBeans for completeness.
I read through your edit and you have successfully lost me. What default package are you referring to? (Remember that none of us know what EasySign.dll is) So, I am going to provide some info about how I do what you originally described and hopefully it will help.
First start by compiling EasySign if you have the src. Do not build a DLL or shared object, instead build a static library. If you do not have the src code for EasySign, or a prebuilt static library, you will be stuck with the dll and can continue to the next step.
Now you are ready to compile the jni portion. All of your JNI C code should basically translate your Java input/output to their JVM/Native types and call the appropriate functions in the DLL library. You want to keep this layer and thin and simple as possible because it is incredibly difficult to debug. Your C++ package names shouldn't really matter here and you can use what ever package name you want for your Java classes. You should be able to compile the JNI code and preferably static link to the EasySign.dll file so you don't need to worry about distributing it. If you must dynamically link, make sure EasySign.dll gets installed to a location that is on the DLL PATH / LDPATH because the OS will need to locate and load that file right after the JVM loads the JNI DLL.
At this point you should just be able to point -Djava.library.path at your JNI DLL's path and all should work.
I want to to run java code in Matlab so I can make use of what I have learned in java to enhance my MATLAB codes.
Totally quoting from here
Suppose your Java program is like this:
public class MyClass {
public static void main( String args[] ){}
}
To call this program in MATLAB:
Outside of MATLAB: Compile this class, so you have file MyClass.class
Locate the classpath.txt file for the MATLAB installation. The location of this file can be found by typing the following command in MATLAB command window:
which classpath.txt
Open the 'classpath.txt' with a text editor as Administrator. Add the full path for the directory with the MyClass.class to the end of the 'classpath.txt' file as a single line and save the file.
Restart MATLAB.
In MATLAB: to create an object of class MyClass, type:
o = MyClass
In MATLAB: to execute main() of object o, type:
javaMethod('main', o, '')
Alternately one may also add the directory in which the class files are to the dynamic path. Use the JAVAADDPATH command to add the directory (which contains the MyClass.class file) to JAVA's dynamic classpath. This also obviates the need to restart MATLAB. Once this is done the code can be invoked as follows:
o = MyClass;
javaMethod('main', o);
For a detailed tutorial please see this.
I use Eclipse Java 32Bit JDK. I am trying to import a 32-Bit DLL, which i got very few documentation for. I am using com.sun.jna.
The documentation tells me to call the method InitImagerIPC without any parameters.
As in this example i created an interface:
public interface ImagerIPC extends com.sun.jna.win32.StdCallLibrary{
HRESULT InitImagerIPC ();
}
When I try to import the DLL no error occurs.
ImagerIPC lib = (ImagerIPC) Native.loadLibrary ("ImagerIPC", ImagerIPC.class);
But I receive an UnsatisfiedLinkError if I mistype my DLL name. So I guess it's loaded correctly?
But when I try to call
lib.InitImagerIPC();
I get the UnsatisfiedLinkError. :(
Where's the mistake?
BTW: The DLL Export Viewer pulls out this info for the wanted method:
_InitImagerIPC#0 0x10001fc0 0x00001fc0 45 (0x2d)
ImagerIPC.dll J:\<my Path>\ImagerIPC.dll Exported Function
I am not sure about the naming. Do I also have to add the _?
Your DLL uses the stdcall calling convention, which typically has the compiler mangle function names to include the arguments' stack size. You need to use a StdCallFunctionMapper passed in as the Library.OPTION_FUNCTION_MAPPER option when you load your library (or recompile your library to use undecorated names).
Library.loadLibrary("myLib", myLib.class, new HashMap() { { put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper()); } });