JNA version

Post here questions and problems related to oXygen frameworks/document types.
Isabelle
Posts: 113
Joined: Fri Jan 20, 2017 1:11 pm

JNA version

Post by Isabelle »

Hello,

I need to use JNA 5.3.1 in our application, but we have conflict with your patched version

Code: Select all

oxygen-patched-jna-21.1.0.2.jar:4.1.0
.
Moreover it seems there are incompatibilities between version 4.1.0 and 5.x of JNA :
https://github.com/java-native-access/j ... ng-changes

4.1.0 version of JNA seems to be an old version.
Do you plan to implement a 5.x version of JNA soon?

Regards,
Isabelle
Radu
Posts: 8283
Joined: Fri Jul 09, 2004 5:18 pm

Re: JNA version

Post by Radu »

Hi Isabelle,

I added an internal issue to look into upgrading our used JNA library but I cannot guarantee a timeline for it.
What errors do you get when you use the latest JNA library instead of ours? For the Author Component I think that we use JNA mostly for the Hunspell spell checker.
Another idea would be for you to create a separate class loader to load the newest JNA library and work with the library through this custom class loader.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Isabelle
Posts: 113
Joined: Fri Jan 20, 2017 1:11 pm

Re: JNA version

Post by Isabelle »

Hi Radu,

The last test I have made was to exclude jna-plateform from oxygen-sdk via pom maven like this :

Code: Select all

<dependency>
            <groupId>com.oxygenxml</groupId>
            <artifactId>oxygen-sdk</artifactId>
            <version>${oxygen.version}</version>           
            <exclusions>
                <exclusion>
                    <groupId>net.java.dev.jna</groupId>
                    <artifactId>jna-platform</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
And add the version 5.3.1 of jna-platform in the same pom file.

And here was the error I get :

Code: Select all

java.lang.UnsatisfiedLinkError: Can't obtain static method fromNative(Method, Object) from class com.sun.jna.Native
	at com.sun.jna.Native.initIDs(Native Method) ~[oxygen-patched-jna-21.1.0.2.jar:4.1.0 (b4)]
	at com.sun.jna.Native.<clinit>(Native.java:143) ~[oxygen-patched-jna-21.1.0.2.jar:4.1.0 (b4)]
	at com.sun.jna.Pointer.<clinit>(Pointer.java:41) ~[oxygen-patched-jna-21.1.0.2.jar:4.1.0 (b4)]
	at com.sun.jna.Structure.<clinit>(Structure.java:1949) ~[oxygen-patched-jna-21.1.0.2.jar:4.1.0 (b4)]
	at oshi.jna.platform.windows.VersionHelpers.IsWindowsVersionOrGreater(VersionHelpers.java:56) ~[oshi-core-3.13.4.jar:3.13.4]
	at oshi.jna.platform.windows.VersionHelpers.IsWindows7OrGreater(VersionHelpers.java:135) ~[oshi-core-3.13.4.jar:3.13.4]
	at oshi.software.os.windows.WindowsOperatingSystem.<clinit>(WindowsOperatingSystem.java:103) ~[oshi-core-3.13.4.jar:3.13.4]
	at oshi.SystemInfo.getOperatingSystem(SystemInfo.java:97) ~[oshi-core-3.13.4.jar:3.13.4]
	at com._4dconcept.quadrolic.asymmetric.systemid.strategy.v2.V2SystemIdStrategy.createPayload(V2SystemIdStrategy.java:36) ~[quadrolic-systemid-common-2.1.1-SNAPSHOT.jar:na]
	at com._4dconcept.quadrolic.asymmetric.systemid.strategy.v2.V2SystemIdStrategy.check(V2SystemIdStrategy.java:59) ~[quadrolic-systemid-common-2.1.1-SNAPSHOT.jar:na]
	at com._4dconcept.quadrolic.asymmetric.systemid.SystemId.check(SystemId.java:60) ~[quadrolic-systemid-common-2.1.1-SNAPSHOT.jar:na]
	at com._4dconcept.quadrolic.asymmetric.LicenseLoader.registerLicense(LicenseLoader.java:90) ~[quadrolic-asymmetric-2.1.1-SNAPSHOT.jar:na]
	at com._4dconcept.adam.author.standalone.AuthorComponentLicenseManager.checkLicense(AuthorComponentLicenseManager.java:64) ~[author-core-core-4.3.0-SNAPSHOT.jar:na]
	at com._4dconcept.adam.author.standalone.ApplicationLauncher.launch(ApplicationLauncher.java:107) ~[author-core-core-4.3.0-SNAPSHOT.jar:na]
	at com._4dconcept.adam.author.custo.adam.CustoLauncher.main(CustoLauncher.java:77) ~[classes/:na]
