1 /* 2 * Copyright (c) 2000, 2015, 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 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 }