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 =
 101             [GlassHelper ClassForName:"com.sun.glass.ui.Application" withEnv:env];
 102         if (_ApplicationClass) {
 103             _ApplicationClass = (*env)->NewGlobalRef(env, _ApplicationClass);
 104         }
 105         GLASS_CHECK_EXCEPTION(env);
 106     }
 107     if (_ApplicationClass == NULL)
 108     {
 109         NSLog(@"GlassHelper error: _ApplicationClass == NULL");
 110     }
 111     return _ApplicationClass;
 112 }
 113 
 114 + (jmethodID)ApplicationNotifyWillFinishLaunchingMethod
 115 {
 116     static jmethodID _ApplicationNotifyWillFinishLaunchingMethod = NULL;
 117     if (_ApplicationNotifyWillFinishLaunchingMethod == NULL)
 118     {
 119         GET_MAIN_JENV;
 120         _ApplicationNotifyWillFinishLaunchingMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillFinishLaunching", "()V");
 121         GLASS_CHECK_EXCEPTION(env);
 122     }
 123     if (_ApplicationNotifyWillFinishLaunchingMethod == NULL)
 124     {
 125         NSLog(@"GlassHelper error: _ApplicationNotifyWillFinishLaunchingMethod == NULL");
 126     }
 127     return _ApplicationNotifyWillFinishLaunchingMethod;
 128 }
 129 
 130 + (jmethodID)ApplicationNotifyDidFinishLaunchingMethod
 131 {
 132     static jmethodID _ApplicationNotifyDidFinishLaunchingMethod = NULL;
 133     if (_ApplicationNotifyDidFinishLaunchingMethod == NULL)
 134     {
 135         GET_MAIN_JENV;
 136         _ApplicationNotifyDidFinishLaunchingMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyDidFinishLaunching", "()V");
 137         GLASS_CHECK_EXCEPTION(env);
 138     }
 139     if (_ApplicationNotifyDidFinishLaunchingMethod == NULL)
 140     {
 141         NSLog(@"GlassHelper error: _ApplicationNotifyDidFinishLaunchingMethod == NULL");
 142     }
 143     return _ApplicationNotifyDidFinishLaunchingMethod;
 144 }
 145 
 146 + (jmethodID)ApplicationNotifyWillBecomeActiveMethod
 147 {
 148     static jmethodID _ApplicationNotifyWillBecomeActiveMethod = NULL;
 149     if (_ApplicationNotifyWillBecomeActiveMethod == NULL)
 150     {
 151         GET_MAIN_JENV;
 152         _ApplicationNotifyWillBecomeActiveMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillBecomeActive", "()V");
 153         GLASS_CHECK_EXCEPTION(env);
 154     }
 155     if (_ApplicationNotifyWillBecomeActiveMethod == NULL)
 156     {
 157         NSLog(@"GlassHelper error: _ApplicationNotifyWillBecomeActiveMethod == NULL");
 158     }
 159     return _ApplicationNotifyWillBecomeActiveMethod;
 160 }
 161 
 162 + (jmethodID)ApplicationNotifyDidBecomeActiveMethod
 163 {
 164     static jmethodID _ApplicationNotifyDidBecomeActiveMethod = NULL;
 165     if (_ApplicationNotifyDidBecomeActiveMethod == NULL)
 166     {
 167         GET_MAIN_JENV;
 168         _ApplicationNotifyDidBecomeActiveMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyDidBecomeActive", "()V");
 169         GLASS_CHECK_EXCEPTION(env);
 170     }
 171     if (_ApplicationNotifyDidBecomeActiveMethod == NULL)
 172     {
 173         NSLog(@"GlassHelper error: _ApplicationNotifyDidBecomeActiveMethod == NULL");
 174     }
 175     return _ApplicationNotifyDidBecomeActiveMethod;
 176 }
 177 
 178 + (jmethodID)ApplicationNotifyWillResignActiveMethod
 179 {
 180     static jmethodID _ApplicationNotifyWillResignActiveMethod = NULL;
 181     if (_ApplicationNotifyWillResignActiveMethod == NULL)
 182     {
 183         GET_MAIN_JENV;
 184         _ApplicationNotifyWillResignActiveMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillResignActive", "()V");
 185         GLASS_CHECK_EXCEPTION(env);
 186     }
 187     if (_ApplicationNotifyWillResignActiveMethod == NULL)
 188     {
 189         NSLog(@"GlassHelper error: _ApplicationNotifyWillResignActiveMethod == NULL");
 190     }
 191     return _ApplicationNotifyWillResignActiveMethod;
 192 }
 193 
 194 + (jmethodID)ApplicationNotifyDidResignActiveMethod
 195 {
 196     static jmethodID _ApplicationNotifyDidResignActiveMethod = NULL;
 197     if (_ApplicationNotifyDidResignActiveMethod == NULL)
 198     {
 199         GET_MAIN_JENV;
 200         _ApplicationNotifyDidResignActiveMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyDidResignActive", "()V");
 201         GLASS_CHECK_EXCEPTION(env);
 202     }
 203     if (_ApplicationNotifyDidResignActiveMethod == NULL)
 204     {
 205         NSLog(@"GlassHelper error: _ApplicationNotifyDidResignActiveMethod == NULL");
 206     }
 207     return _ApplicationNotifyDidResignActiveMethod;
 208 }
 209 
 210 + (jmethodID)ApplicationNotifyWillHideMethod
 211 {
 212     static jmethodID _ApplicationNotifyWillHideMethod = NULL;
 213     if (_ApplicationNotifyWillHideMethod == NULL)
 214     {
 215         GET_MAIN_JENV;
 216         _ApplicationNotifyWillHideMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillHide", "()V");
 217         GLASS_CHECK_EXCEPTION(env);
 218     }
 219     if (_ApplicationNotifyWillHideMethod == NULL)
 220     {
 221         NSLog(@"GlassHelper error: _ApplicationNotifyWillHideMethod == NULL");
 222     }
 223     return _ApplicationNotifyWillHideMethod;
 224 }
 225 
 226 + (jmethodID)ApplicationNotifyDidHideMethod
 227 {
 228     static jmethodID _ApplicationNotifyDidHideMethod = NULL;
 229     if (_ApplicationNotifyDidHideMethod == NULL)
 230     {
 231         GET_MAIN_JENV;
 232         _ApplicationNotifyDidHideMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyDidHide", "()V");
 233         GLASS_CHECK_EXCEPTION(env);
 234     }
 235     if (_ApplicationNotifyDidHideMethod == NULL)
 236     {
 237         NSLog(@"GlassHelper error: _ApplicationNotifyDidHideMethod == NULL");
 238     }
 239     return _ApplicationNotifyDidHideMethod;
 240 }
 241 
 242 + (jmethodID)ApplicationNotifyWillUnhideMethod
 243 {
 244     static jmethodID _ApplicationNotifyWillUnhideMethod = NULL;
 245     if (_ApplicationNotifyWillUnhideMethod == NULL)
 246     {
 247         GET_MAIN_JENV;
 248         _ApplicationNotifyWillUnhideMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillUnhide", "()V");
 249         GLASS_CHECK_EXCEPTION(env);
 250     }
 251     if (_ApplicationNotifyWillUnhideMethod == NULL)
 252     {
 253         NSLog(@"GlassHelper error: _ApplicationNotifyWillUnhideMethod == NULL");
 254     }
 255     return _ApplicationNotifyWillUnhideMethod;
 256 }
 257 
 258 + (jmethodID)ApplicationNotifyDidUnhideMethod
 259 {
 260     static jmethodID _ApplicationNotifyDidUnhideMethod = NULL;
 261     if (_ApplicationNotifyDidUnhideMethod == NULL)
 262     {
 263         GET_MAIN_JENV;
 264         _ApplicationNotifyDidUnhideMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyDidUnhide", "()V");
 265         GLASS_CHECK_EXCEPTION(env);
 266     }
 267     if (_ApplicationNotifyDidUnhideMethod == NULL)
 268     {
 269         NSLog(@"GlassHelper error: _ApplicationNotifyDidUnhideMethod == NULL");
 270     }
 271     return _ApplicationNotifyDidUnhideMethod;
 272 }
 273 
 274 + (jmethodID)ApplicationNotifyOpenFilesMethod
 275 {
 276     static jmethodID _ApplicationNotifyOpenFilesMethod = NULL;
 277     if (_ApplicationNotifyOpenFilesMethod == NULL)
 278     {
 279         GET_MAIN_JENV;
 280         _ApplicationNotifyOpenFilesMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyOpenFiles", "([Ljava/lang/String;)V");
 281         GLASS_CHECK_EXCEPTION(env);
 282     }
 283     if (_ApplicationNotifyOpenFilesMethod == NULL)
 284     {
 285         NSLog(@"GlassHelper error: _ApplicationNotifyOpenFilesMethod == NULL");
 286     }
 287     return _ApplicationNotifyOpenFilesMethod;
 288 }
 289 
 290 + (jmethodID)ApplicationNotifyWillQuitMethod
 291 {
 292     static jmethodID _ApplicationNotifyWillQuitMethod = NULL;
 293     if (_ApplicationNotifyWillQuitMethod == NULL)
 294     {
 295         GET_MAIN_JENV;
 296         _ApplicationNotifyWillQuitMethod = (*env)->GetMethodID(env, [GlassHelper ApplicationClass], "notifyWillQuit", "()V");
 297         GLASS_CHECK_EXCEPTION(env);
 298     }
 299     if (_ApplicationNotifyWillQuitMethod == NULL)
 300     {
 301         NSLog(@"GlassHelper error: _ApplicationNotifyWillQuitMethod == NULL");
 302     }
 303     return _ApplicationNotifyWillQuitMethod;
 304 }
 305 
 306 #pragma mark --- Invocation
 307 
 308 + (BOOL)InvokeSelectorIfAvailable:(SEL)aSelector forClass:(Class)aClass withArgument:(void *)anArgument withReturnValue:(void **)aReturnValue
 309 {
 310     if ([aClass respondsToSelector:aSelector] == YES)
 311     {
 312         NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[aClass methodSignatureForSelector:aSelector]];
 313         [invocation setSelector:aSelector];
 314         [invocation setTarget:aClass];
 315 
 316         if (anArgument != NULL)
 317         {
 318             [invocation setArgument:anArgument atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, which are set automatically by NSInvocation
 319         }
 320 
 321         [invocation invoke];
 322 
 323         if (aReturnValue != NULL)
 324         {
 325             [invocation getReturnValue:aReturnValue];
 326         }
 327 
 328         return YES;
 329     }
 330     else
 331     {
 332         return NO;
 333     }
 334 }
 335 
 336 + (NSString*)nsStringWithJavaString:(jstring)javaString withEnv:(JNIEnv*)env
 337 {
 338     NSString *string = @"";
 339     if (javaString != NULL)
 340     {
 341         const jchar* jstrChars = (*env)->GetStringChars(env, javaString, NULL);
 342         jsize size = (*env)->GetStringLength(env, javaString);
 343         if (size > 0)
 344         {
 345             string = [[[NSString alloc] initWithCharacters:jstrChars length:(NSUInteger)size] autorelease];
 346         }
 347         (*env)->ReleaseStringChars(env, javaString, jstrChars);
 348     }
 349     return string;
 350 }
 351 
 352 @end