I made this test because of the result of

Code: Select all

mvn dependency:tree
which reveals that oxygen-sdk was the only one to get jna-platform 4.1.0.

I have already started to create a separate class loader for our need, thanks.
But it is a big development to workaround an old version of jna.

Regards,
Isabelle
Radu
Posts: 8283
Joined: Fri Jul 09, 2004 5:18 pm

Re: JNA version

Post by Radu »

Hi Isabelle,

From that stack trace it looks as if our patched JNA JAR library is still in the classpath before the newer JNA library when the application is run. Maybe you can remove it from the classpath completely when starting the application.
Also please tell me if using the custom class loader worked for you.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Isabelle
Posts: 113
Joined: Fri Jan 20, 2017 1:11 pm

Re: JNA version

Post by Isabelle »

Hello Radu,

Sorry for the late of my response, but before to report you, I want to make deep test.

I have tested to exclude your version of jna via maven.

Code: Select all

         <dependency>
            <groupId>com.oxygenxml</groupId>
            <artifactId>oxygen-sdk</artifactId>
            <version>${oxygen.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>net.java.dev.jna</groupId>
                    <artifactId>jna-platform</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.oxygenxml</groupId>
                    <artifactId>oxygen-patched-jna</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.oxygenxml</groupId>
                    <artifactId>native-jna</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
And I have specified a dependence to jna

Code: Select all

    <dependency>
      <groupId>net.java.dev.jna</groupId>
      <artifactId>jna</artifactId>
      <version>5.3.1</version>
    </dependency>
For the moment, it seems to work fine.
I will let you know if we get issues.
Thanks.

Regards,
Isabelle
Radu
Posts: 8283
Joined: Fri Jul 09, 2004 5:18 pm

Re: JNA version

Post by Radu »

Hi,

We released Oxygen 23 yesterday and it contains an updated JNA version 5.6.0.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Isabelle
Posts: 113
Joined: Fri Jan 20, 2017 1:11 pm

Re: JNA version

Post by Isabelle »

Hi everyone,

We use 24.0.0.2 of Oxygen sdk, and we still have oxygen-patched-jna-24.0.0.2.jar.
Can you please confirm to me, you use JNA only for Hunspell spell checker ?
We need to work on JNA and I want to be sure it will not impact other functionality of Oxygen framework.
Thanks.

Regards,
Isabelle
Radu
Posts: 8283
Joined: Fri Jul 09, 2004 5:18 pm

Re: JNA version

Post by Radu »

Hi Isabelle,

We use JNA in more places than the Hunspell spell checker to:
1) Move files to trash from the Project view
2) Show the native Windows file chooser when using our File->Open action.
3) Detect if Oxygen is working on a retina 4k monitor on Windows.
4) To read some keys from the Windows registries and for example determine if the HTTP proxy is enabled in the OS.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Isabelle
Posts: 113
Joined: Fri Jan 20, 2017 1:11 pm

Re: JNA version

Post by Isabelle »

Hello Radu,

Thanks for the feedback.
For this particular point :
4) To read some keys from the Windows registries and for example determine if the HTTP proxy is enabled in the OS.
Is it possible to retrieve values of HTTP proxy ?

An other point
We have noticed that Oxygen extract some dlls like :
375296 2021-11-26 07:37 hunspell-win-x86-32.dll
467456 2021-11-26 07:37 hunspell-win-x86-64.dll
... found in native-hunspell-24.0.0.2.jar
254464 2021-11-26 07:37 com/sun/jna/win32-x86-64/jnidispatch.dll
216576 2021-11-26 07:37 com/sun/jna/win32-x86/jnidispatch.dll
... found in native-jna-24.0.0.2.jar
67584 2021-11-26 07:37 WindowsNativeHelper32.dll
71680 2021-11-26 07:37 WindowsNativeHelper64.dll
... found in native-windows-helper-24.0.0.2.jar
We need to provide all dlls in a specific folder to our client and avoid any extract of dll at runtime.
Is it possible to define to Oxygen the path to all dlls instead of extract them ? (including jnidispatch)

Moreover, Can you tell us the original jna version you used to build the native-jna jar in Oxygen 24.0.* and 24.1.* ?

Thanks,
Regards,
Isabelle
Radu
Posts: 8283
Joined: Fri Jul 09, 2004 5:18 pm

Re: JNA version

Post by Radu »

Hi Isabelle,

