1 package org.antlr.xjlib.appkit.utils; 2 3 import java.io.File ; 4 import java.io.IOException ; 5 import java.lang.reflect.Constructor ; 6 import java.lang.reflect.Field ; 7 import java.lang.reflect.InvocationTargetException ; 8 import java.lang.reflect.Method ; 9 10 54 public class BrowserLauncher { 55 56 59 private static int jvm; 60 61 62 private static Object browser; 63 64 71 private static boolean loadedWithoutErrors; 72 73 74 private static Class mrjFileUtilsClass; 75 76 77 private static Class mrjOSTypeClass; 78 79 80 private static Class <?> aeDescClass; 81 82 83 private static Constructor <?> aeTargetConstructor; 84 85 86 private static Constructor <?> appleEventConstructor; 87 88 89 private static Constructor <?> aeDescConstructor; 90 91 92 private static Method findFolder; 93 94 95 private static Method getFileCreator; 96 97 98 private static Method getFileType; 99 100 101 private static Method openURL; 102 103 104 private static Method makeOSType; 105 106 107 private static Method putParameter; 108 109 110 private static Method sendNoReply; 111 112 113 private static Object kSystemFolderType; 114 115 116 private static Integer keyDirectObject; 117 118 119 private static Integer kAutoGenerateReturnID; 120 121 122 private static Integer kAnyTransactionID; 123 124 125 private static Object linkage; 126 127 128 private static final String JDirect_MacOSX = "/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox"; 129 130 131 private static final int MRJ_2_0 = 0; 132 133 134 private static final int MRJ_2_1 = 1; 135 136 137 private static final int MRJ_3_0 = 3; 138 139 140 private static final int MRJ_3_1 = 4; 141 142 143 private static final int WINDOWS_NT = 5; 144 145 146 private static final int WINDOWS_9x = 6; 147 148 private static final int LINUX = 7; 149 150 151 private static final int OTHER = -1; 152 153 157 private static final String FINDER_TYPE = "FNDR"; 158 159 163 private static final String FINDER_CREATOR = "MACS"; 164 165 166 private static final String GURL_EVENT = "GURL"; 167 168 172 private static final String FIRST_WINDOWS_PARAMETER = "/c"; 173 174 175 private static final String SECOND_WINDOWS_PARAMETER = "start"; 176 177 182 private static final String THIRD_WINDOWS_PARAMETER = "\"\""; 183 184 188 private static final String NETSCAPE_REMOTE_PARAMETER = "-remote"; 189 private static final String NETSCAPE_OPEN_PARAMETER_START = "'openURL("; 190 private static final String NETSCAPE_OPEN_PARAMETER_END = ")'"; 191 192 195 private static String errorMessage; 196 197 201 static { 202 loadedWithoutErrors = true; 203 String osName = System.getProperty("os.name"); 204 if (osName.startsWith("Mac OS")) { 205 String mrjVersion = System.getProperty("mrj.version"); 206 String majorMRJVersion = mrjVersion.substring(0, 3); 207 try { 208 double version = Double.valueOf(majorMRJVersion).doubleValue(); 209 if (version == 2) { 210 jvm = MRJ_2_0; 211 } else if (version >= 2.1 && version < 3) { 212 jvm = MRJ_2_1; 216 } else if (version == 3.0) { 217 jvm = MRJ_3_0; 218 } else if (version >= 3.1) { 219 jvm = MRJ_3_1; 221 } else { 222 loadedWithoutErrors = false; 223 errorMessage = "Unsupported MRJ version: " + version; 224 } 225 } catch (NumberFormatException nfe) { 226 loadedWithoutErrors = false; 227 errorMessage = "Invalid MRJ version: " + mrjVersion; 228 } 229 } else if (osName.startsWith("Windows")) { 230 if (osName.indexOf("9") != -1) { 231 jvm = WINDOWS_9x; 232 } else { 233 jvm = WINDOWS_NT; 234 } 235 } else if (osName.startsWith("Linux")) { 236 jvm = LINUX; 237 } else { 238 jvm = OTHER; 239 } 240 241 if (loadedWithoutErrors) { loadedWithoutErrors = loadClasses(); 243 } 244 } 245 246 249 private BrowserLauncher() { } 250 251 257 private static boolean loadClasses() { 258 switch (jvm) { 259 case MRJ_2_0: 260 try { 261 Class <?> aeTargetClass = Class.forName("com.apple.MacOS.AETarget"); 262 Class osUtilsClass = Class.forName("com.apple.MacOS.OSUtils"); 263 Class <?> appleEventClass = Class.forName("com.apple.MacOS.AppleEvent"); 264 Class aeClass = Class.forName("com.apple.MacOS.ae"); 265 aeDescClass = Class.forName("com.apple.MacOS.AEDesc"); 266 267 aeTargetConstructor = aeTargetClass.getDeclaredConstructor(new Class [] { int.class }); 268 appleEventConstructor = appleEventClass.getDeclaredConstructor(new Class [] { int.class, int.class, aeTargetClass, int.class, int.class }); 269 aeDescConstructor = aeDescClass.getDeclaredConstructor(new Class [] { String .class }); 270 271 makeOSType = osUtilsClass.getDeclaredMethod("makeOSType", new Class [] { String .class }); 272 putParameter = appleEventClass.getDeclaredMethod("putParameter", new Class [] { int.class, aeDescClass }); 273 sendNoReply = appleEventClass.getDeclaredMethod("sendNoReply", new Class [] { }); 274 275 Field keyDirectObjectField = aeClass.getDeclaredField("keyDirectObject"); 276 keyDirectObject = (Integer ) keyDirectObjectField.get(null); 277 Field autoGenerateReturnIDField = appleEventClass.getDeclaredField("kAutoGenerateReturnID"); 278 kAutoGenerateReturnID = (Integer ) autoGenerateReturnIDField.get(null); 279 Field anyTransactionIDField = appleEventClass.getDeclaredField("kAnyTransactionID"); 280 kAnyTransactionID = (Integer ) anyTransactionIDField.get(null); 281 } catch (ClassNotFoundException cnfe) { 282 errorMessage = cnfe.getMessage(); 283 return false; 284 } catch (NoSuchMethodException nsme) { 285 errorMessage = nsme.getMessage(); 286 return false; 287 } catch (NoSuchFieldException nsfe) { 288 errorMessage = nsfe.getMessage(); 289 return false; 290 } catch (IllegalAccessException iae) { 291 errorMessage = iae.getMessage(); 292 return false; 293 } 294 break; 295 case MRJ_2_1: 296 try { 297 mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils"); 298 mrjOSTypeClass = Class.forName("com.apple.mrj.MRJOSType"); 299 Field systemFolderField = mrjFileUtilsClass.getDeclaredField("kSystemFolderType"); 300 kSystemFolderType = systemFolderField.get(null); 301 findFolder = mrjFileUtilsClass.getDeclaredMethod("findFolder", new Class [] { mrjOSTypeClass }); 302 getFileCreator = mrjFileUtilsClass.getDeclaredMethod("getFileCreator", new Class [] { File .class }); 303 getFileType = mrjFileUtilsClass.getDeclaredMethod("getFileType", new Class [] { File .class }); 304 } catch (ClassNotFoundException cnfe) { 305 errorMessage = cnfe.getMessage(); 306 return false; 307 } catch (NoSuchFieldException nsfe) { 308 errorMessage = nsfe.getMessage(); 309 return false; 310 } catch (NoSuchMethodException nsme) { 311 errorMessage = nsme.getMessage(); 312 return false; 313 } catch (SecurityException se) { 314 errorMessage = se.getMessage(); 315 return false; 316 } catch (IllegalAccessException iae) { 317 errorMessage = iae.getMessage(); 318 return false; 319 } 320 break; 321 case MRJ_3_0: 322 try { 323 Class <?> linker = Class.forName("com.apple.mrj.jdirect.Linker"); 324 Constructor <?> constructor = linker.getConstructor(new Class []{ Class .class }); 325 linkage = constructor.newInstance(new Object [] { BrowserLauncher.class }); 326 } catch (ClassNotFoundException cnfe) { 327 errorMessage = cnfe.getMessage(); 328 return false; 329 } catch (NoSuchMethodException nsme) { 330 errorMessage = nsme.getMessage(); 331 return false; 332 } catch (InvocationTargetException ite) { 333 errorMessage = ite.getMessage(); 334 return false; 335 } catch (InstantiationException ie) { 336 errorMessage = ie.getMessage(); 337 return false; 338 } catch (IllegalAccessException iae) { 339 errorMessage = iae.getMessage(); 340 return false; 341 } 342 break; 343 case MRJ_3_1: 344 try { 345 mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils"); 346 openURL = mrjFileUtilsClass.getDeclaredMethod("openURL", new Class [] { String .class }); 347 } catch (ClassNotFoundException cnfe) { 348 errorMessage = cnfe.getMessage(); 349 return false; 350 } catch (NoSuchMethodException nsme) { 351 errorMessage = nsme.getMessage(); 352 return false; 353 } 354 break; 355 default: 356 break; 357 } 358 return true; 359 } 360 361 369 private static Object locateBrowser() { 370 if (browser != null) { 371 return browser; 372 } 373 374 switch (jvm) { 375 case MRJ_2_0: 376 try { 377 Integer finderCreatorCode = (Integer ) makeOSType.invoke(null, new Object [] { FINDER_CREATOR }); 378 Object aeTarget = aeTargetConstructor.newInstance(new Object [] { finderCreatorCode }); 379 Integer gurlType = (Integer ) makeOSType.invoke(null, new Object [] { GURL_EVENT }); 380 Object appleEvent = appleEventConstructor.newInstance(new Object [] { gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID }); 381 return appleEvent; 387 } catch (IllegalAccessException iae) { 388 browser = null; 389 errorMessage = iae.getMessage(); 390 return browser; 391 } catch (InstantiationException ie) { 392 browser = null; 393 errorMessage = ie.getMessage(); 394 return browser; 395 } catch (InvocationTargetException ite) { 396 browser = null; 397 errorMessage = ite.getMessage(); 398 return browser; 399 } 400 case MRJ_2_1: 401 File systemFolder; 402 try { 403 systemFolder = (File ) findFolder.invoke(null, new Object [] { kSystemFolderType }); 404 } catch (IllegalArgumentException iare) { 405 browser = null; 406 errorMessage = iare.getMessage(); 407 return browser; 408 } catch (IllegalAccessException iae) { 409 browser = null; 410 errorMessage = iae.getMessage(); 411 return browser; 412 } catch (InvocationTargetException ite) { 413 browser = null; 414 errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); 415 return browser; 416 } 417 String [] systemFolderFiles = systemFolder.list(); 418 for(int i = 0; i < systemFolderFiles.length; i++) { 420 try { 421 File file = new File (systemFolder, systemFolderFiles[i]); 422 if (!file.isFile()) { 423 continue; 424 } 425 Object fileType = getFileType.invoke(null, new Object [] { file }); 431 if (FINDER_TYPE.equals(fileType.toString())) { 432 Object fileCreator = getFileCreator.invoke(null, new Object [] { file }); 433 if (FINDER_CREATOR.equals(fileCreator.toString())) { 434 browser = file.toString(); return browser; 436 } 437 } 438 } catch (IllegalArgumentException iare) { 439 errorMessage = iare.getMessage(); 440 return null; 441 } catch (IllegalAccessException iae) { 442 browser = null; 443 errorMessage = iae.getMessage(); 444 return browser; 445 } catch (InvocationTargetException ite) { 446 browser = null; 447 errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); 448 return browser; 449 } 450 } 451 browser = null; 452 break; 453 case MRJ_3_0: 454 case MRJ_3_1: 455 browser = ""; break; 457 case WINDOWS_NT: 458 browser = "cmd.exe"; 459 break; 460 case WINDOWS_9x: 461 browser = "command.com"; 462 break; 463 case LINUX: 464 case OTHER: 465 default: 466 browser = new String [] {"firefox", "mozilla", "netscape", "opera", "konqueror", "galeon", "firebird"}; 468 break; 469 } 470 return browser; 471 } 472 473 478 public static void openURL(String url) throws IOException { 479 if (!loadedWithoutErrors) { 480 throw new IOException ("Exception in finding browser: " + errorMessage); 481 } 482 Object browser = locateBrowser(); 483 if (browser == null) { 484 throw new IOException ("Unable to locate browser: " + errorMessage); 485 } 486 487 switch (jvm) { 488 case MRJ_2_0: 489 Object aeDesc; 490 try { 491 aeDesc = aeDescConstructor.newInstance(new Object [] { url }); 492 putParameter.invoke(browser, new Object [] { keyDirectObject, aeDesc }); 493 sendNoReply.invoke(browser, new Object [] { }); 494 } catch (InvocationTargetException ite) { 495 throw new IOException ("InvocationTargetException while creating AEDesc: " + ite.getMessage()); 496 } catch (IllegalAccessException iae) { 497 throw new IOException ("IllegalAccessException while building AppleEvent: " + iae.getMessage()); 498 } catch (InstantiationException ie) { 499 throw new IOException ("InstantiationException while creating AEDesc: " + ie.getMessage()); 500 } finally { 501 aeDesc = null; browser = null; } 504 break; 505 case MRJ_2_1: 506 Runtime.getRuntime().exec(new String [] { (String ) browser, url } ); 507 break; 508 case MRJ_3_0: 509 int[] instance = new int[1]; 510 int result = ICStart(instance, 0); 511 if (result == 0) { 512 int[] selectionStart = new int[] { 0 }; 513 byte[] urlBytes = url.getBytes(); 514 int[] selectionEnd = new int[] { urlBytes.length }; 515 result = ICLaunchURL(instance[0], new byte[] { 0 }, urlBytes, 516 urlBytes.length, selectionStart, 517 selectionEnd); 518 if (result == 0) { 519 ICStop(instance); 522 } else { 523 throw new IOException ("Unable to launch URL: " + result); 524 } 525 } else { 526 throw new IOException ("Unable to create an Internet Config instance: " + result); 527 } 528 break; 529 case MRJ_3_1: 530 try { 531 openURL.invoke(null, new Object [] { url }); 532 } catch (InvocationTargetException ite) { 533 throw new IOException ("InvocationTargetException while calling openURL: " + ite.getMessage()); 534 } catch (IllegalAccessException iae) { 535 throw new IOException ("IllegalAccessException while calling openURL: " + iae.getMessage()); 536 } 537 break; 538 case WINDOWS_NT: 539 case WINDOWS_9x: 540 Process process = Runtime.getRuntime().exec(new String [] { (String ) browser, 543 FIRST_WINDOWS_PARAMETER, 544 SECOND_WINDOWS_PARAMETER, 545 THIRD_WINDOWS_PARAMETER, 546 '"' + url + '"' }); 547 try { 550 process.waitFor(); 551 process.exitValue(); 552 } catch (InterruptedException ie) { 553 throw new IOException ("InterruptedException while launching browser: " + ie.getMessage()); 554 } 555 break; 556 case LINUX: 557 case OTHER: 558 String [] array = (String [])browser; 560 for (int i = 0; i < array.length; i++) { 561 if(openUnixBrowser(array[i], url)) 562 return; 563 } 564 throw new IOException ("Unable to locate browser"); 565 default: 566 Runtime.getRuntime().exec(new String [] { (String ) browser, url }); 568 break; 569 } 570 } 571 572 private static boolean openUnixBrowser(String browser, String url) { 573 boolean success = false; 574 Process process; 575 try { 576 process = Runtime.getRuntime().exec(new String [] { (String ) browser, 578 NETSCAPE_REMOTE_PARAMETER, 579 NETSCAPE_OPEN_PARAMETER_START + 580 url + 581 NETSCAPE_OPEN_PARAMETER_END }); 582 try { 583 int exitCode = process.waitFor(); 584 if (exitCode != 0) { Runtime.getRuntime().exec(new String [] { (String ) browser, url }); 586 exitCode = 0; 587 } 588 success = (exitCode == 0); 589 } catch (InterruptedException ie) { 590 } 592 } catch(IOException e) { 593 594 } 595 return success; 596 } 597 598 602 private native static int ICStart(int[] instance, int signature); 603 private native static int ICStop(int[] instance); 604 private native static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len, 605 int[] selectionStart, int[] selectionEnd); 606 } 607 | Popular Tags |