summaryrefslogtreecommitdiff
blob: 7c35d1cb1242bd3e8e258c90f0360de96c852232 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
From baba2c213770972e79be6be4902716278f351fb4 Mon Sep 17 00:00:00 2001
From: James Le Cuirot <chewi@gentoo.org>
Date: Wed, 24 Aug 2016 23:32:13 +0100
Subject: [PATCH 1/2] Allow libjvm.so to be dlopen'd with --with-jvm-lib=dlopen

Having to set LD_LIBRARY_PATH is a pain and relying on the rpath can
be problematic when libjvm.so lives in a versioned directory. Some
distributions even allow per-user JVM selection so checking the value
of JAVA_HOME at runtime allows this choice to be respected.

libjvm.so's location is hard to predict (amd64 vs i386, jre or not?)
so ${JAVA_HOME}/bin/java -XshowSettings is executed to find its
location. If JAVA_HOME is not set then java is executed from the PATH
instead.
---
 gdal/configure                              | 11 +++++-
 gdal/configure.in                           |  7 +++-
 gdal/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp | 57 +++++++++++++++++++++++++++--
 gdal/port/cpl_config.h.in                   |  3 ++
 4 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/configure b/configure
index 75e4e279de..acdfa439de 100755
--- a/configure
+++ b/configure
@@ -1753,7 +1753,7 @@ Optional Packages:
   --with-python=ARG   Enable python bindings (ARG=yes, no, or path to python binary)
   --with-java       Include Java support (ARG=yes, no or JDK home path)  [default=no]
   --with-mdb       Include MDB driver
