1 package com.sslexplorer.agent.client.util; 2 3 import java.io.BufferedReader ; 4 import java.io.File ; 5 import java.io.InputStream ; 6 import java.io.InputStreamReader ; 7 import java.io.IOException ; 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 import java.text.MessageFormat ; 13 import java.util.Vector ; 14 15 75 public class BrowserLauncher { 76 77 82 private static int jvm; 83 84 85 private static Object browser; 86 87 88 private static String browserCommand; 89 90 97 private static boolean loadedWithoutErrors; 98 99 100 private static Class mrjFileUtilsClass; 101 102 103 private static Class mrjOSTypeClass; 104 105 106 private static Class aeDescClass; 107 108 109 private static Constructor aeTargetConstructor; 110 111 112 private static Constructor appleEventConstructor; 113 114 115 private static Constructor aeDescConstructor; 116 117 118 private static Method findFolder; 119 120 121 private static Method getFileCreator; 122 123 124 private static Method getFileType; 125 126 127 private static Method openURL; 128 129 130 private static Method makeOSType; 131 132 133 private static Method putParameter; 134 135 136 private static Method sendNoReply; 137 138 139 private static Object kSystemFolderType; 140 141 142 private static Integer keyDirectObject; 143 144 145 private static Integer kAutoGenerateReturnID; 146 147 148 private static Integer kAnyTransactionID; 149 150 151 private static Object linkage; 152 153 154 private static final String JDirect_MacOSX = "/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox"; 156 157 private static final int MRJ_2_0 = 0; 158 159 160 private static final int MRJ_2_1 = 1; 161 162 163 private static final int MRJ_3_0 = 3; 164 165 166 private static final int MRJ_3_1 = 4; 167 168 169 private static final int MRJ_COCOA = 5; 170 171 172 private static final int WINDOWS_NT = 6; 173 174 175 private static final int WINDOWS_9x = 7; 176 177 178 private static final int OTHER = -1; 179 180 184 private static final String FINDER_TYPE = "FNDR"; 186 190 private static final String FINDER_CREATOR = "MACS"; 192 193 private static final String GURL_EVENT = "GURL"; 195 199 private static final String FIRST_WINDOWS_PARAMETER = "/c"; 201 202 private static final String SECOND_WINDOWS_PARAMETER = "start"; 204 209 private static final String THIRD_WINDOWS_PARAMETER = "\"\""; 211 215 private static final String NETSCAPE_REMOTE_PARAMETER = "-remote"; private static final String NETSCAPE_OPEN_PARAMETER_START = "'openURL("; private static final String NETSCAPE_OPEN_PARAMETER_END = ")'"; 219 223 private static String errorMessage; 224 225 229 static { 230 loadedWithoutErrors = true; 231 String osName = System.getProperty("os.name"); if (osName.startsWith("Mac OS")) { String javaVersion = System.getProperty("java.version"); String majorJavaVersion = javaVersion.substring(0, 3); 235 try { 236 double version = Double.valueOf(majorJavaVersion).doubleValue(); 237 if (version >= 1.4) { 238 jvm = MRJ_COCOA; 239 } 240 } catch (NumberFormatException nfe) { 241 } 243 if (jvm != MRJ_COCOA) { 244 String mrjVersion = System.getProperty("mrj.version"); String majorMRJVersion = mrjVersion.substring(0, 3); 246 try { 247 double version = Double.valueOf(majorMRJVersion).doubleValue(); 248 if (version == 2) { 249 jvm = MRJ_2_0; 250 } else if (version >= 2.1 && version < 3) { 251 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; 263 } else { 264 loadedWithoutErrors = false; 265 errorMessage = "Unsupported MRJ version: " + version; } 267 } catch (NumberFormatException nfe) { 268 loadedWithoutErrors = false; 269 errorMessage = "Invalid MRJ version: " + mrjVersion; } 271 } 272 } else if (osName.startsWith("Windows")) { if (osName.indexOf("9") != -1 || osName.indexOf("Me") != -1) { jvm = WINDOWS_9x; 275 } else { 276 jvm = WINDOWS_NT; 277 } 278 } else { 279 jvm = OTHER; 280 } 281 282 if (loadedWithoutErrors) { loadedWithoutErrors = loadClasses(); 284 } 285 } 286 287 290 private BrowserLauncher() { 291 } 292 293 300 public static void setBrowserCommand(String browserCommand) { 301 BrowserLauncher.browserCommand = browserCommand; 302 } 303 304 314 315 public static String [] splitString(String str, char delim, char quote, char escape) { 316 Vector v = new Vector (); 317 StringBuffer str1 = new StringBuffer (); 318 char ch = ' '; 319 boolean inQuote = false; 320 boolean escaped = false; 321 322 for (int i = 0; i < str.length(); i++) { 323 ch = str.charAt(i); 324 325 if ((escape != -1) && (ch == escape) && !escaped) { 326 escaped = true; 327 } else { 328 if ((quote != -1) && (ch == quote) && !escaped) { 329 inQuote = !inQuote; 330 } else if (!inQuote && (ch == delim && !escaped)) { 331 v.addElement(str1.toString()); 332 str1.setLength(0); 333 } else { 334 str1.append(ch); 335 } 336 if (escaped) { 337 escaped = false; 338 } 339 } 340 } 341 342 if (str.length() > 0) { 343 v.addElement(str1.toString()); 344 345 } 346 String [] array; 347 array = new String [v.size()]; 348 v.copyInto(array); 349 350 return array; 351 } 352 353 360 private static boolean loadClasses() { 361 switch (jvm) { 362 case MRJ_2_0 : 363 return loadMRJ20Classes(); 364 case MRJ_2_1 : 365 try { 366 mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils"); mrjOSTypeClass = Class.forName("com.apple.mrj.MRJOSType"); Field systemFolderField = mrjFileUtilsClass.getDeclaredField("kSystemFolderType"); kSystemFolderType = systemFolderField.get(null); 370 findFolder = mrjFileUtilsClass.getDeclaredMethod("findFolder", new Class []{mrjOSTypeClass}); getFileCreator = mrjFileUtilsClass.getDeclaredMethod("getFileCreator", new Class []{File .class}); getFileType = mrjFileUtilsClass.getDeclaredMethod("getFileType", new Class []{File .class}); } catch (ClassNotFoundException cnfe) { 374 errorMessage = cnfe.getMessage(); 375 return false; 376 } catch (NoSuchFieldException nsfe) { 377 errorMessage = nsfe.getMessage(); 378 return false; 379 } catch (NoSuchMethodException nsme) { 380 errorMessage = nsme.getMessage(); 381 return false; 382 } catch (SecurityException se) { 383 errorMessage = se.getMessage(); 384 return false; 385 } catch (IllegalAccessException iae) { 386 errorMessage = iae.getMessage(); 387 return false; 388 } 389 break; 390 case MRJ_3_0 : 391 try { 392 Class linker = Class.forName("com.apple.mrj.jdirect.Linker"); Constructor constructor = linker.getConstructor(new Class []{Class .class}); 394 linkage = constructor.newInstance(new Object []{BrowserLauncher.class}); 395 } catch (ClassNotFoundException cnfe) { 396 errorMessage = cnfe.getMessage(); 397 return false; 398 } catch (NoSuchMethodException nsme) { 399 errorMessage = nsme.getMessage(); 400 return false; 401 } catch (InvocationTargetException ite) { 402 errorMessage = ite.getMessage(); 403 return false; 404 } catch (InstantiationException ie) { 405 errorMessage = ie.getMessage(); 406 return false; 407 } catch (IllegalAccessException iae) { 408 errorMessage = iae.getMessage(); 409 return false; 410 } 411 break; 412 case MRJ_3_1 : 413 case MRJ_COCOA : 414 String className; 415 if (jvm == MRJ_3_1) { 416 className = "com.apple.mrj.MRJFileUtils"; } else { 418 className = "com.apple.eio.FileManager"; } 420 try { 421 mrjFileUtilsClass = Class.forName(className); 422 openURL = mrjFileUtilsClass.getDeclaredMethod("openURL", new Class []{String .class}); } catch (ClassNotFoundException cnfe) { 424 errorMessage = cnfe.getMessage(); 425 return false; 426 } catch (NoSuchMethodException nsme) { 427 errorMessage = nsme.getMessage(); 428 return false; 429 } 430 break; 431 default : 432 break; 433 } 434 return true; 435 } 436 437 444 private static boolean loadMRJ20Classes() { 445 try { 446 Class aeTargetClass = Class.forName("com.apple.MacOS.AETarget"); Class osUtilsClass = Class.forName("com.apple.MacOS.OSUtils"); Class appleEventClass = Class.forName("com.apple.MacOS.AppleEvent"); Class aeClass = Class.forName("com.apple.MacOS.ae"); aeDescClass = Class.forName("com.apple.MacOS.AEDesc"); 452 aeTargetConstructor = aeTargetClass.getDeclaredConstructor(new Class []{int.class}); 453 appleEventConstructor = appleEventClass.getDeclaredConstructor(new Class []{int.class, int.class, aeTargetClass, int.class, 454 int.class}); 455 aeDescConstructor = aeDescClass.getDeclaredConstructor(new Class []{String .class}); 456 457 makeOSType = osUtilsClass.getDeclaredMethod("makeOSType", new Class []{String .class}); putParameter = appleEventClass.getDeclaredMethod("putParameter", new Class []{int.class, aeDescClass}); sendNoReply = appleEventClass.getDeclaredMethod("sendNoReply", new Class []{}); 461 Field keyDirectObjectField = aeClass.getDeclaredField("keyDirectObject"); keyDirectObject = (Integer ) keyDirectObjectField.get(null); 463 Field autoGenerateReturnIDField = appleEventClass.getDeclaredField("kAutoGenerateReturnID"); kAutoGenerateReturnID = (Integer ) autoGenerateReturnIDField.get(null); 465 Field anyTransactionIDField = appleEventClass.getDeclaredField("kAnyTransactionID"); kAnyTransactionID = (Integer ) anyTransactionIDField.get(null); 467 } catch (ClassNotFoundException cnfe) { 468 errorMessage = cnfe.getMessage(); 469 return false; 470 } catch (NoSuchMethodException nsme) { 471 errorMessage = nsme.getMessage(); 472 return false; 473 } catch (NoSuchFieldException nsfe) { 474 errorMessage = nsfe.getMessage(); 475 return false; 476 } catch (IllegalAccessException iae) { 477 errorMessage = iae.getMessage(); 478 return false; 479 } 480 return true; 481 } 482 483 494 private static Object locateBrowser() { 495 if (browser != null) { 496 return browser; 497 } 498 switch (jvm) { 499 case MRJ_2_0 : 500 try { 501 Integer finderCreatorCode = (Integer ) makeOSType.invoke(null, new Object []{FINDER_CREATOR}); 502 Object aeTarget = aeTargetConstructor.newInstance(new Object []{finderCreatorCode}); 503 Integer gurlType = (Integer ) makeOSType.invoke(null, new Object []{GURL_EVENT}); 504 Object appleEvent = appleEventConstructor.newInstance(new Object []{gurlType, gurlType, aeTarget, kAutoGenerateReturnID, 505 kAnyTransactionID}); 506 return appleEvent; 515 } catch (IllegalAccessException iae) { 516 browser = null; 517 errorMessage = iae.getMessage(); 518 return browser; 519 } catch (InstantiationException ie) { 520 browser = null; 521 errorMessage = ie.getMessage(); 522 return browser; 523 } catch (InvocationTargetException ite) { 524 browser = null; 525 errorMessage = ite.getMessage(); 526 return browser; 527 } 528 case MRJ_2_1 : 529 File systemFolder; 530 try { 531 systemFolder = (File ) findFolder.invoke(null, new Object []{kSystemFolderType}); 532 } catch (IllegalArgumentException iare) { 533 browser = null; 534 errorMessage = iare.getMessage(); 535 return browser; 536 } catch (IllegalAccessException iae) { 537 browser = null; 538 errorMessage = iae.getMessage(); 539 return browser; 540 } catch (InvocationTargetException ite) { 541 browser = null; 542 errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); return browser; 544 } 545 String [] systemFolderFiles = systemFolder.list(); 546 for (int i = 0; i < systemFolderFiles.length; i++) { 548 try { 549 File file = new File (systemFolder, systemFolderFiles[i]); 550 if (!file.isFile()) { 551 continue; 552 } 553 Object fileType = getFileType.invoke(null, new Object []{file}); 559 if (FINDER_TYPE.equals(fileType.toString())) { 560 Object fileCreator = getFileCreator.invoke(null, new Object []{file}); 561 if (FINDER_CREATOR.equals(fileCreator.toString())) { 562 browser = file.toString(); return browser; 564 } 565 } 566 } catch (IllegalArgumentException iare) { 567 browser = null; 568 errorMessage = iare.getMessage(); 569 return null; 570 } catch (IllegalAccessException iae) { 571 browser = null; 572 errorMessage = iae.getMessage(); 573 return browser; 574 } catch (InvocationTargetException ite) { 575 browser = null; 576 errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); return browser; 578 } 579 } 580 browser = null; 581 break; 582 case MRJ_3_0 : 583 case MRJ_3_1 : 584 browser = ""; break; 586 case WINDOWS_NT : 587 browser = "cmd.exe"; break; 589 case WINDOWS_9x : 590 browser = "command.com"; break; 592 case OTHER : 593 default : 594 browser = getEnvironmentBrowser(); 600 if (browser == null) { 601 browser = "netscape"; } 603 break; 604 } 605 return browser; 606 } 607 608 616 public static void openURL(String url) throws IOException { 617 if (!loadedWithoutErrors) { 618 throw new IOException (MessageFormat.format(Messages.getString("BrowserLauncher.exceptionFindingBrowser"), new Object [] { errorMessage })); } 620 621 622 if(browserCommand != null) { 623 String [] cmd = splitString(browserCommand, ' ', '"', '\\'); 624 String [] cmde = new String [cmd.length + 1]; 625 System.arraycopy(cmd, 0, cmde, 0 , cmd.length); 626 cmde[cmd.length] = url; 627 Runtime.getRuntime().exec(cmde); 628 return; 629 } 630 631 Object browser = locateBrowser(); 632 if (browser == null) { 633 throw new IOException (MessageFormat.format(Messages.getString("BrowserLauncher.unableToLocateBrowser"), new Object [] { errorMessage } ) ); } 635 636 switch (jvm) { 637 case MRJ_2_0 : 638 Object aeDesc = null; 639 try { 640 aeDesc = aeDescConstructor.newInstance(new Object []{url}); 641 putParameter.invoke(browser, new Object []{keyDirectObject, aeDesc}); 642 sendNoReply.invoke(browser, new Object []{}); 643 } catch (InvocationTargetException ite) { 644 throw new IOException (MessageFormat.format(Messages.getString("BrowserLauncher.invocationTargetException"), new Object [] { ite.getMessage() } ) ); } catch (IllegalAccessException iae) { 646 throw new IOException (MessageFormat.format(Messages.getString("BrowserLauncher.illegalAccess"), new Object [] { iae.getMessage() } )); } catch (InstantiationException ie) { 648 throw new IOException (MessageFormat.format(Messages.getString("BrowserLauncher.instantiation"), new Object [] { ie.getMessage() } )); } finally { 650 aeDesc = null; browser = null; } 653 break; 654 case MRJ_2_1 : 655 Runtime.getRuntime().exec(new String []{(String ) browser, url}); 656 break; 657 case MRJ_3_0 : 658 int[] instance = new int[1]; 659 int result = ICStart(instance, 0); 660 if (result == 0) { 661 int[] selectionStart = new int[]{0}; 662 byte[] urlBytes = url.getBytes(); 663 int[] selectionEnd = new int[]{urlBytes.length}; 664 result = ICLaunchURL(instance[0], new byte[]{0}, urlBytes, urlBytes.length, selectionStart, selectionEnd); 665 if (result == 0) { 666 ICStop(instance); 669 } else { 670 throw new IOException (MessageFormat.format(Messages.getString("BrowserLauncher.cannotLaunchURL"), new Object [] { new Integer (result) } )); } 672 } else { 673 throw new IOException (MessageFormat.format(Messages.getString("BrowserLauncher.cannotCreateNetConfg"), new Object [] { new Integer (result) } ) ); } 675 break; 676 case MRJ_3_1 : 677 case MRJ_COCOA : 678 try { 679 openURL.invoke(null, new Object []{url}); 680 } catch (InvocationTargetException ite) { 681 throw new IOException (MessageFormat.format(Messages.getString("BrowserLauncher.cannotOpenURL"), new Object [] { ite.getMessage() } ) ); } catch (IllegalAccessException iae) { 683 throw new IOException (MessageFormat.format(Messages.getString("BrowserLauncher.ilegalAccessOpeningURL"), new Object [] { iae.getMessage() } ) ); } 685 break; 686 case WINDOWS_NT : 687 case WINDOWS_9x : 688 String [] arguments; 691 if (jvm == WINDOWS_9x) { 692 arguments = new String []{(String ) browser, FIRST_WINDOWS_PARAMETER, SECOND_WINDOWS_PARAMETER, null}; 693 } else { 694 arguments = new String []{(String ) browser, FIRST_WINDOWS_PARAMETER, SECOND_WINDOWS_PARAMETER, THIRD_WINDOWS_PARAMETER, 695 null}; 696 } 697 arguments[arguments.length - 1] = '"' + url + '"'; 698 Process process = Runtime.getRuntime().exec(arguments); 699 try { 703 process.waitFor(); 704 process.exitValue(); 705 } catch (InterruptedException ie) { 706 throw new IOException (Messages.getString("BrowserLauncher.interruptedLaunchingBrowser") + ie.getMessage()); } 708 break; 709 case OTHER : 710 712 process = Runtime.getRuntime().exec( 714 new String []{(String ) browser, NETSCAPE_REMOTE_PARAMETER, 715 NETSCAPE_OPEN_PARAMETER_START + url + NETSCAPE_OPEN_PARAMETER_END}); 716 try { 717 int exitCode = process.waitFor(); 718 if (exitCode != 0) { Runtime.getRuntime().exec(new String []{(String ) browser, url}); 720 } 721 } catch (InterruptedException ie) { 722 throw new IOException (MessageFormat.format(Messages.getString("BrowserLauncher.interruptedLaunchingBrowser"), new Object [] { ie.getMessage() } ) ); } 724 break; 725 default : 726 Runtime.getRuntime().exec(new String []{(String ) browser, url}); 729 break; 730 } 731 } 732 733 741 private static String getEnvironmentBrowser() { 742 String browser = null; 743 try { 744 String [] echoParams = {"/bin/sh", "-c", "echo ${BROWSER:-netscape}"}; Process echoProcess = Runtime.getRuntime().exec(echoParams); 746 InputStream echoStream = echoProcess.getInputStream(); 747 BufferedReader echoReader = new BufferedReader (new InputStreamReader (echoStream)); 748 browser = echoReader.readLine(); 749 echoReader.close(); 750 } catch (Throwable t) { 751 } 753 return browser; 754 } 755 756 760 private native static int ICStart(int[] instance, int signature); 761 private native static int ICStop(int[] instance); 762 private native static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len, int[] selectionStart, int[] selectionEnd); 763 } 764 | Popular Tags |