1 /* 2 * Copyright (c) 2000, 2014, 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 } 75 return isHeadless; 76 } 77 78 #define CHECK_EXCEPTION_FATAL(env, message) \ 79 if ((*env)->ExceptionCheck(env)) { \ 80 (*env)->ExceptionClear(env); \ 81 (*env)->FatalError(env, message); \ 82 } 83 84 /* 85 * Pathnames to the various awt toolkits 86 */ 87 88 #ifdef MACOSX 89 #define LWAWT_PATH "/libawt_lwawt.dylib" 90 #define DEFAULT_PATH LWAWT_PATH 91 #else 92 #define XAWT_PATH "/libawt_xawt.so" 93 #define DEFAULT_PATH XAWT_PATH 94 #define HEADLESS_PATH "/libawt_headless.so" 95 #endif 96 97 jint 98 AWT_OnLoad(JavaVM *vm, void *reserved) 99 { 100 Dl_info dlinfo; 101 char buf[MAXPATHLEN]; 102 int32_t len; 103 char *p, *tk; 104 JNI_OnLoad_type *JNI_OnLoad_ptr; 105 struct utsname name; 106 JNIEnv *env = (JNIEnv *)JNU_GetEnv(vm, JNI_VERSION_1_2); 107 void *v; 108 jstring fmanager = NULL; 109 jstring fmProp = NULL; 110 111 if (awtHandle != NULL) { 112 /* Avoid several loading attempts */ 113 return JNI_VERSION_1_2; 114 } 115 116 jvm = vm; 117 118 /* Get address of this library and the directory containing it. */ 119 dladdr((void *)AWT_OnLoad, &dlinfo); 120 realpath((char *)dlinfo.dli_fname, buf); 121 len = strlen(buf); 122 p = strrchr(buf, '/'); 123 124 /* 125 * The code below is responsible for: 126 * 1. Loading appropriate awt library, i.e. libawt_xawt or libawt_headless 127 * 2. Set the "sun.font.fontmanager" system property. 128 */ 129 130 fmProp = (*env)->NewStringUTF(env, "sun.font.fontmanager"); 131 CHECK_EXCEPTION_FATAL(env, "Could not allocate font manager property"); 132 133 #ifdef MACOSX 134 fmanager = (*env)->NewStringUTF(env, "sun.font.CFontManager"); 135 tk = LWAWT_PATH; 136 #else 137 fmanager = (*env)->NewStringUTF(env, "sun.awt.X11FontManager"); 138 tk = XAWT_PATH; 139 #endif 140 CHECK_EXCEPTION_FATAL(env, "Could not allocate font manager name"); 141 142 if (fmanager && fmProp) { 143 JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "setProperty", 144 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", 145 fmProp, fmanager); 146 CHECK_EXCEPTION_FATAL(env, "Could not allocate set properties"); 147 } 148 149 #ifndef MACOSX 150 if (AWTIsHeadless()) { 151 tk = HEADLESS_PATH; 152 } 153 #endif 154 155 /* Calculate library name to load */ 156 strncpy(p, tk, MAXPATHLEN-len-1); 157 158 if (fmProp) { 159 (*env)->DeleteLocalRef(env, fmProp); 160 } 161 if (fmanager) { 162 (*env)->DeleteLocalRef(env, fmanager); 163 } 164 165 jstring jbuf = JNU_NewStringPlatform(env, buf); 166 CHECK_EXCEPTION_FATAL(env, "Could not allocate library name"); 167 JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "load", 168 "(Ljava/lang/String;)V", 169 jbuf); 170 171 awtHandle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL); 172 173 return JNI_VERSION_1_2; 174 } 175 176 JNIEXPORT jint JNICALL 177 JNI_OnLoad(JavaVM *vm, void *reserved) 178 { 179 return AWT_OnLoad(vm, reserved); 180 } 181 182 /* 183 * This entry point must remain in libawt.so as part of a contract 184 * with the CDE variant of Java Media Framework. (sdtjmplay) 185 * Reflect this call over to the correct libawt_<toolkit>.so. 186 */ 187 JNIEXPORT void JNICALL 188 Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this, 189 jobject frame, jstring jcommand) 190 { 191 /* type of the old backdoor function */ 192 typedef void JNICALL 193 XsessionWMcommand_type(JNIEnv *env, jobject this, 194 jobject frame, jstring jcommand); 195 196 static XsessionWMcommand_type *XsessionWMcommand = NULL; 197 198 if (XsessionWMcommand == NULL && awtHandle == NULL) { 199 return; 200 } 201 202 XsessionWMcommand = (XsessionWMcommand_type *) 203 dlsym(awtHandle, "Java_sun_awt_motif_XsessionWMcommand"); 204 205 if (XsessionWMcommand == NULL) 206 return; 207 208 (*XsessionWMcommand)(env, this, frame, jcommand); 209 } 210 211 212 /* 213 * This entry point must remain in libawt.so as part of a contract 214 * with the CDE variant of Java Media Framework. (sdtjmplay) 215 * Reflect this call over to the correct libawt_<toolkit>.so. 216 */ 217 JNIEXPORT void JNICALL 218 Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jargv) 219 { 220 typedef void JNICALL 221 XsessionWMcommand_New_type(JNIEnv *env, jobjectArray jargv); 222 223 static XsessionWMcommand_New_type *XsessionWMcommand = NULL; 224 225 if (XsessionWMcommand == NULL && awtHandle == NULL) { 226 return; 227 } 228 229 XsessionWMcommand = (XsessionWMcommand_New_type *) 230 dlsym(awtHandle, "Java_sun_awt_motif_XsessionWMcommand_New"); 231 232 if (XsessionWMcommand == NULL) 233 return; 234 235 (*XsessionWMcommand)(env, jargv); 236 }