-  --with-jvm-lib=ARG        ARG points to Java libjvm path
+  --with-jvm-lib=ARG        ARG is dlopen or points to Java libjvm path
   --with-jvm-lib-add-rpath    Add the libjvm path to the RPATH (no by default)
   --with-rasdaman=DIR        Include rasdaman support (DIR is rasdaman's install dir).
   --with-armadillo=ARG       Include Armadillo support for faster TPS transform computation (ARG=yes/no/path to armadillo install root) [default=no]
@@ -29491,7 +29491,14 @@ if test "${with_jvm_lib_add_rpath+set}" = set; then :
 fi
 
 
-    if test "x$with_jvm_lib" != "x"; then
+    if test "x$with_jvm_lib" = "xdlopen"; then
+
+cat >>confdefs.h <<_ACEOF
+#define JVM_LIB_DLOPEN 1
+_ACEOF
+
+        JVM_LIB="-ldl"
+    elif test "x$with_jvm_lib" != "x"; then
         if test -d "$with_jvm_lib"; then
             saved_LDFLAGS="$LDFLAGS"
             LDFLAGS="$LDFLAGS -L$with_jvm_lib"
diff --git a/configure.in b/configure.in
index 91efa5a32a..546ff04049 100644
--- a/configure.in
+++ b/configure.in
@@ -4213,11 +4213,14 @@ if test "$with_mdb" = "yes" ; then
         AC_MSG_ERROR("--with-java must be specified.")
     fi
 
-    AC_ARG_WITH(jvm-lib,          [  --with-jvm-lib=[ARG]        ARG points to Java libjvm path],,)
+    AC_ARG_WITH(jvm-lib,          [  --with-jvm-lib=[ARG]        ARG is dlopen or points to Java libjvm path],,)
 
     AC_ARG_WITH(jvm-lib-add-rpath,[  --with-jvm-lib-add-rpath    Add the libjvm path to the RPATH (no by default)],,)
 
-    if test "x$with_jvm_lib" != "x"; then
+    if test "x$with_jvm_lib" = "xdlopen"; then
+        AC_DEFINE_UNQUOTED(JVM_LIB_DLOPEN, 1, [Define to 1 if libjvm.so should be dlopen'd])
+        JVM_LIB="-ldl"
+    elif test "x$with_jvm_lib" != "x"; then
         if test -d "$with_jvm_lib"; then
             saved_LDFLAGS="$LDFLAGS"
             LDFLAGS="$LDFLAGS -L$with_jvm_lib"
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
index b068adf777..bc54a115df 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
@@ -29,6 +29,11 @@
 
 #include "ogr_mdb.h"
 
+#if JVM_LIB_DLOPEN
+#include <limits.h>
+#include <stdio.h>
+#endif
+
 CPL_CVSID("$Id: ogrmdbjackcess.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static JavaVM *jvm_static = NULL;
@@ -161,9 +166,41 @@ int OGRMDBJavaEnv::Init()
     {
         JavaVM* vmBuf[1];
         jsize nVMs;
+        int ret = 0;
+
+#if JVM_LIB_DLOPEN
+        const char *jvmLibPtr = "libjvm.so";
+        char jvmLib[PATH_MAX];
+
+        FILE *javaCmd = popen("\"${JAVA_HOME}${JAVA_HOME:+/bin/}java\" -XshowSettings 2>&1 | sed -n '/\\bsun\\.boot\\.library\\.path =/s:.* = \\(.*\\):\\1/server/libjvm.so:p'", "r");
+
+        if (javaCmd != NULL)
+        {
+            size_t javaCmdRead = fread(jvmLib, 1, PATH_MAX, javaCmd);
+            ret = pclose(javaCmd);
+
+            if (ret == 0 && javaCmdRead >= 2)
+            {
+                /* Chomp the new line */
+                jvmLib[javaCmdRead - 1] = '\0';
+                jvmLibPtr = jvmLib;
+            }
+        }
+
+        jint (*pfnJNI_GetCreatedJavaVMs)(JavaVM **, jsize, jsize *);
+        pfnJNI_GetCreatedJavaVMs = (jint (*)(JavaVM **, jsize, jsize *))
+            CPLGetSymbol(jvmLibPtr, "JNI_GetCreatedJavaVMs");
+
+        if (pfnJNI_GetCreatedJavaVMs == NULL)
+            return FALSE;
+        else
+            ret = pfnJNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs);
+#else
+        ret = JNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs);
+#endif
 
         /* Are we already called from Java ? */
-        if (JNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs) == JNI_OK && nVMs == 1)
+        if (ret == JNI_OK && nVMs == 1)
         {
             jvm = vmBuf[0];
             if (jvm->GetEnv((void **)&env, JNI_VERSION_1_2) == JNI_OK)
@@ -194,8 +231,22 @@ int OGRMDBJavaEnv::Init()
                 args.nOptions = 0;
             args.ignoreUnrecognized = JNI_FALSE;
 
-            int ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
-            if (ret != 0 || jvm == NULL || env == NULL)
+#if JVM_LIB_DLOPEN
+            jint (*pfnJNI_CreateJavaVM)(JavaVM **, void **, void *);
+            pfnJNI_CreateJavaVM = (jint (*)(JavaVM **, void **, void *))
+                CPLGetSymbol(jvmLibPtr, "JNI_CreateJavaVM");
+
+            if (pfnJNI_CreateJavaVM == NULL)
+                return FALSE;
+            else
+                ret = pfnJNI_CreateJavaVM(&jvm, (void **)&env, &args);
+#else
+            ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
+#endif
+
+            CPLFree(pszClassPathOption);
+
+            if (ret != JNI_OK || jvm == NULL || env == NULL)
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "JNI_CreateJavaVM failed (%d)", ret);
                 return FALSE;
diff --git a/port/cpl_config.h.in b/port/cpl_config.h.in
index 313729fd3e..e8fa21140a 100644
--- a/port/cpl_config.h.in
+++ b/port/cpl_config.h.in
@@ -161,6 +161,9 @@
 /* For .cpp files, define as const if the declaration of iconv() needs const. */
 #undef ICONV_CPP_CONST
 
+/* Define to 1 if libjvm.so should be dlopen'd */
+#undef JVM_LIB_DLOPEN
+
 /* Define to the sub-directory in which libtool stores uninstalled libraries.
    */
 #undef LT_OBJDIR
-- 
2.11.0


From cd6bbb60ced62b6176482e86c54ab618e2592ac8 Mon Sep 17 00:00:00 2001
From: James Le Cuirot <chewi@gentoo.org>
Date: Thu, 25 Aug 2016 21:26:20 +0100
Subject: [PATCH 2/2] Fetch jackcess classpath using java-config instead of
 using CLASSPATH

---
 gdal/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
index bc54a115df..5b0972677e 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
@@ -218,19 +218,37 @@ int OGRMDBJavaEnv::Init()
             JavaVMInitArgs args;
             JavaVMOption options[1];
             args.version = JNI_VERSION_1_2;
-            const char* pszClassPath = CPLGetConfigOption("CLASSPATH", NULL);
-            CPLString osClassPathOption;
+
+            FILE *javaCmd = popen("java-config --with-dependencies --classpath=jackcess-1", "r");
+
+            const char* pszClassPath = NULL;
+            if (javaCmd != NULL)
+            {
+                pszClassPath = CPLReadLine(javaCmd);
+                ret = pclose(javaCmd);
+
+                if (ret != 0)
+                    pszClassPath = NULL;
+            }
+
+            if (pszClassPath == NULL)
+                pszClassPath = CPLGetConfigOption("CLASSPATH", NULL);
+
+            char* pszClassPathOption = NULL;
             if (pszClassPath)
             {
                 args.nOptions = 1;
-                osClassPathOption.Printf("-Djava.class.path=%s", pszClassPath);
-                options[0].optionString = (char*) osClassPathOption.c_str();
+                pszClassPathOption = CPLStrdup(CPLSPrintf("-Djava.class.path=%s", pszClassPath));
+                options[0].optionString = pszClassPathOption;
                 args.options = options;
             }
             else
                 args.nOptions = 0;
             args.ignoreUnrecognized = JNI_FALSE;
 
+            if (javaCmd != NULL)
+                CPLReadLine(NULL);
+
 #if JVM_LIB_DLOPEN
             jint (*pfnJNI_CreateJavaVM)(JavaVM **, void **, void *);
             pfnJNI_CreateJavaVM = (jint (*)(JavaVM **, void **, void *))
-- 
2.11.0