So:
Is it possible to retrieve values of HTTP proxy ?
We do not have API for this.
We need to provide all dlls in a specific folder to our client and avoid any extract of dll at runtime.
Is it possible to define to Oxygen the path to all dlls instead of extract them ? (including jnidispatch)
I looked a bit in our code, if the directory where the application starts (new File(".")) has a "lib/hunspell" subfolder containing the libraries, we should load them from there.
If that does not work, can you check if this returns anything in your code "System.getProperty("com.oxygenxml.editor.lib.dir")"? If it has some value, you can create a "hunspell" subfolder inside it. If it does not, set its value as early as possible in your code to a folder which has a "hunspell" subfolder inside it containing the hunspell*.dll libraries and other platform specific libraries.
I think the place where Oxygen looks for "jnidispatch.dll" should be established in the same way.
Moreover, Can you tell us the original jna version you used to build the native-jna jar in Oxygen 24.0.* and 24.1.* ?
Our oxygen-patched.jna.jar should be based on JNA 5.7.0.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Isabelle
Posts: 113
Joined: Fri Jan 20, 2017 1:11 pm

Re: JNA version

Post by Isabelle »

Hello Radu,

I tried to launch our app with the following arguments :

Code: Select all

jna.nounpack=true
jna.debug=true
jna.debug_load=true
jna.debug_load.jna=true
jna.boot.library.path=C:/lib
jna.library.path=C:/lib
com.oxygenxml.editor.lib.dir=C:/lib
In the folder C:/lib, I have the jnidispatch.dll.

But when I start our app, I get this error from jna

Code: Select all

com.sun.jna.Native extractFromResourcePath
INFO: Looking in classpath from java.net.URLClassLoader@355da254 for /com/sun/jna/win32-x86-64/jnidispatch.dll
com.sun.jna.Native extractFromResourcePath
INFO: Found library resource at jar:file:/C:/Users/.m2/repository/com/oxygenxml/native-jna/24.1.0.0/native-jna-24.1.0.0.jar!/com/sun/jna/win32-x86-64/jnidispatch.dll
And because of jna.nounpack=true, our app can not use JNA.
It seems that com.oxygenxml.editor.lib.dir is not use for JNA.
Can you explain me how it works, please ?
I did not find any documentation on this.

Thanks,
Regards,
Isabelle
Radu
Posts: 8283
Joined: Fri Jul 09, 2004 5:18 pm

Re: JNA version

Post by Radu »

HI Isabelle,

About this remark:
I did not find any documentation on this.
You are trying to replace libraries bundled with the Author Component project with your own libraries. We do not officially support something like this and this means we also do not document such possibilities.
What I'm trying to do is look in our code and give you various hints based on what I find there.
In the folder C:/lib, I have the jnidispatch.dll.
You should probably try to place it like this:

Code: Select all

C:\lib\com\sun\jna\win32-x86-64\jnidispatch.dll
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Isabelle
Posts: 113
Joined: Fri Jan 20, 2017 1:11 pm

Re: JNA version

Post by Isabelle »

Hello Radu,
Radu wrote: Thu Sep 15, 2022 9:47 am
In the folder C:/lib, I have the jnidispatch.dll.
You should probably try to place it like this:

Code: Select all

C:\lib\com\sun\jna\win32-x86-64\jnidispatch.dll
I have already tried, but it is does not work neither.
Radu wrote: Thu Sep 15, 2022 9:47 am You are trying to replace libraries bundled with the Author Component project with your own libraries.
It is not what we want.
One of our client has very restrictive right access for users and they do not allowed them to have execution right on directory C:\Users\[USER]\AppData\Local\Temp.
This is why we can not let our application extract dll in that folder (JNA, HUNSPELL, ...).
What we want is to specify a specific path where our application can extract dll.
com.oxygenxml.editor.lib.dir works well for hunspell but not for jna.
For my test, I use dll from your native-* jars.

Regards,
Isabelle
Radu
Posts: 8283
Joined: Fri Jul 09, 2004 5:18 pm

Re: JNA version

Post by Radu »

Hi Isabelle,

So for the Hunspell checker we have custom code which searches for the dictionaries in the classpath (and in the "com.oxygenxml.editor.lib.dir" folder).
For JNA I do not see such code so it's probable the JNA libraries themselves have inside them code which searches for libraries like "com\sun\jna\win32-x86-64\jnidispatch.dll" in the classpath of the started Java process. So it would seem for JNA setting our custom "com.oxygenxml.editor.lib.dir" system property does not help. And we do not control from the Oxygen code how JNA looks for libraries.
The method where JNA loads libraries (and you can also find the source code online) is this one "com.sun.jna.Native.extractFromResourcePath(String, ClassLoader)". Pasting below how it looks like:

