1 | /* |
2 | * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. Oracle designates this |
8 | * particular file as subject to the "Classpath" exception as provided |
9 | * by Oracle in the LICENSE file that accompanied this code. |
10 | * |
11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | * version 2 for more details (a copy is included in the LICENSE file that |
15 | * accompanied this code). |
16 | * |
17 | * You should have received a copy of the GNU General Public License version |
18 | * 2 along with this work; if not, write to the Free Software Foundation, |
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
20 | * |
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 | * or visit www.oracle.com if you need additional information or have any |
23 | * questions. |
24 | */ |
25 | |
26 | #include <stdio.h> |
27 | #include <dlfcn.h> |
28 | #include <string.h> |
29 | #include <stdlib.h> |
30 | #include <jni.h> |
31 | #include <jni_util.h> |
32 | #include <jvm.h> |
33 | #include "gdefs.h" |
34 | |
35 | #include <sys/param.h> |
36 | #include <sys/utsname.h> |
37 | |
38 | #ifdef AIX |
39 | #include "porting_aix.h" /* For the 'dladdr' function. */ |
40 | #endif |
41 | |
42 | #ifdef DEBUG |
43 | #define VERBOSE_AWT_DEBUG |
44 | #endif |
45 | |
46 | static void *awtHandle = NULL; |
47 | |
48 | typedef jint JNICALL JNI_OnLoad_type(JavaVM *vm, void *reserved); |
49 | |
50 | /* Initialize the Java VM instance variable when the library is |
51 | first loaded */ |
52 | JNIEXPORT JavaVM *jvm; |
53 | |
54 | JNIEXPORT jboolean JNICALL AWTIsHeadless() { |
55 | static JNIEnv *env = NULL; |
56 | static jboolean isHeadless; |
57 | jmethodID headlessFn; |
58 | jclass graphicsEnvClass; |
59 | |
60 | if (env == NULL) { |
61 | env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
62 | graphicsEnvClass = (*env)->FindClass(env, |
63 | "java/awt/GraphicsEnvironment" ); |
64 | if (graphicsEnvClass == NULL) { |
65 | return JNI_TRUE; |
66 | } |
67 | headlessFn = (*env)->GetStaticMethodID(env, |
68 | graphicsEnvClass, "isHeadless" , "()Z" ); |
69 | if (headlessFn == NULL) { |
70 | return JNI_TRUE; |
71 | } |
72 | isHeadless = (*env)->CallStaticBooleanMethod(env, graphicsEnvClass, |
73 | headlessFn); |
74 | if ((*env)->ExceptionCheck(env)) { |
75 | (*env)->ExceptionClear(env); |
76 | return JNI_TRUE; |
77 | } |
78 | } |
79 | return isHeadless; |
80 | } |
81 | |
82 | #define CHECK_EXCEPTION_FATAL(env, message) \ |
83 | if ((*env)->ExceptionCheck(env)) { \ |
84 | (*env)->ExceptionClear(env); \ |
85 | (*env)->FatalError(env, message); \ |
86 | } |
87 | |
88 | /* |
89 | * Pathnames to the various awt toolkits |
90 | */ |
91 | |
92 | #ifdef MACOSX |
93 | #define LWAWT_PATH "/libawt_lwawt.dylib" |
94 | #define DEFAULT_PATH LWAWT_PATH |
95 | #else |
96 | #define XAWT_PATH "/libawt_xawt.so" |
97 | #define DEFAULT_PATH XAWT_PATH |
98 | #define HEADLESS_PATH "/libawt_headless.so" |
99 | #endif |
100 | |
101 | jint |
102 | AWT_OnLoad(JavaVM *vm, void *reserved) |
103 | { |
104 | Dl_info dlinfo; |
105 | char buf[MAXPATHLEN]; |
106 | int32_t len; |
107 | char *p, *tk; |
108 | JNI_OnLoad_type *JNI_OnLoad_ptr; |
109 | struct utsname name; |
110 | JNIEnv *env = (JNIEnv *)JNU_GetEnv(vm, JNI_VERSION_1_2); |
111 | void *v; |
112 | jstring fmanager = NULL; |
113 | jstring fmProp = NULL; |
114 | |
115 | if (awtHandle != NULL) { |
116 | /* Avoid several loading attempts */ |
117 | return JNI_VERSION_1_2; |
118 | } |
119 | |
120 | jvm = vm; |
121 | |
122 | /* Get address of this library and the directory containing it. */ |
123 | dladdr((void *)AWT_OnLoad, &dlinfo); |
124 | realpath((char *)dlinfo.dli_fname, buf); |
125 | len = strlen(buf); |
126 | p = strrchr(buf, '/'); |
127 | |
128 | /* |
129 | * The code below is responsible for: |
130 | * 1. Loading appropriate awt library, i.e. libawt_xawt or libawt_headless |
131 | * 2. Set the "sun.font.fontmanager" system property. |
132 | */ |
133 | |
134 | fmProp = (*env)->NewStringUTF(env, "sun.font.fontmanager" ); |
135 | CHECK_EXCEPTION_FATAL(env, "Could not allocate font manager property" ); |
136 | |
137 | #ifdef MACOSX |
138 | fmanager = (*env)->NewStringUTF(env, "sun.font.CFontManager" ); |
139 | tk = LWAWT_PATH; |
140 | #else |
141 | fmanager = (*env)->NewStringUTF(env, "sun.awt.X11FontManager" ); |
142 | tk = XAWT_PATH; |
143 | #endif |
144 | CHECK_EXCEPTION_FATAL(env, "Could not allocate font manager name" ); |
145 | |
146 | if (fmanager && fmProp) { |
147 | JNU_CallStaticMethodByName(env, NULL, "java/lang/System" , "setProperty" , |
148 | "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;" , |
149 | fmProp, fmanager); |
150 | CHECK_EXCEPTION_FATAL(env, "Could not allocate set properties" ); |
151 | } |
152 | |
153 | #ifndef MACOSX |
154 | if (AWTIsHeadless()) { |
155 | tk = HEADLESS_PATH; |
156 | } |
157 | #endif |
158 | |
159 | /* Calculate library name to load */ |
160 | strncpy(p, tk, MAXPATHLEN-len-1); |
161 | |
162 | if (fmProp) { |
163 | (*env)->DeleteLocalRef(env, fmProp); |
164 | } |
165 | if (fmanager) { |
166 | (*env)->DeleteLocalRef(env, fmanager); |
167 | } |
168 | |
169 | jstring jbuf = JNU_NewStringPlatform(env, buf); |
170 | CHECK_EXCEPTION_FATAL(env, "Could not allocate library name" ); |
171 | JNU_CallStaticMethodByName(env, NULL, "java/lang/System" , "load" , |
172 | "(Ljava/lang/String;)V" , |
173 | jbuf); |
174 | |
175 | awtHandle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL); |
176 | |
177 | return JNI_VERSION_1_2; |
178 | } |
179 | |
180 | JNIEXPORT jint JNICALL |
181 | DEF_JNI_OnLoad(JavaVM *vm, void *reserved) |
182 | { |
183 | return AWT_OnLoad(vm, reserved); |
184 | } |
185 | |
186 | /* |
187 | * This entry point must remain in libawt.so as part of a contract |
188 | * with the CDE variant of Java Media Framework. (sdtjmplay) |
189 | * Reflect this call over to the correct libawt_<toolkit>.so. |
190 | */ |
191 | JNIEXPORT void JNICALL |
192 | Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this, |
193 | jobject frame, jstring jcommand) |
194 | { |
195 | /* type of the old backdoor function */ |
196 | typedef void JNICALL |
197 | XsessionWMcommand_type(JNIEnv *env, jobject this, |
198 | jobject frame, jstring jcommand); |
199 | |
200 | static XsessionWMcommand_type *XsessionWMcommand = NULL; |
201 | |
202 | if (XsessionWMcommand == NULL && awtHandle == NULL) { |
203 | return; |
204 | } |
205 | |
206 | XsessionWMcommand = (XsessionWMcommand_type *) |
207 | dlsym(awtHandle, "Java_sun_awt_motif_XsessionWMcommand" ); |
208 | |
209 | if (XsessionWMcommand == NULL) |
210 | return; |
211 | |
212 | (*XsessionWMcommand)(env, this, frame, jcommand); |
213 | } |
214 | |
215 | |
216 | /* |
217 | * This entry point must remain in libawt.so as part of a contract |
218 | * with the CDE variant of Java Media Framework. (sdtjmplay) |
219 | * Reflect this call over to the correct libawt_<toolkit>.so. |
220 | */ |
221 | JNIEXPORT void JNICALL |
222 | Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jargv) |
223 | { |
224 | typedef void JNICALL |
225 | XsessionWMcommand_New_type(JNIEnv *env, jobjectArray jargv); |
226 | |
227 | static XsessionWMcommand_New_type *XsessionWMcommand = NULL; |
228 | |
229 | if (XsessionWMcommand == NULL && awtHandle == NULL) { |
230 | return; |
231 | } |
232 | |
233 | XsessionWMcommand = (XsessionWMcommand_New_type *) |
234 | dlsym(awtHandle, "Java_sun_awt_motif_XsessionWMcommand_New" ); |
235 | |
236 | if (XsessionWMcommand == NULL) |
237 | return; |
238 | |
239 | (*XsessionWMcommand)(env, jargv); |
240 | } |
241 | |