1 package com.sslexplorer.boot; 2 3 import java.io.BufferedReader ; 4 import java.io.File ; 5 import java.io.IOException ; 6 import java.io.InputStream ; 7 import java.io.InputStreamReader ; 8 import java.lang.reflect.Constructor ; 9 import java.lang.reflect.Field ; 10 import java.lang.reflect.InvocationTargetException ; 11 import java.lang.reflect.Method ; 12 13 73 public class BrowserLauncher { 74 75 80 private static int jvm; 81 82 83 private static Object browser; 84 85 86 private static String browserCommand; 87 88 95 private static boolean loadedWithoutErrors; 96 97 98 private static Class mrjFileUtilsClass; 99 100 101 private static Class mrjOSTypeClass; 102 103 104 private static Class aeDescClass; 105 106 107 private static Constructor aeTargetConstructor; 108 109 110 private static Constructor appleEventConstructor; 111 112 113 private static Constructor aeDescConstructor; 114 115 116 private static Method findFolder; 117 118 119 private static Method getFileCreator; 120 121 122 private static Method getFileType; 123 124 125 private static Method openURL; 126 127 128 private static Method makeOSType; 129 130 131 private static Method putParameter; 132 133 134 private static Method sendNoReply; 135 136 137 private static Object kSystemFolderType; 138 139 140 private static Integer keyDirectObject; 141 142 143 private static Integer kAutoGenerateReturnID; 144 145 146 private static Integer kAnyTransactionID; 147 148 149 151 154 private static final int MRJ_2_0 = 0; 155 156 157 private static final int MRJ_2_1 = 1; 158 159 160 private static final int MRJ_3_0 = 3; 161 162 163 private static final int MRJ_3_1 = 4; 164 165 166 private static final int MRJ_COCOA = 5; 167 168 169 private static final int WINDOWS_NT = 6; 170 171 172 private static final int WINDOWS_9x = 7; 173 174 175 private static final int OTHER = -1; 176 177 181 private static final String FINDER_TYPE = "FNDR"; 182 183 187 private static final String FINDER_CREATOR = "MACS"; 188 189 190 private static final String GURL_EVENT = "GURL"; 191 192 196 private static final String FIRST_WINDOWS_PARAMETER = "/c"; 197 198 199 private static final String SECOND_WINDOWS_PARAMETER = "start"; 200 201 206 private static final String THIRD_WINDOWS_PARAMETER = "\"\""; 207 208 212 private static final String NETSCAPE_REMOTE_PARAMETER = "-remote"; 213 private static final String NETSCAPE_OPEN_PARAMETER_START = "'openURL("; 214 private static final String NETSCAPE_OPEN_PARAMETER_END = ")'"; 215 216 220 private static String errorMessage; 221 222 226 static { 227 loadedWithoutErrors = true; 228 String osName = System.getProperty("os.name"); 229 if (osName.startsWith("Mac OS")) { 230 String javaVersion = System.getProperty("java.version"); 231 String majorJavaVersion = javaVersion.substring(0, 3); 232 try { 233 double version = Double.valueOf(majorJavaVersion).doubleValue(); 234 if (version >= 1.4) { 235 jvm = MRJ_COCOA; 236 } 237 } catch (NumberFormatException nfe) { 238 } 240 if (jvm != MRJ_COCOA) { 241 String mrjVersion = System.getProperty("mrj.version"); 242 String majorMRJVersion = mrjVersion.substring(0, 3); 243 try { 244 double version = Double.valueOf(majorMRJVersion).doubleValue(); 245 if (version == 2) { 246 jvm = MRJ_2_0; 247 } else if (version >= 2.1 && version < 3) { 248 jvm = MRJ_2_1; 258 } else if (version == 3.0) { 259 jvm = MRJ_3_0; 260 } else if (version >= 3.1) { 261 jvm = MRJ_3_1; 264 } else { 265 loadedWithoutErrors = false; 266 errorMessage = "Unsupported MRJ version: " + version; 267 } 268 } catch (NumberFormatException nfe) { 269 loadedWithoutErrors = false; 270 errorMessage = "Invalid MRJ version: " + mrjVersion; 271 } 272 } 273 } else if (osName.startsWith("Windows")) { 274 if (osName.indexOf("9") != -1 || osName.indexOf("Me") != -1) { 275 jvm = WINDOWS_9x; 276 } else { 277 jvm = WINDOWS_NT; 278 } 279 } else { 280 jvm = OTHER; 281 } 282 283 if (loadedWithoutErrors) { loadedWithoutErrors = loadClasses(); 285 } 286 } 287 288 291 private BrowserLauncher() { 292 } 293 294 300 public static void setBrowserCommand(String browserCommand) { 301 BrowserLauncher.browserCommand = browserCommand; 302 } 303 304 311 private static boolean loadClasses() { 312 switch (jvm) { 313 case MRJ_2_0: 314 return loadMRJ20Classes(); 315 case MRJ_2_1: 316 try { 317 mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils"); 318 mrjOSTypeClass = Class.forName("com.apple.mrj.MRJOSType"); 319 Field systemFolderField = mrjFileUtilsClass.getDeclaredField("kSystemFolderType"); 320 kSystemFolderType = systemFolderField.get(null); 321 findFolder = mrjFileUtilsClass.getDeclaredMethod("findFolder", new Class [] { 322 mrjOSTypeClass 323 }); 324 getFileCreator = mrjFileUtilsClass.getDeclaredMethod("getFileCreator", new Class [] { 325 File .class 326 }); 327 getFileType = mrjFileUtilsClass.getDeclaredMethod("getFileType", new Class [] { 328 File .class 329 }); 330 } catch (ClassNotFoundException cnfe) { 331 errorMessage = cnfe.getMessage(); 332 return false; 333 } catch (NoSuchFieldException nsfe) { 334 errorMessage = nsfe.getMessage(); 335 return false; 336 } catch (NoSuchMethodException nsme) { 337 errorMessage = nsme.getMessage(); 338 return false; 339 } catch (SecurityException se) { 340 errorMessage = se.getMessage(); 341 return false; 342 } catch (IllegalAccessException iae) { 343 errorMessage = iae.getMessage(); 344 return false; 345 } 346 break; 347 case MRJ_3_0: 348 try { 349 Class linker = Class.forName("com.apple.mrj.jdirect.Linker"); 350 Constructor constructor = linker.getConstructor(new Class [] { 351 Class .class 352 }); 353 constructor.newInstance(new Object [] { 354 BrowserLauncher.class 355 }); 356 } catch (ClassNotFoundException cnfe) { 357 errorMessage = cnfe.getMessage(); 358 return false; 359 } catch (NoSuchMethodException nsme) { 360 errorMessage = nsme.getMessage(); 361 return false; 362 } catch (InvocationTargetException ite) { 363 errorMessage = ite.getMessage(); 364 return false; 365 } catch (InstantiationException ie) { 366 errorMessage = ie.getMessage(); 367 return false; 368 } catch (IllegalAccessException iae) { 369 errorMessage = iae.getMessage(); 370 return false; 371 } 372 break; 373 case MRJ_3_1: 374 case MRJ_COCOA: 375 String className; 376 if (jvm == MRJ_3_1) { 377 className = "com.apple.mrj.MRJFileUtils"; 378 } else { 379 className = "com.apple.eio.FileManager"; 380 } 381 try { 382 mrjFileUtilsClass = Class.forName(className); 383 openURL = mrjFileUtilsClass.getDeclaredMethod("openURL", new Class [] { 384 String .class 385 }); 386 } catch (ClassNotFoundException cnfe) { 387 errorMessage = cnfe.getMessage(); 388 return false; 389 } catch (NoSuchMethodException nsme) { 390 errorMessage = nsme.getMessage(); 391 return false; 392 } 393 break; 394 default: 395 break; 396 } 397 return true; 398 } 399 400 407 private static boolean loadMRJ20Classes() { 408 try { 409 Class aeTargetClass = Class.forName("com.apple.MacOS.AETarget"); 410 Class osUtilsClass = Class.forName("com.apple.MacOS.OSUtils"); 411 Class appleEventClass = Class.forName("com.apple.MacOS.AppleEvent"); 412 Class aeClass = Class.forName("com.apple.MacOS.ae"); 413 aeDescClass = Class.forName("com.apple.MacOS.AEDesc"); 414 415 aeTargetConstructor = aeTargetClass.getDeclaredConstructor(new Class [] { 416 int.class 417 }); 418 appleEventConstructor = appleEventClass.getDeclaredConstructor(new Class [] { 419 int.class, int.class, aeTargetClass, int.class, int.class 420 }); 421 aeDescConstructor = aeDescClass.getDeclaredConstructor(new Class [] { 422 String .class 423 }); 424 425 makeOSType = osUtilsClass.getDeclaredMethod("makeOSType", new Class [] { 426 String .class 427 }); 428 putParameter = appleEventClass.getDeclaredMethod("putParameter", new Class [] { 429 int.class, aeDescClass 430 }); 431 sendNoReply = appleEventClass.getDeclaredMethod("sendNoReply", new Class [] {}); 432 433 Field keyDirectObjectField = aeClass.getDeclaredField("keyDirectObject"); 434 keyDirectObject = (Integer ) keyDirectObjectField.get(null); 435 Field autoGenerateReturnIDField = appleEventClass.getDeclaredField("kAutoGenerateReturnID"); 436 kAutoGenerateReturnID = (Integer ) autoGenerateReturnIDField.get(null); 437 Field anyTransactionIDField = appleEventClass.getDeclaredField("kAnyTransactionID"); 438 kAnyTransactionID = (Integer ) anyTransactionIDField.get(null); 439 } catch (ClassNotFoundException cnfe) { 440 errorMessage = cnfe.getMessage(); 441 return false; 442 } catch (NoSuchMethodException nsme) { 443 errorMessage = nsme.getMessage(); 444 return false; 445 } catch (NoSuchFieldException nsfe) { 446 errorMessage = nsfe.getMessage(); 447 return false; 448 } catch (IllegalAccessException iae) { 449 errorMessage = iae.getMessage(); 450 return false; 451 } 452 return true; 453 } 454 455 466 private static Object locateBrowser() { 467 if (browser != null) { 468 return browser; 469 } 470 switch (jvm) { 471 case MRJ_2_0: 472 try { 473 Integer finderCreatorCode = (Integer ) makeOSType.invoke(null, new Object [] { 474 FINDER_CREATOR 475 }); 476 Object aeTarget = aeTargetConstructor.newInstance(new Object [] { 477 finderCreatorCode 478 }); 479 Integer gurlType = (Integer ) makeOSType.invoke(null, new Object [] { 480 GURL_EVENT 481 }); 482 Object appleEvent = appleEventConstructor.newInstance(new Object [] { 483 gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID 484 }); 485 return appleEvent; 498 } catch (IllegalAccessException iae) { 499 browser = null; 500 errorMessage = iae.getMessage(); 501 return browser; 502 } catch (InstantiationException ie) { 503 browser = null; 504 errorMessage = ie.getMessage(); 505 return browser; 506 } catch (InvocationTargetException ite) { 507 browser = null; 508 errorMessage = ite.getMessage(); 509 return browser; 510 } 511 case MRJ_2_1: 512 File systemFolder; 513 try { 514 systemFolder = (File ) findFolder.invoke(null, new Object [] { 515 kSystemFolderType 516 }); 517 } catch (IllegalArgumentException iare) { 518 browser = null; 519 errorMessage = iare.getMessage(); 520 return browser; 521 } catch (IllegalAccessException iae) { 522 browser = null; 523 errorMessage = iae.getMessage(); 524 return browser; 525 } catch (InvocationTargetException ite) { 526 browser = null; 527 errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); 528 return browser; 529 } 530 String [] systemFolderFiles = systemFolder.list(); 531 for (int i = 0; i < systemFolderFiles.length; i++) { 533 try { 534 File file = new File (systemFolder, systemFolderFiles[i]); 535 if (!file.isFile()) { 536 continue; 537 } 538 Object fileType = getFileType.invoke(null, new Object [] { 549 file 550 }); 551 if (FINDER_TYPE.equals(fileType.toString())) { 552 Object fileCreator = getFileCreator.invoke(null, new Object [] { 553 file 554 }); 555 if (FINDER_CREATOR.equals(fileCreator.toString())) { 556 browser = file.toString(); return browser; 560 } 561 } 562 } catch (IllegalArgumentException iare) { 563 browser = null; 564 errorMessage = iare.getMessage(); 565 return null; 566 } catch (IllegalAccessException iae) { 567 browser = null; 568 errorMessage = iae.getMessage(); 569 return browser; 570 } catch (InvocationTargetException ite) { 571 browser = null; 572 errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); 573 return browser; 574 } 575 } 576 browser = null; 577 break; 578 case MRJ_3_0: 579 case MRJ_3_1: 580 browser = ""; break; 582 case WINDOWS_NT: 583 browser = "cmd.exe"; 584 break; 585 case WINDOWS_9x: 586 browser = "command.com"; 587 break; 588 case OTHER: 589 default: 590 browser = getEnvironmentBrowser(); 598 if (browser == null) { 599 browser = "netscape"; 600 } 601 break; 602 } 603 return browser; 604 } 605 606 613 public static void openURL(String url) throws IOException { 614 if (!loadedWithoutErrors) { 615 throw new IOException ("Exception in finding browser: " + errorMessage); 616 } 617 618 if (browserCommand != null) { 619 String [] cmd = Util.splitString(browserCommand, ' ', '"', '\\'); 620 String [] cmde = new String [cmd.length + 1]; 621 System.arraycopy(cmd, 0, cmde, 0, cmd.length); 622 cmde[cmd.length] = url; 623 Runtime.getRuntime().exec(cmde); 624 return; 625 } 626 627 Object browser = locateBrowser(); 628 if (browser == null) { 629 throw new IOException ("Unable to locate browser: " + errorMessage); 630 } 631 632 switch (jvm) { 633 case MRJ_2_0: 634 Object aeDesc = null; 635 try { 636 aeDesc = aeDescConstructor.newInstance(new Object [] { 637 url 638 }); 639 putParameter.invoke(browser, new Object [] { 640 keyDirectObject, aeDesc 641 }); 642 sendNoReply.invoke(browser, new Object [] {}); 643 } catch (InvocationTargetException ite) { 644 throw new IOException ("InvocationTargetException while creating AEDesc: " + ite.getMessage()); 645 } catch (IllegalAccessException iae) { 646 throw new IOException ("IllegalAccessException while building AppleEvent: " + iae.getMessage()); 647 } catch (InstantiationException ie) { 648 throw new IOException ("InstantiationException while creating AEDesc: " + ie.getMessage()); 649 } finally { 650 aeDesc = null; browser = null; } 654 break; 655 case MRJ_2_1: 656 Runtime.getRuntime().exec(new String [] { 657 (String ) browser, url 658 }); 659 break; 660 case MRJ_3_0: 661 int[] instance = new int[1]; 662 int result = ICStart(instance, 0); 663 if (result == 0) { 664 int[] selectionStart = new int[] { 665 0 666 }; 667 byte[] urlBytes = url.getBytes(); 668 int[] selectionEnd = new int[] { 669 urlBytes.length 670 }; 671 result = ICLaunchURL(instance[0], new byte[] { 672 0 673 }, urlBytes, urlBytes.length, selectionStart, selectionEnd); 674 if (result == 0) { 675 ICStop(instance); 679 } else { 680 throw new IOException ("Unable to launch URL: " + result); 681 } 682 } else { 683 throw new IOException ("Unable to create an Internet Config instance: " + result); 684 } 685 break; 686 case MRJ_3_1: 687 case MRJ_COCOA: 688 try { 689 openURL.invoke(null, new Object [] { 690 url 691 }); 692 } catch (InvocationTargetException ite) { 693 throw new IOException ("InvocationTargetException while calling openURL: " + ite.getMessage()); 694 } catch (IllegalAccessException iae) { 695 throw new IOException ("IllegalAccessException while calling openURL: " + iae.getMessage()); 696 } 697 break; 698 case WINDOWS_NT: 699 case WINDOWS_9x: 700 String [] arguments; 704 if (jvm == WINDOWS_9x) { 705 arguments = new String [] { 706 (String ) browser, FIRST_WINDOWS_PARAMETER, SECOND_WINDOWS_PARAMETER, null 707 }; 708 } else { 709 arguments = new String [] { 710 (String ) browser, FIRST_WINDOWS_PARAMETER, SECOND_WINDOWS_PARAMETER, THIRD_WINDOWS_PARAMETER, 711 null 712 }; 713 } 714 arguments[arguments.length - 1] = '"' + url + '"'; 715 Process process = Runtime.getRuntime().exec(arguments); 716 try { 721 process.waitFor(); 722 process.exitValue(); 723 } catch (InterruptedException ie) { 724 throw new IOException ("InterruptedException while launching browser: " + ie.getMessage()); 725 } 726 break; 727 case OTHER: 728 730 process = Runtime.getRuntime().exec( 733 new String [] { 734 (String ) browser, NETSCAPE_REMOTE_PARAMETER, 735 NETSCAPE_OPEN_PARAMETER_START + url + NETSCAPE_OPEN_PARAMETER_END 736 }); 737 try { 738 int exitCode = process.waitFor(); 739 if (exitCode != 0) { Runtime.getRuntime().exec(new String [] { 741 (String ) browser, url 742 }); 743 } 744 } catch (InterruptedException ie) { 745 throw new IOException ("InterruptedException while launching browser: " + ie.getMessage()); 746 } 747 break; 748 default: 749 Runtime.getRuntime().exec(new String [] { 753 (String ) browser, url 754 }); 755 break; 756 } 757 } 758 759 767 private static String getEnvironmentBrowser() { 768 String browser = null; 769 try { 770 String [] echoParams = { 771 "/bin/sh", "-c", "echo ${BROWSER:-netscape}" 772 }; 773 Process echoProcess = Runtime.getRuntime().exec(echoParams); 774 InputStream echoStream = echoProcess.getInputStream(); 775 BufferedReader echoReader = new BufferedReader (new InputStreamReader (echoStream)); 776 browser = echoReader.readLine(); 777 echoReader.close(); 778 } catch (Throwable t) { 779 } 781 return browser; 782 } 783 784 788 private native static int ICStart(int[] instance, int signature); 789 790 private native static int ICStop(int[] instance); 791 792 private native static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len, int[] selectionStart, int[] selectionEnd); 793 } 794 | Popular Tags |