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;
|