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 char* res = realpath((char *)dlinfo.dli_fname, buf); 125 (void)res; 126 len = strlen(buf); 127 p = strrchr(buf, '/'); 128 129 /* 130 * The code below is responsible for: 131 * 1. Loading appropriate awt library, i.e. libawt_xawt or libawt_headless 132 * 2. Set the "sun.font.fontmanager" system property. 133 */ 134 135 fmProp = (*env)->NewStringUTF(env, "sun.font.fontmanager"); 136 CHECK_EXCEPTION_FATAL(env, "Could not allocate font manager property"); 137 138 #ifdef MACOSX 139 fmanager = (*env)->NewStringUTF(env, "sun.font.CFontManager"); 140 tk = LWAWT_PATH; 141 #else 142 fmanager = (*env)->NewStringUTF(env, "sun.awt.X11FontManager"); 143 tk = XAWT_PATH; 144 #endif 145 CHECK_EXCEPTION_FATAL(env, "Could not allocate font manager name"); 146 147 if (fmanager && fmProp) { 148 JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "setProperty", 149 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", 150 fmProp, fmanager); 151 CHECK_EXCEPTION_FATAL(env, "Could not allocate set properties"); 152 } 153 154 #ifndef MACOSX 155 if (AWTIsHeadless()) { 156 tk = HEADLESS_PATH; 157 } 158 #endif 159 160 /* Calculate library name to load */ 161 strncpy(p, tk, MAXPATHLEN-len-1); 162 163 if (fmProp) { 164 (*env)->DeleteLocalRef(env, fmProp); 165 } 166 if (fmanager) { 167 (*env)->DeleteLocalRef(env, fmanager); 168 } 169 170 jstring jbuf = JNU_NewStringPlatform(env, buf); 171 CHECK_EXCEPTION_FATAL(env, "Could not allocate library name"); 172 JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "load", 173 "(Ljava/lang/String;)V", 174 jbuf); 175 176 awtHandle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL); 177 178 return JNI_VERSION_1_2; 179 } 180 181 JNIEXPORT jint JNICALL 182 DEF_JNI_OnLoad(JavaVM *vm, void *reserved) 183 { 184 return AWT_OnLoad(vm, reserved); 185 } 186 187 /* 188 * This entry point must remain in libawt.so as part of a contract 189 * with the CDE variant of Java Media Framework. (sdtjmplay) 190 * Reflect this call over to the correct libawt_<toolkit>.so. 191 */ 192 JNIEXPORT void JNICALL 193 Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this, 194 jobject frame, jstring jcommand) 195 { 196 /* type of the old backdoor function */ 197 typedef void JNICALL 198 XsessionWMcommand_type(JNIEnv *env, jobject this, 199 jobject frame, jstring jcommand); 200 201 static XsessionWMcommand_type *XsessionWMcommand = NULL; 202 203 if (XsessionWMcommand == NULL && awtHandle == NULL) { 204 return; 205 } 206 207 XsessionWMcommand = (XsessionWMcommand_type *) 208 dlsym(awtHandle, "Java_sun_awt_motif_XsessionWMcommand"); 209 210 if (XsessionWMcommand == NULL) 211 return; 212 213 (*XsessionWMcommand)(env, this, frame, jcommand); 214 } 215 216 217 /* 218 * This entry point must remain in libawt.so as part of a contract 219 * with the CDE variant of Java Media Framework. (sdtjmplay) 220 * Reflect this call over to the correct libawt_<toolkit>.so. 221 */ 222 JNIEXPORT void JNICALL 223 Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jargv) 224 { 225 typedef void JNICALL 226 XsessionWMcommand_New_type(JNIEnv *env, jobjectArray jargv); 227 228 static XsessionWMcommand_New_type *XsessionWMcommand = NULL; 229 230 if (XsessionWMcommand == NULL && awtHandle == NULL) { 231 return; 232 } 233 234 XsessionWMcommand = (XsessionWMcommand_New_type *) 235 dlsym(awtHandle, "Java_sun_awt_motif_XsessionWMcommand_New"); 236 237 if (XsessionWMcommand == NULL) 238 return; 239 240 (*XsessionWMcommand)(env, jargv); 241 }