Code: Select all

    public static File extractFromResourcePath(String name, ClassLoader loader) throws IOException {
        final Level DEBUG = (DEBUG_LOAD
            || (DEBUG_JNA_LOAD && name.contains("jnidispatch"))) ? Level.INFO : Level.FINE;
        if (loader == null) {
            loader = Thread.currentThread().getContextClassLoader();
            // Context class loader is not guaranteed to be set
            if (loader == null) {
                loader = Native.class.getClassLoader();
            }
        }
        LOG.log(DEBUG, "Looking in classpath from {0} for {1}", new Object[]{loader, name});
        String libname = name.startsWith("/") ? name : NativeLibrary.mapSharedLibraryName(name);
        String resourcePath = name.startsWith("/") ? name : Platform.RESOURCE_PREFIX + "/" + libname;
        if (resourcePath.startsWith("/")) {
            resourcePath = resourcePath.substring(1);
        }
        URL url = loader.getResource(resourcePath);
        if (url == null && resourcePath.startsWith(Platform.RESOURCE_PREFIX)) {
            // If not found with the standard resource prefix, try without it
            url = loader.getResource(libname);
        }
        if (url == null) {
            String path = System.getProperty("java.class.path");
            if (loader instanceof URLClassLoader) {
                path = Arrays.asList(((URLClassLoader)loader).getURLs()).toString();
            }
            throw new IOException("Native library (" + resourcePath + ") not found in resource path (" + path + ")");
        }
        LOG.log(DEBUG, "Found library resource at {0}", url);

        File lib = null;
        if (url.getProtocol().toLowerCase().equals("file")) {
            try {
                lib = new File(new URI(url.toString()));
            }
            catch(URISyntaxException e) {
                lib = new File(url.getPath());
            }
            LOG.log(DEBUG, "Looking in {0}", lib.getAbsolutePath());
            if (!lib.exists()) {
                throw new IOException("File URL " + url + " could not be properly decoded");
            }
        }
        else if (!Boolean.getBoolean("jna.nounpack")) {
            InputStream is = loader.getResourceAsStream(resourcePath);
            if (is == null) {
                throw new IOException("Can't obtain InputStream for " + resourcePath);
            }

            FileOutputStream fos = null;
            try {
                // Suffix is required on windows, or library fails to load
                // Let Java pick the suffix, except on windows, to avoid
                // problems with Web Start.
                File dir = getTempDir();
                lib = File.createTempFile(JNA_TMPLIB_PREFIX, Platform.isWindows()?".dll":null, dir);
                if (!Boolean.getBoolean("jnidispatch.preserve")) {
                    lib.deleteOnExit();
                }
                LOG.log(DEBUG, "Extracting library to {0}", lib.getAbsolutePath());
                fos = new FileOutputStream(lib);
                int count;
                byte[] buf = new byte[1024];
                while ((count = is.read(buf, 0, buf.length)) > 0) {
                    fos.write(buf, 0, count);
                }
            }
            catch(IOException e) {
                throw new IOException("Failed to create temporary file for " + name + " library: " + e.getMessage());
            }
            finally {
                try { is.close(); } catch(IOException e) { }
                if (fos != null) {
                    try { fos.close(); } catch(IOException e) { }
                }
            }
        }
        return lib;
    }
It first seems to look for the dll in the class loader, meaning that if the "C:\lib" path would be in the classpath of the started Java process, the "com\sun\jna\win32-x86-64\jnidispatch.dll" dll should be found there.
I do not see in their code any place where the "jna.library.path" property that you are setting would be used.
I think the "jna.library.path" is a place where it looks for extra libraries to load (see "com.sun.jna.NativeLibrary.loadLibrary(String, Map<String, ?>)") and not its initial native libraries.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Isabelle
Posts: 113
Joined: Fri Jan 20, 2017 1:11 pm

Re: JNA version

Post by Isabelle »

Hello Radu,

Finally we found what we need.
When we build our own app, we extract your native-*.jar in our own lib folder (next to our .exe file).
Then we specify this three properties as jre options :

Code: Select all

                                       
  -Djna.nounpack=true
  -Djna.library.path=%EXEDIR%/lib
  -Dcom.oxygenxml.editor.home.url=file:///%EXEDIR%
  
This way, our app never extract dll, and we still can use your dll.

Regards,
Isabelle
Radu
Posts: 8283
Joined: Fri Jul 09, 2004 5:18 pm

Re: JNA version

Post by Radu »

Hi Isabelle,
I'm glad this works for you now.
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Post Reply