1 /*
   2  * Copyright (c) 2011, 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 #import "GlassMacros.h"
  27 #import "GlassHelper.h"
  28 
  29 @implementation GlassHelper
  30 
  31 #pragma mark --- ClassLoader
  32 
  33 static volatile jobject glassClassLoader = NULL;
  34 + (void)SetGlassClassLoader:(jobject)classLoader withEnv:(JNIEnv*)env
  35 {
  36     glassClassLoader = (*env)->NewGlobalRef(env, classLoader);
  37 }
  38 
  39 /*
  40  * Function to find a glass class using the glass class loader. All glass
  41  * classes must be looked up using this function rather than FindClass so that
  42  * the correct ClassLoader is used.
  43  *
  44  * Note that the className passed to this function must use "." rather than "/"
  45  * as a package separator.
  46  */
  47 + (jclass)ClassForName:(char*)className withEnv:(JNIEnv*)env
  48 {
  49     static jclass classCls = NULL;
  50     if (classCls == NULL)
  51     {
  52         jclass jcls = (*env)->FindClass(env, "java/lang/Class");
  53         GLASS_CHECK_EXCEPTION(env);
  54         if (jcls == NULL)
  55         {
  56             NSLog(@"GlassHelper error: jcls == NULL");
  57             return NULL;
  58         }
  59         classCls = (*env)->NewGlobalRef(env, jcls);
  60     }
  61     if (classCls == NULL)
  62     {
  63         NSLog(@"GlassHelper error: classCls == NULL");
  64         return NULL;
  65     }
  66 
  67     static jmethodID forNameMID = NULL;
  68     if (forNameMID == NULL)
  69     {
  70         forNameMID = (*env)->GetStaticMethodID(env, classCls, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
  71         GLASS_CHECK_EXCEPTION(env);
  72     }
  73     if (forNameMID == NULL)
  74     {
  75         NSLog(@"GlassHelper error: forNameMID == NULL");
  76         return NULL;
  77     }
  78 
  79     jstring classNameStr = (*env)->NewStringUTF(env, className);
  80     if (classNameStr == NULL)
  81     {
  82         NSLog(@"GlassHelper error: classNameStrs == NULL");
  83         return NULL;
  84     }
  85 
  86     jclass foundClass = (*env)->CallStaticObjectMethod(env, classCls,
  87         forNameMID,classNameStr, JNI_TRUE, glassClassLoader);
  88     GLASS_CHECK_EXCEPTION(env);
  89     (*env)->DeleteLocalRef(env, classNameStr);
  90 
  91     return foundClass;
  92 }
  93 
  94 + (jclass)ApplicationClass
  95 {
  96     static jclass _ApplicationClass = NULL;
  97     if (_ApplicationClass == NULL)
  98     {
  99         GET_MAIN_JENV;
 100         _ApplicationClass = (*env)->NewGlobalRef(env, [GlassHelper ClassForName:"com.sun.glass.ui.Application" withEnv:env]);
 101         GLASS_CHECK_EXCEPTION(env);
 102     }
 103     if (_ApplicationClass == NULL)
 104     {
 105         NSLog(@"GlassHelper error: _ApplicationClass == NULL");
 106     }
 107     return _ApplicationClass;
 108 }
 109 
 110 + (jmethodID)ApplicationNotifyWillFinishLaunchingMethod
 111 {
 112     static jmethodID _ApplicationNotifyWillFinishLaunchingMethod = NULL;
 113     if (_ApplicationNotifyWillFinishLaunchingMethod == NULL)
 114     {
 115         GET_MAIN_JENV;
 116         _ApplicationNotifyWillFinishLaunchingMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillFinishLaunching", "()V");
 117         GLASS_CHECK_EXCEPTION(env);
 118     }
 119     if (_ApplicationNotifyWillFinishLaunchingMethod == NULL)
 120     {
 121         NSLog(@"GlassHelper error: _ApplicationNotifyWillFinishLaunchingMethod == NULL");
 122     }
 123     return _ApplicationNotifyWillFinishLaunchingMethod;
 124 }
 125 
 126 + (jmethodID)ApplicationNotifyDidFinishLaunchingMethod
 127 {
 128     static jmethodID _ApplicationNotifyDidFinishLaunchingMethod = NULL;
 129     if (_ApplicationNotifyDidFinishLaunchingMethod == NULL)
 130     {
 131         GET_MAIN_JENV;
 132         _ApplicationNotifyDidFinishLaunchingMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyDidFinishLaunching", "()V");
 133         GLASS_CHECK_EXCEPTION(env);
 134     }
 135     if (_ApplicationNotifyDidFinishLaunchingMethod == NULL)
 136     {
 137         NSLog(@"GlassHelper error: _ApplicationNotifyDidFinishLaunchingMethod == NULL");
 138     }
 139     return _ApplicationNotifyDidFinishLaunchingMethod;
 140 }
 141 
 142 + (jmethodID)ApplicationNotifyWillBecomeActiveMethod
 143 {
 144     static jmethodID _ApplicationNotifyWillBecomeActiveMethod = NULL;
 145     if (_ApplicationNotifyWillBecomeActiveMethod == NULL)
 146     {
 147         GET_MAIN_JENV;
 148         _ApplicationNotifyWillBecomeActiveMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillBecomeActive", "()V");
 149         GLASS_CHECK_EXCEPTION(env);
 150     }
 151     if (_ApplicationNotifyWillBecomeActiveMethod == NULL)
 152     {
 153         NSLog(@"GlassHelper error: _ApplicationNotifyWillBecomeActiveMethod == NULL");
 154     }
 155     return _ApplicationNotifyWillBecomeActiveMethod;
 156 }
 157 
 158 + (jmethodID)ApplicationNotifyDidBecomeActiveMethod
 159 {
 160     static jmethodID _ApplicationNotifyDidBecomeActiveMethod = NULL;
 161     if (_ApplicationNotifyDidBecomeActiveMethod == NULL)
 162     {
 163         GET_MAIN_JENV;
 164         _ApplicationNotifyDidBecomeActiveMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyDidBecomeActive", "()V");
 165         GLASS_CHECK_EXCEPTION(env);
 166     }
 167     if (_ApplicationNotifyDidBecomeActiveMethod == NULL)
 168     {
 169         NSLog(@"GlassHelper error: _ApplicationNotifyDidBecomeActiveMethod == NULL");
 170     }
 171     return _ApplicationNotifyDidBecomeActiveMethod;
 172 }
 173 
 174 + (jmethodID)ApplicationNotifyWillResignActiveMethod
 175 {
 176     static jmethodID _ApplicationNotifyWillResignActiveMethod = NULL;
 177     if (_ApplicationNotifyWillResignActiveMethod == NULL)
 178     {
 179         GET_MAIN_JENV;
 180         _ApplicationNotifyWillResignActiveMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillResignActive", "()V");
 181         GLASS_CHECK_EXCEPTION(env);
 182     }
 183     if (_ApplicationNotifyWillResignActiveMethod == NULL)
 184     {
 185         NSLog(@"GlassHelper error: _ApplicationNotifyWillResignActiveMethod == NULL");
 186     }
 187     return _ApplicationNotifyWillResignActiveMethod;
 188 }
 189 
 190 + (jmethodID)ApplicationNotifyDidResignActiveMethod
 191 {
 192     static jmethodID _ApplicationNotifyDidResignActiveMethod = NULL;
 193     if (_ApplicationNotifyDidResignActiveMethod == NULL)
 194     {
 195         GET_MAIN_JENV;
 196         _ApplicationNotifyDidResignActiveMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyDidResignActive", "()V");
 197         GLASS_CHECK_EXCEPTION(env);
 198     }
 199     if (_ApplicationNotifyDidResignActiveMethod == NULL)
 200     {
 201         NSLog(@"GlassHelper error: _ApplicationNotifyDidResignActiveMethod == NULL");
 202     }
 203     return _ApplicationNotifyDidResignActiveMethod;
 204 }
 205 
 206 + (jmethodID)ApplicationNotifyWillHideMethod
 207 {
 208     static jmethodID _ApplicationNotifyWillHideMethod = NULL;
 209     if (_ApplicationNotifyWillHideMethod == NULL)
 210     {
 211         GET_MAIN_JENV;
 212         _ApplicationNotifyWillHideMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillHide", "()V");
 213         GLASS_CHECK_EXCEPTION(env);
 214     }
 215     if (_ApplicationNotifyWillHideMethod == NULL)
 216     {
 217         NSLog(@"GlassHelper error: _ApplicationNotifyWillHideMethod == NULL");
 218     }
 219     return _ApplicationNotifyWillHideMethod;
 220 }
 221 
 222 + (jmethodID)ApplicationNotifyDidHideMethod
 223 {
 224     static jmethodID _ApplicationNotifyDidHideMethod = NULL;
 225     if (_ApplicationNotifyDidHideMethod == NULL)
 226     {
 227         GET_MAIN_JENV;
 228         _ApplicationNotifyDidHideMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyDidHide", "()V");
 229         GLASS_CHECK_EXCEPTION(env);
 230     }
 231     if (_ApplicationNotifyDidHideMethod == NULL)
 232     {
 233         NSLog(@"GlassHelper error: _ApplicationNotifyDidHideMethod == NULL");
 234     }
 235     return _ApplicationNotifyDidHideMethod;
 236 }
 237 
 238 + (jmethodID)ApplicationNotifyWillUnhideMethod
 239 {
 240     static jmethodID _ApplicationNotifyWillUnhideMethod = NULL;
 241     if (_ApplicationNotifyWillUnhideMethod == NULL)
 242     {
 243         GET_MAIN_JENV;
 244         _ApplicationNotifyWillUnhideMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillUnhide", "()V");
 245         GLASS_CHECK_EXCEPTION(env);
 246     }
 247     if (_ApplicationNotifyWillUnhideMethod == NULL)
 248     {
 249         NSLog(@"GlassHelper error: _ApplicationNotifyWillUnhideMethod == NULL");
 250     }
 251     return _ApplicationNotifyWillUnhideMethod;
 252 }
 253 
 254 + (jmethodID)ApplicationNotifyDidUnhideMethod
 255 {
 256     static jmethodID _ApplicationNotifyDidUnhideMethod = NULL;
 257     if (_ApplicationNotifyDidUnhideMethod == NULL)
 258     {
 259         GET_MAIN_JENV;
 260         _ApplicationNotifyDidUnhideMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyDidUnhide", "()V");
 261         GLASS_CHECK_EXCEPTION(env);
 262     }
 263     if (_ApplicationNotifyDidUnhideMethod == NULL)
 264     {
 265         NSLog(@"GlassHelper error: _ApplicationNotifyDidUnhideMethod == NULL");
 266     }
 267     return _ApplicationNotifyDidUnhideMethod;
 268 }
 269 
 270 + (jmethodID)ApplicationNotifyOpenFilesMethod
 271 {
 272     static jmethodID _ApplicationNotifyOpenFilesMethod = NULL;
 273     if (_ApplicationNotifyOpenFilesMethod == NULL)
 274     {
 275         GET_MAIN_JENV;
 276         _ApplicationNotifyOpenFilesMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyOpenFiles", "([Ljava/lang/String;)V");
 277         GLASS_CHECK_EXCEPTION(env);
 278     }
 279     if (_ApplicationNotifyOpenFilesMethod == NULL)
 280     {
 281         NSLog(@"GlassHelper error: _ApplicationNotifyOpenFilesMethod == NULL");
 282     }
 283     return _ApplicationNotifyOpenFilesMethod;
 284 }
 285 
 286 + (jmethodID)ApplicationNotifyWillQuitMethod
 287 {
 288     static jmethodID _ApplicationNotifyWillQuitMethod = NULL;
 289     if (_ApplicationNotifyWillQuitMethod == NULL)
 290     {
 291         GET_MAIN_JENV;
 292         _ApplicationNotifyWillQuitMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillQuit", "()V");
 293         GLASS_CHECK_EXCEPTION(env);
 294     }
 295     if (_ApplicationNotifyWillQuitMethod == NULL)
 296     {
 297         NSLog(@"GlassHelper error: _ApplicationNotifyWillQuitMethod == NULL");
 298     }
 299     return _ApplicationNotifyWillQuitMethod;
 300 }
 301 
 302 #pragma mark --- Invocation
 303 
 304 + (BOOL)InvokeSelectorIfAvailable:(SEL)aSelector forClass:(Class)aClass withArgument:(void *)anArgument withReturnValue:(void **)aReturnValue
 305 {
 306     if ([aClass respondsToSelector:aSelector] == YES)
 307     {
 308         NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[aClass methodSignatureForSelector:aSelector]];
 309         [invocation setSelector:aSelector];
 310         [invocation setTarget:aClass];
 311 
 312         if (anArgument != NULL)
 313         {
 314             [invocation setArgument:anArgument atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, which are set automatically by NSInvocation
 315         }
 316 
 317         [invocation invoke];
 318 
 319         if (aReturnValue != NULL)
 320         {
 321             [invocation getReturnValue:aReturnValue];
 322         }
 323 
 324         return YES;
 325     }
 326     else
 327     {
 328         return NO;
 329     }
 330 }
 331 
 332 + (NSString*)nsStringWithJavaString:(jstring)javaString withEnv:(JNIEnv*)env
 333 {
 334     NSString *string = @"";
 335     if (javaString != NULL)
 336     {
 337         const jchar* jstrChars = (*env)->GetStringChars(env, javaString, NULL);
 338         jsize size = (*env)->GetStringLength(env, javaString);
 339         if (size > 0)
 340         {
 341             string = [[[NSString alloc] initWithCharacters:jstrChars length:(NSUInteger)size] autorelease];
 342         }
 343         (*env)->ReleaseStringChars(env, javaString, jstrChars);
 344     }
 345     return string;
 346 }
 347 
 348 @end