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
46static void *awtHandle = NULL;
47
48typedef jint JNICALL JNI_OnLoad_type(JavaVM *vm, void *reserved);
49
50/* Initialize the Java VM instance variable when the library is
51 first loaded */
52JNIEXPORT JavaVM *jvm;
53
54JNIEXPORT 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
101jint
102AWT_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
180JNIEXPORT jint JNICALL
181DEF_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 */
191JNIEXPORT void JNICALL
192Java_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 */
221JNIEXPORT void JNICALL
222Java_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