modules/fxpackager/src/main/native/library/common/MacPlatform.mm

Print this page




  21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 
  33 
  34 #include "Platform.h"
  35 
  36 #ifdef MAC
  37 
  38 #include "MacPlatform.h"
  39 #include "Helpers.h"
  40 #include "Package.h"


  41 
  42 #include <sys/sysctl.h>
  43 #include <pthread.h>
  44 #include <vector>
  45 
  46 #import <Foundation/Foundation.h>
  47 
  48 #include <CoreFoundation/CoreFoundation.h>
  49 #include <CoreFoundation/CFString.h>
  50 
  51 #ifdef __OBJC__
  52 #import <Cocoa/Cocoa.h>
  53 #endif //__OBJC__
  54 
  55 //--------------------------------------------------------------------------------------------------
  56 
  57 NSString* StringToNSString(TString Value) {
  58     NSString* result = [NSString stringWithCString:Value.c_str()
  59                                           encoding:[NSString defaultCStringEncoding]];
  60     return result;


 149 
 150 TString MacPlatform::GetPackageRootDirectory() {
 151     NSBundle *mainBundle = [NSBundle mainBundle];
 152     NSString *mainBundlePath = [mainBundle bundlePath];
 153     NSString *contentsPath = [mainBundlePath stringByAppendingString:@"/Contents"];
 154     TString result = [contentsPath UTF8String];
 155     return result;
 156 }
 157 
 158 TString MacPlatform::GetAppDataDirectory() {
 159     TString result;
 160     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
 161     NSString *applicationSupportDirectory = [paths firstObject];
 162     result = [applicationSupportDirectory UTF8String];
 163     return result;
 164 }
 165 
 166 TString MacPlatform::GetBundledJVMLibraryFileName(TString RuntimePath) {
 167     TString result;
 168 
 169     result = FilePath::IncludeTrailingSlash(RuntimePath) + _T("Contents/Home/jre/lib/jli/libjli.dylib");
 170 
 171     if (FilePath::FileExists(result) == false) {
 172         result = FilePath::IncludeTrailingSlash(RuntimePath) + _T("Contents/Home/lib/jli/libjli.dylib");
 173 
 174         if (FilePath::FileExists(result) == false) {
 175             result = _T("");
 176         }
 177     }
 178 
 179     return result;
 180 }
 181 
 182 
 183 TString MacPlatform::GetSystemJRE() {





 184     return _T("/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/jli/libjli.dylib");
 185 }
 186 
 187 TString MacPlatform::GetSystemJVMLibraryFileName() {
 188     TString result = GetSystemJRE();
 189 
 190     if (FilePath::FileExists(result) == false) {
 191         result = _T("");
 192     }
 193 
 194     return result;
 195 }
 196 
 197 TString MacPlatform::GetAppName() {
 198     NSString *appName = [[NSProcessInfo processInfo] processName];
 199     TString result = [appName UTF8String];
 200     return result;
 201 }
 202 
 203 // Convert parts of the info.plist to the INI format the rest of the packager uses unless
 204 // a packager config file exists.
 205 PropertyContainer* MacPlatform::GetConfigFile(TString FileName) {
 206     if (UsePListForConfigFile() == false) {
 207         return new PropertyFile(FileName);









 208     }


 209 
 210     NSBundle *mainBundle = [NSBundle mainBundle];
 211     NSDictionary *infoDictionary = [mainBundle infoDictionary];
 212 
 213     std::map<TString, TString> data;






 214 
 215     // Packager options.
 216     for (id key in [infoDictionary allKeys]) {
 217         id option = [infoDictionary valueForKey:key];
 218 
 219         if ([key isKindOfClass:[NSString class]] && [option isKindOfClass:[NSString class]]) {
 220             TString name = [key UTF8String];
 221             TString value = [option UTF8String];
 222             data.insert(std::map<TString, TString>::value_type(name, value));
 223         }
 224     }

 225 
 226     // jvmargs
 227     NSArray *options = [infoDictionary objectForKey:@"JVMOptions"];
 228     int index = 1;

 229 
 230     for (id option in options) {
 231         if ([option isKindOfClass:[NSString class]]) {
 232             TString value = [option UTF8String];
 233             TString argname = TString(_T("jvmarg.")) + PlatformString(index).toString();
 234             data.insert(std::map<TString, TString>::value_type(argname, value));
 235             index++;
 236         }
 237     }










 238 
 239     // jvmuserargs
 240     NSDictionary *defaultOverrides = [infoDictionary objectForKey:@"JVMUserOptions"];
 241     index = 1;
 242 
 243     for (id key in defaultOverrides) {
 244         id option = [defaultOverrides valueForKey:key];

 245 
 246         if ([key isKindOfClass:[NSString class]] && [option isKindOfClass:[NSString class]]) {
 247             TString name = [key UTF8String];
 248             TString value = [option UTF8String];
 249             TString prefix = TString(_T("jvmuserarg.")) + PlatformString(index).toString();
 250             TString argname = prefix + _T(".name");
 251             TString argvalue = prefix + _T(".value");
 252             data.insert(std::map<TString, TString>::value_type(argname, name));
 253             data.insert(std::map<TString, TString>::value_type(argvalue, value));
 254             index++;
 255         }
 256     }
 257 
 258     // args
 259     NSDictionary *args = [infoDictionary objectForKey:@"ArgOptions"];
 260     index = 1;




 261 
 262     for (id option in args) {
 263         if ([option isKindOfClass:[NSString class]]) {
 264             TString value = [option UTF8String];
 265             TString argname = TString(_T("arg.")) + PlatformString(index).toString();
 266             data.insert(std::map<TString, TString>::value_type(argname, value));
 267             index++;

















 268         }
 269     }


 270 
 271     return new PropertyFile(data);






 272 }
 273 


 274 TString MacPlatform::GetModuleFileName() {
 275     return "";










 276 }
 277 
 278 bool MacPlatform::IsMainThread() {
 279     bool result = (pthread_main_np() == 1);
 280     return result;
 281 }
 282 
 283 TPlatformNumber MacPlatform::GetMemorySize() {
 284     unsigned long long memory = [[NSProcessInfo processInfo] physicalMemory];
 285     TPlatformNumber result = memory / 1048576; // Convert from bytes to megabytes.
 286     return result;
 287 }
 288 
 289 std::map<TString, TString> MacPlatform::GetKeys() {
 290     std::map<TString, TString> keys;
 291 
 292     if (UsePListForConfigFile() == false) {
 293         return GenericPlatform::GetKeys();
 294     }
 295     else {

 296         keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINJAR_KEY,        _T("JVMMainJarName")));
 297         keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINCLASSNAME_KEY,  _T("JVMMainClassName")));
 298         keys.insert(std::map<TString, TString>::value_type(CONFIG_CLASSPATH_KEY,      _T("JVMAppClasspath")));
 299         keys.insert(std::map<TString, TString>::value_type(APP_NAME_KEY,              _T("CFBundleName")));
 300         keys.insert(std::map<TString, TString>::value_type(CONFIG_SPLASH_KEY,         _T("app.splash")));
 301         keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_ID_KEY,         _T("JVMPreferencesID")));
 302         keys.insert(std::map<TString, TString>::value_type(JVM_RUNTIME_KEY,           _T("JVMRuntime")));
 303         keys.insert(std::map<TString, TString>::value_type(PACKAGER_APP_DATA_DIR,     _T("CFBundleIdentifier")));


 304         keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_MEMORY,         _T("app.memory")));








 305     }
 306 
 307     return keys;
 308 }
 309 
 310 #ifdef DEBUG 
 311 bool MacPlatform::IsNativeDebuggerPresent() {
 312     int state;
 313     int mib[4];
 314     struct kinfo_proc info;
 315     size_t size;
 316     
 317     info.kp_proc.p_flag = 0;
 318     
 319     mib[0] = CTL_KERN;
 320     mib[1] = KERN_PROC;
 321     mib[2] = KERN_PROC_PID;
 322     mib[3] = getpid();
 323     
 324     size = sizeof(info);
 325     state = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
 326     assert(state == 0);
 327     return ((info.kp_proc.p_flag & P_TRACED) != 0);
 328 }
 329 
 330 int MacPlatform::GetProcessID() {
 331     int pid = [[NSProcessInfo processInfo] processIdentifier];
 332     return pid;
 333 }
 334 #endif //DEBUG
 335 
 336 //--------------------------------------------------------------------------------------------------
 337 
 338 class UserDefaults {
 339 private:
 340     TOrderedMap FData;
 341     TString FDomainName;
 342     
 343     bool ReadDictionary(NSDictionary *Items, TOrderedMap &Data) {
 344         bool result = false;
 345         int index = 1;
 346         
 347         for (id key in Items) {
 348             id option = [Items valueForKey:key];
 349             
 350             if ([key isKindOfClass:[NSString class]] && [option isKindOfClass:[NSString class]]) {
 351                 TString name = [key UTF8String];
 352                 TString value = [option UTF8String];
 353                 
 354                 if (name.empty() == false) {
 355                     TValueIndex item;
 356                     item.value = value;
 357                     item.index = index;
 358                     
 359                     Data.insert(TOrderedMap::value_type(name, item));
 360                     result = true;
 361                     index++;
 362                 }
 363             }
 364         }
 365         
 366         return result;
 367     }
 368     
 369     // Open and read the defaults file specified by domain.
 370     bool ReadPreferences(NSDictionary *Defaults, std::list<TString> Keys, TOrderedMap &Data) {
 371         bool result = false;
 372         
 373         if (Keys.size() > 0 && Defaults != NULL) {
 374             NSDictionary *node = Defaults;
 375             
 376             while (Keys.size() > 0 && node != NULL) {
 377                 TString key = Keys.front();
 378                 Keys.pop_front();
 379                 NSString *tempKey = StringToNSString(key);
 380                 node = [node valueForKey:tempKey];
 381                 
 382                 if (Keys.size() == 0) {
 383                     break;
 384                 }
 385             }
 386             
 387             if (node != NULL) {
 388                 result = ReadDictionary(node, Data);
 389             }
 390         }


 400             
 401             if (prefs != NULL) {
 402                 NSString *lDomainName = StringToNSString(DomainName);
 403                 result = [prefs persistentDomainForName: lDomainName];
 404             }
 405         }
 406         
 407         return result;
 408     }
 409     
 410 public:
 411     UserDefaults(TString DomainName) {
 412         FDomainName = DomainName;
 413     }
 414     
 415     bool Read(std::list<TString> Keys) {
 416         NSDictionary *defaults = LoadPreferences(FDomainName);
 417         return ReadPreferences(defaults, Keys, FData);
 418     }
 419     
 420     TOrderedMap GetData() {
 421         return FData;
 422     }
 423 };
 424 
 425 //--------------------------------------------------------------------------------------------------
 426 
 427 MacJavaUserPreferences::MacJavaUserPreferences(void) : JavaUserPreferences() {
 428 }
 429 
 430 TString toLowerCase(TString Value) {
 431     // Use Cocoa's lowercase method because it is better than the ones provided by C/C++.
 432     NSString *temp = StringToNSString(Value);
 433     temp = [temp lowercaseString];
 434     TString result = [temp UTF8String];
 435     return result;
 436 }
 437 
 438 // Split the string Value into using Delimiter.
 439 std::list<TString> Split(TString Value, TString Delimiter) {
 440     std::list<TString> result;




  21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 
  33 
  34 #include "Platform.h"
  35 
  36 #ifdef MAC
  37 
  38 #include "MacPlatform.h"
  39 #include "Helpers.h"
  40 #include "Package.h"
  41 #include "PropertyFile.h"
  42 #include "IniFile.h"
  43 
  44 #include <sys/sysctl.h>
  45 #include <pthread.h>
  46 #include <vector>
  47 
  48 #import <Foundation/Foundation.h>
  49 
  50 #include <CoreFoundation/CoreFoundation.h>
  51 #include <CoreFoundation/CFString.h>
  52 
  53 #ifdef __OBJC__
  54 #import <Cocoa/Cocoa.h>
  55 #endif //__OBJC__
  56 
  57 //--------------------------------------------------------------------------------------------------
  58 
  59 NSString* StringToNSString(TString Value) {
  60     NSString* result = [NSString stringWithCString:Value.c_str()
  61                                           encoding:[NSString defaultCStringEncoding]];
  62     return result;


 151 
 152 TString MacPlatform::GetPackageRootDirectory() {
 153     NSBundle *mainBundle = [NSBundle mainBundle];
 154     NSString *mainBundlePath = [mainBundle bundlePath];
 155     NSString *contentsPath = [mainBundlePath stringByAppendingString:@"/Contents"];
 156     TString result = [contentsPath UTF8String];
 157     return result;
 158 }
 159 
 160 TString MacPlatform::GetAppDataDirectory() {
 161     TString result;
 162     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
 163     NSString *applicationSupportDirectory = [paths firstObject];
 164     result = [applicationSupportDirectory UTF8String];
 165     return result;
 166 }
 167 
 168 TString MacPlatform::GetBundledJVMLibraryFileName(TString RuntimePath) {
 169     TString result;
 170 
 171     result = FilePath::IncludeTrailingSeparater(RuntimePath) + _T("Contents/Home/jre/lib/jli/libjli.dylib");
 172 
 173     if (FilePath::FileExists(result) == false) {
 174         result = FilePath::IncludeTrailingSeparater(RuntimePath) + _T("Contents/Home/lib/jli/libjli.dylib");
 175 
 176         if (FilePath::FileExists(result) == false) {
 177             result = _T("");
 178         }
 179     }
 180 
 181     return result;
 182 }
 183 
 184 
 185 TString MacPlatform::GetSystemJRE() {
 186     if (GetAppCDSState() == cdsOn || GetAppCDSState() == cdsGenCache) {
 187         //TODO throw exception
 188         return _T("");
 189     }
 190 
 191     return _T("/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/jli/libjli.dylib");
 192 }
 193 
 194 TString MacPlatform::GetSystemJVMLibraryFileName() {
 195     TString result = GetSystemJRE();
 196 
 197     if (FilePath::FileExists(result) == false) {
 198         result = _T("");
 199     }
 200 
 201     return result;
 202 }
 203 
 204 TString MacPlatform::GetAppName() {
 205     NSString *appName = [[NSProcessInfo processInfo] processName];
 206     TString result = [appName UTF8String];
 207     return result;
 208 }
 209 
 210 void AppendPListArrayToIniFile(NSDictionary *infoDictionary, IniFile *result, TString Section) {
 211     NSString *sectionKey = [NSString stringWithUTF8String:PlatformString(Section).toMultibyte()];
 212     NSDictionary *array = [infoDictionary objectForKey:sectionKey];
 213 
 214     for (id option in array) {
 215         if ([option isKindOfClass:[NSString class]]) {
 216             TString arg = [option UTF8String];
 217 
 218             TString name;
 219             TString value;
 220 
 221             if (Helpers::SplitOptionIntoNameValue(arg, name, value) == true) {
 222                 result->Append(Section, name, value);
 223             }
 224         }
 225     }
 226 }
 227 
 228 void AppendPListDictionaryToIniFile(NSDictionary *infoDictionary, IniFile *result, TString Section, bool FollowSection = true) {
 229     NSDictionary *dictionary = NULL;
 230 
 231     if (FollowSection == true) {
 232         NSString *sectionKey = [NSString stringWithUTF8String:PlatformString(Section).toMultibyte()];
 233         dictionary = [infoDictionary objectForKey:sectionKey];
 234     }
 235     else {
 236         dictionary = infoDictionary;
 237     }
 238 
 239     for (id key in dictionary) {
 240         id option = [dictionary valueForKey:key];

 241 
 242         if ([key isKindOfClass:[NSString class]] && [option isKindOfClass:[NSString class]]) {
 243             TString name = [key UTF8String];
 244             TString value = [option UTF8String];
 245             result->Append(Section, name, value);
 246         }
 247     }
 248 }
 249 
 250 // Convert parts of the info.plist to the INI format the rest of the packager uses unless
 251 // a packager config file exists.
 252 ISectionalPropertyContainer* MacPlatform::GetConfigFile(TString FileName) {
 253     IniFile* result = new IniFile();
 254 
 255     if (UsePListForConfigFile() == false) {
 256         if (result->LoadFromFile(FileName) == false) {
 257             // New property file format was not found, attempt to load old property file format.
 258             Helpers::LoadOldConfigFile(FileName, result);


 259         }
 260     }
 261     else {
 262         NSBundle *mainBundle = [NSBundle mainBundle];
 263         NSDictionary *infoDictionary = [mainBundle infoDictionary];
 264         std::map<TString, TString> keys = GetKeys();
 265 
 266         // Packager options.
 267         AppendPListDictionaryToIniFile(infoDictionary, result, keys[CONFIG_SECTION_APPLICATION], false);
 268 
 269         // jvmargs
 270         AppendPListArrayToIniFile(infoDictionary, result, keys[CONFIG_SECTION_JVMOPTIONS]);
 271 
 272         // jvmuserargs
 273         AppendPListDictionaryToIniFile(infoDictionary, result, keys[CONFIG_SECTION_JVMUSEROPTIONS]);

 274 
 275         // Generate AppCDS Cache
 276         AppendPListDictionaryToIniFile(infoDictionary, result, keys[CONFIG_SECTION_APPCDSJVMOPTIONS]);
 277         AppendPListDictionaryToIniFile(infoDictionary, result, keys[CONFIG_SECTION_APPCDSGENERATECACHEJVMOPTIONS]);
 278 
 279         // args
 280         AppendPListArrayToIniFile(infoDictionary, result, keys[CONFIG_SECTION_ARGOPTIONS]);








 281     }
 282 
 283     return result;
 284 }
 285 /*
 286 #include <mach-o/dyld.h>
 287 #include <mach-o/getsect.h>
 288 #include <dlfcn.h>
 289 #include <string>
 290 
 291 std::string GetModuleFileName(const void *module)
 292 {
 293     if (!module) { return std::string(); }
 294     uint32_t count = _dyld_image_count();
 295     for (uint32_t i = 0; i < count; ++i) {
 296         const mach_header *header = _dyld_get_image_header(i);
 297         if (!header) { break; }
 298         char *code_ptr = NULL;
 299         if ((header->magic & MH_MAGIC_64) == MH_MAGIC_64) {
 300             uint64_t size;
 301             code_ptr = getsectdatafromheader_64((const mach_header_64 *)header, SEG_TEXT, SECT_TEXT, &size);
 302         } else {
 303             uint32_t size;
 304             code_ptr = getsectdatafromheader(header, SEG_TEXT, SECT_TEXT, &size);
 305         }
 306         if (!code_ptr) { continue; }
 307         const uintptr_t slide = _dyld_get_image_vmaddr_slide(i);
 308         const uintptr_t start = (const uintptr_t)code_ptr + slide;
 309         Dl_info info;
 310         if (dladdr((const void *)start, &info)) {
 311             if (dlopen(info.dli_fname, RTLD_NOW) == module) {
 312                 return std::string(info.dli_fname);
 313             }
 314         }
 315     }
 316     return std::string();
 317 }*/
 318 
 319 TString GetModuleFileNameOSX() {
 320     Dl_info module_info;
 321     if (dladdr(reinterpret_cast<void*>(GetModuleFileNameOSX), &module_info) == 0) {
 322         // Failed to find the symbol we asked for.
 323         return std::string();
 324     }
 325     return TString(module_info.dli_fname);
 326 }
 327 
 328 #include <mach-o/dyld.h>
 329 
 330 TString MacPlatform::GetModuleFileName() {
 331     //return GetModuleFileNameOSX();
 332 
 333     TString result;
 334     DynamicBuffer<TCHAR> buffer(MAX_PATH);
 335     uint32_t size = buffer.GetSize();
 336 
 337     if (_NSGetExecutablePath(buffer.GetData(), &size) == 0) {
 338         result = FileSystemStringToString(buffer.GetData());
 339     }
 340 
 341     return result;
 342 }
 343 
 344 bool MacPlatform::IsMainThread() {
 345     bool result = (pthread_main_np() == 1);
 346     return result;
 347 }
 348 
 349 TPlatformNumber MacPlatform::GetMemorySize() {
 350     unsigned long long memory = [[NSProcessInfo processInfo] physicalMemory];
 351     TPlatformNumber result = memory / 1048576; // Convert from bytes to megabytes.
 352     return result;
 353 }
 354 
 355 std::map<TString, TString> MacPlatform::GetKeys() {
 356     std::map<TString, TString> keys;
 357 
 358     if (UsePListForConfigFile() == false) {
 359         return GenericPlatform::GetKeys();
 360     }
 361     else {
 362         keys.insert(std::map<TString, TString>::value_type(CONFIG_VERSION,            _T("app.version")));
 363         keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINJAR_KEY,        _T("JVMMainJarName")));
 364         keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINCLASSNAME_KEY,  _T("JVMMainClassName")));
 365         keys.insert(std::map<TString, TString>::value_type(CONFIG_CLASSPATH_KEY,      _T("JVMAppClasspath")));
 366         keys.insert(std::map<TString, TString>::value_type(APP_NAME_KEY,              _T("CFBundleName")));

 367         keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_ID_KEY,         _T("JVMPreferencesID")));
 368         keys.insert(std::map<TString, TString>::value_type(JVM_RUNTIME_KEY,           _T("JVMRuntime")));
 369         keys.insert(std::map<TString, TString>::value_type(PACKAGER_APP_DATA_DIR,     _T("CFBundleIdentifier")));
 370 
 371         keys.insert(std::map<TString, TString>::value_type(CONFIG_SPLASH_KEY,         _T("app.splash")));
 372         keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_MEMORY,         _T("app.memory")));
 373 
 374         keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_APPLICATION,    _T("Application")));
 375         keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_JVMOPTIONS,     _T("JVMOptions")));
 376         keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_JVMUSEROPTIONS, _T("JVMUserOptions")));
 377         keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS, _T("JVMUserOverrideOptions")));
 378         keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_APPCDSJVMOPTIONS, _T("AppCDSJVMOptions")));
 379         keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_APPCDSGENERATECACHEJVMOPTIONS, _T("AppCDSGenerateCacheJVMOptions")));
 380         keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_ARGOPTIONS,     _T("ArgOptions")));
 381     }
 382 
 383     return keys;
 384 }
 385 
 386 #ifdef DEBUG
 387 bool MacPlatform::IsNativeDebuggerPresent() {
 388     int state;
 389     int mib[4];
 390     struct kinfo_proc info;
 391     size_t size;
 392 
 393     info.kp_proc.p_flag = 0;
 394 
 395     mib[0] = CTL_KERN;
 396     mib[1] = KERN_PROC;
 397     mib[2] = KERN_PROC_PID;
 398     mib[3] = getpid();
 399 
 400     size = sizeof(info);
 401     state = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
 402     assert(state == 0);
 403     return ((info.kp_proc.p_flag & P_TRACED) != 0);
 404 }
 405 
 406 int MacPlatform::GetProcessID() {
 407     int pid = [[NSProcessInfo processInfo] processIdentifier];
 408     return pid;
 409 }
 410 #endif //DEBUG
 411 
 412 //--------------------------------------------------------------------------------------------------
 413 
 414 class UserDefaults {
 415 private:
 416     OrderedMap<TString, TString> FData;
 417     TString FDomainName;
 418 
 419     bool ReadDictionary(NSDictionary *Items, OrderedMap<TString, TString> &Data) {
 420         bool result = false;

 421 
 422         for (id key in Items) {
 423             id option = [Items valueForKey:key];
 424 
 425             if ([key isKindOfClass:[NSString class]] && [option isKindOfClass:[NSString class]]) {
 426                 TString name = [key UTF8String];
 427                 TString value = [option UTF8String];
 428 
 429                 if (name.empty() == false) {
 430                     Data.Append(name, value);






 431                 }
 432             }
 433         }
 434 
 435         return result;
 436     }
 437 
 438     // Open and read the defaults file specified by domain.
 439     bool ReadPreferences(NSDictionary *Defaults, std::list<TString> Keys, OrderedMap<TString, TString> &Data) {
 440         bool result = false;
 441 
 442         if (Keys.size() > 0 && Defaults != NULL) {
 443             NSDictionary *node = Defaults;
 444 
 445             while (Keys.size() > 0 && node != NULL) {
 446                 TString key = Keys.front();
 447                 Keys.pop_front();
 448                 NSString *tempKey = StringToNSString(key);
 449                 node = [node valueForKey:tempKey];
 450 
 451                 if (Keys.size() == 0) {
 452                     break;
 453                 }
 454             }
 455 
 456             if (node != NULL) {
 457                 result = ReadDictionary(node, Data);
 458             }
 459         }


 469 
 470             if (prefs != NULL) {
 471                 NSString *lDomainName = StringToNSString(DomainName);
 472                 result = [prefs persistentDomainForName: lDomainName];
 473             }
 474         }
 475 
 476         return result;
 477     }
 478 
 479 public:
 480     UserDefaults(TString DomainName) {
 481         FDomainName = DomainName;
 482     }
 483 
 484     bool Read(std::list<TString> Keys) {
 485         NSDictionary *defaults = LoadPreferences(FDomainName);
 486         return ReadPreferences(defaults, Keys, FData);
 487     }
 488 
 489     OrderedMap<TString, TString> GetData() {
 490         return FData;
 491     }
 492 };
 493 
 494 //--------------------------------------------------------------------------------------------------
 495 
 496 MacJavaUserPreferences::MacJavaUserPreferences(void) : JavaUserPreferences() {
 497 }
 498 
 499 TString toLowerCase(TString Value) {
 500     // Use Cocoa's lowercase method because it is better than the ones provided by C/C++.
 501     NSString *temp = StringToNSString(Value);
 502     temp = [temp lowercaseString];
 503     TString result = [temp UTF8String];
 504     return result;
 505 }
 506 
 507 // Split the string Value into using Delimiter.
 508 std::list<TString> Split(TString Value, TString Delimiter) {
 509     std::list<TString> result;