1 22 23 package apollo.dev.browser.albert; 24 25 import java.io.File ; 26 import java.io.FileNotFoundException ; 27 import java.io.IOException ; 28 import java.lang.reflect.Constructor ; 29 import java.lang.reflect.Field ; 30 import java.lang.reflect.InvocationTargetException ; 31 import java.lang.reflect.Method ; 32 33 87 public class BrowserLauncher 88 { 89 90 94 private final static String FINDER_CREATOR = "MACS"; 95 96 100 private final static String FINDER_TYPE = "FNDR"; 101 102 106 private final static String FIRST_WINDOWS_PARAMETER = "/c"; 107 108 111 private final static String GURL_EVENT = "GURL"; 112 113 116 private final static String JDirect_MacOSX = "/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox"; 117 118 121 private final static int MRJ_2_0 = 0; 122 123 126 private final static int MRJ_2_1 = 1; 127 128 131 private final static int MRJ_3_0 = 3; 132 133 136 private final static int MRJ_3_1 = 4; 137 private final static String NETSCAPE_OPEN_PARAMETER_END = ")'"; 138 private final static String NETSCAPE_OPEN_PARAMETER_START = "'openURL("; 139 140 144 private final static String NETSCAPE_REMOTE_PARAMETER = "-remote"; 145 146 149 private final static int OTHER = -1; 150 151 154 private final static String SECOND_WINDOWS_PARAMETER = "start"; 155 156 161 private final static String THIRD_WINDOWS_PARAMETER = "\"\""; 162 163 166 private final static int WINDOWS_9x = 6; 167 168 171 private final static int WINDOWS_NT = 5; 172 173 176 private static Class aeDescClass; 177 178 181 private static Constructor aeDescConstructor; 182 183 186 private static Constructor aeTargetConstructor; 187 188 191 private static Constructor appleEventConstructor; 192 193 196 private static Object browser; 197 198 202 private static String errorMessage; 203 204 207 private static Method findFolder; 208 209 212 private static Method getFileCreator; 213 214 217 private static Method getFileType; 218 219 224 private static int jvm; 225 226 229 private static Integer kAnyTransactionID; 230 231 234 private static Integer kAutoGenerateReturnID; 235 236 239 private static Object kSystemFolderType; 240 241 244 private static Integer keyDirectObject; 245 246 249 private static Object linkage; 250 251 258 private static boolean loadedWithoutErrors; 259 260 263 private static Method makeOSType; 264 265 268 private static Class mrjFileUtilsClass; 269 270 273 private static Class mrjOSTypeClass; 274 275 278 private static Method openURL; 279 280 283 private static Method putParameter; 284 285 288 private static Method sendNoReply; 289 290 293 private BrowserLauncher() { } 294 295 302 public static void openURL( String url ) throws IOException 303 { 304 if( !loadedWithoutErrors ) 305 { 306 throw new IOException ( "Exception in finding browser: " + errorMessage ); 307 } 308 Object browser = locateBrowser(); 309 if( browser == null ) 310 { 311 throw new IOException ( "Unable to locate browser: " + errorMessage ); 312 } 313 314 switch ( jvm ) 315 { 316 case MRJ_2_0: 317 Object aeDesc = null; 318 try 319 { 320 aeDesc = aeDescConstructor.newInstance( new Object []{url} ); 321 putParameter.invoke( browser, new Object []{keyDirectObject, aeDesc} ); 322 sendNoReply.invoke( browser, new Object []{} ); 323 } 324 catch( InvocationTargetException ite ) 325 { 326 throw new IOException ( "InvocationTargetException while creating AEDesc: " + ite.getMessage() ); 327 } 328 catch( IllegalAccessException iae ) 329 { 330 throw new IOException ( "IllegalAccessException while building AppleEvent: " + iae.getMessage() ); 331 } 332 catch( InstantiationException ie ) 333 { 334 throw new IOException ( "InstantiationException while creating AEDesc: " + ie.getMessage() ); 335 } 336 finally 337 { 338 aeDesc = null; 339 browser = null; 341 } 343 break; 344 case MRJ_2_1: 345 Runtime.getRuntime().exec( new String []{( String ) browser, url} ); 346 break; 347 case MRJ_3_0: 348 int[] instance = new int[1]; 349 int result = ICStart( instance, 0 ); 350 if( result == 0 ) 351 { 352 int[] selectionStart = new int[]{0}; 353 byte[] urlBytes = url.getBytes(); 354 int[] selectionEnd = new int[]{urlBytes.length}; 355 result = ICLaunchURL( instance[0], new byte[]{0}, urlBytes, 356 urlBytes.length, selectionStart, 357 selectionEnd ); 358 if( result == 0 ) 359 { 360 ICStop( instance ); 363 } 364 else 365 { 366 throw new IOException ( "Unable to launch URL: " + result ); 367 } 368 } 369 else 370 { 371 throw new IOException ( "Unable to create an Internet Config instance: " + result ); 372 } 373 break; 374 case MRJ_3_1: 375 try 376 { 377 openURL.invoke( null, new Object []{url} ); 378 } 379 catch( InvocationTargetException ite ) 380 { 381 throw new IOException ( "InvocationTargetException while calling openURL: " + ite.getMessage() ); 382 } 383 catch( IllegalAccessException iae ) 384 { 385 throw new IOException ( "IllegalAccessException while calling openURL: " + iae.getMessage() ); 386 } 387 break; 388 case WINDOWS_NT: 389 case WINDOWS_9x: 390 Process process = Runtime.getRuntime().exec( new String []{( String ) browser, 393 FIRST_WINDOWS_PARAMETER, 394 SECOND_WINDOWS_PARAMETER, 395 THIRD_WINDOWS_PARAMETER, 396 '"' + url + '"'} ); 397 try 400 { 401 process.waitFor(); 402 process.exitValue(); 403 } 404 catch( InterruptedException ie ) 405 { 406 throw new IOException ( "InterruptedException while launching browser: " + ie.getMessage() ); 407 } 408 break; 409 case OTHER: 410 412 process = Runtime.getRuntime().exec( new String []{( String ) browser, 414 NETSCAPE_REMOTE_PARAMETER, 415 NETSCAPE_OPEN_PARAMETER_START + 416 url + 417 NETSCAPE_OPEN_PARAMETER_END} ); 418 try 419 { 420 int exitCode = process.waitFor(); 421 if( exitCode != 0 ) 422 { 423 Runtime.getRuntime().exec( new String []{( String ) browser, url} ); 425 } 426 } 427 catch( InterruptedException ie ) 428 { 429 throw new IOException ( "InterruptedException while launching browser: " + ie.getMessage() ); 430 } 431 break; 432 default: 433 Runtime.getRuntime().exec( new String []{( String ) browser, url} ); 435 break; 436 } 437 } 438 439 private native static int ICLaunchURL( int instance, byte[] hint, byte[] data, int len, 440 int[] selectionStart, int[] selectionEnd ); 441 442 446 private native static int ICStart( int[] instance, int signature ); 447 448 private native static int ICStop( int[] instance ); 449 450 457 private static boolean loadClasses() 458 { 459 switch ( jvm ) 460 { 461 case MRJ_2_0: 462 try 463 { 464 Class aeTargetClass = Class.forName( "com.apple.MacOS.AETarget" ); 465 Class osUtilsClass = Class.forName( "com.apple.MacOS.OSUtils" ); 466 Class appleEventClass = Class.forName( "com.apple.MacOS.AppleEvent" ); 467 Class aeClass = Class.forName( "com.apple.MacOS.ae" ); 468 aeDescClass = Class.forName( "com.apple.MacOS.AEDesc" ); 469 470 aeTargetConstructor = aeTargetClass.getDeclaredConstructor( new Class []{int.class} ); 471 appleEventConstructor = appleEventClass.getDeclaredConstructor( new Class []{int.class, int.class, aeTargetClass, int.class, int.class} ); 472 aeDescConstructor = aeDescClass.getDeclaredConstructor( new Class []{String .class} ); 473 474 makeOSType = osUtilsClass.getDeclaredMethod( "makeOSType", new Class []{String .class} ); 475 putParameter = appleEventClass.getDeclaredMethod( "putParameter", new Class []{int.class, aeDescClass} ); 476 sendNoReply = appleEventClass.getDeclaredMethod( "sendNoReply", new Class []{} ); 477 478 Field keyDirectObjectField = aeClass.getDeclaredField( "keyDirectObject" ); 479 keyDirectObject = ( Integer ) keyDirectObjectField.get( null ); 480 Field autoGenerateReturnIDField = appleEventClass.getDeclaredField( "kAutoGenerateReturnID" ); 481 kAutoGenerateReturnID = ( Integer ) autoGenerateReturnIDField.get( null ); 482 Field anyTransactionIDField = appleEventClass.getDeclaredField( "kAnyTransactionID" ); 483 kAnyTransactionID = ( Integer ) anyTransactionIDField.get( null ); 484 } 485 catch( ClassNotFoundException cnfe ) 486 { 487 errorMessage = cnfe.getMessage(); 488 return false; 489 } 490 catch( NoSuchMethodException nsme ) 491 { 492 errorMessage = nsme.getMessage(); 493 return false; 494 } 495 catch( NoSuchFieldException nsfe ) 496 { 497 errorMessage = nsfe.getMessage(); 498 return false; 499 } 500 catch( IllegalAccessException iae ) 501 { 502 errorMessage = iae.getMessage(); 503 return false; 504 } 505 break; 506 case MRJ_2_1: 507 try 508 { 509 mrjFileUtilsClass = Class.forName( "com.apple.mrj.MRJFileUtils" ); 510 mrjOSTypeClass = Class.forName( "com.apple.mrj.MRJOSType" ); 511 Field systemFolderField = mrjFileUtilsClass.getDeclaredField( "kSystemFolderType" ); 512 kSystemFolderType = systemFolderField.get( null ); 513 findFolder = mrjFileUtilsClass.getDeclaredMethod( "findFolder", new Class []{mrjOSTypeClass} ); 514 getFileCreator = mrjFileUtilsClass.getDeclaredMethod( "getFileCreator", new Class []{File .class} ); 515 getFileType = mrjFileUtilsClass.getDeclaredMethod( "getFileType", new Class []{File .class} ); 516 } 517 catch( ClassNotFoundException cnfe ) 518 { 519 errorMessage = cnfe.getMessage(); 520 return false; 521 } 522 catch( NoSuchFieldException nsfe ) 523 { 524 errorMessage = nsfe.getMessage(); 525 return false; 526 } 527 catch( NoSuchMethodException nsme ) 528 { 529 errorMessage = nsme.getMessage(); 530 return false; 531 } 532 catch( SecurityException se ) 533 { 534 errorMessage = se.getMessage(); 535 return false; 536 } 537 catch( IllegalAccessException iae ) 538 { 539 errorMessage = iae.getMessage(); 540 return false; 541 } 542 break; 543 case MRJ_3_0: 544 try 545 { 546 Class linker = Class.forName( "com.apple.mrj.jdirect.Linker" ); 547 Constructor constructor = linker.getConstructor( new Class []{Class .class} ); 548 linkage = constructor.newInstance( new Object []{BrowserLauncher.class} ); 549 } 550 catch( ClassNotFoundException cnfe ) 551 { 552 errorMessage = cnfe.getMessage(); 553 return false; 554 } 555 catch( NoSuchMethodException nsme ) 556 { 557 errorMessage = nsme.getMessage(); 558 return false; 559 } 560 catch( InvocationTargetException ite ) 561 { 562 errorMessage = ite.getMessage(); 563 return false; 564 } 565 catch( InstantiationException ie ) 566 { 567 errorMessage = ie.getMessage(); 568 return false; 569 } 570 catch( IllegalAccessException iae ) 571 { 572 errorMessage = iae.getMessage(); 573 return false; 574 } 575 break; 576 case MRJ_3_1: 577 try 578 { 579 mrjFileUtilsClass = Class.forName( "com.apple.mrj.MRJFileUtils" ); 580 openURL = mrjFileUtilsClass.getDeclaredMethod( "openURL", new Class []{String .class} ); 581 } 582 catch( ClassNotFoundException cnfe ) 583 { 584 errorMessage = cnfe.getMessage(); 585 return false; 586 } 587 catch( NoSuchMethodException nsme ) 588 { 589 errorMessage = nsme.getMessage(); 590 return false; 591 } 592 break; 593 default: 594 break; 595 } 596 return true; 597 } 598 599 610 private static Object locateBrowser() 611 { 612 if( browser != null ) 613 { 614 return browser; 615 } 616 switch ( jvm ) 617 { 618 case MRJ_2_0: 619 try 620 { 621 Integer finderCreatorCode = ( Integer ) makeOSType.invoke( null, new Object []{FINDER_CREATOR} ); 622 Object aeTarget = aeTargetConstructor.newInstance( new Object []{finderCreatorCode} ); 623 Integer gurlType = ( Integer ) makeOSType.invoke( null, new Object []{GURL_EVENT} ); 624 Object appleEvent = appleEventConstructor.newInstance( new Object []{gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID} ); 625 return appleEvent; 631 } 632 catch( IllegalAccessException iae ) 633 { 634 browser = null; 635 errorMessage = iae.getMessage(); 636 return browser; 637 } 638 catch( InstantiationException ie ) 639 { 640 browser = null; 641 errorMessage = ie.getMessage(); 642 return browser; 643 } 644 catch( InvocationTargetException ite ) 645 { 646 browser = null; 647 errorMessage = ite.getMessage(); 648 return browser; 649 } 650 case MRJ_2_1: 651 File systemFolder; 652 try 653 { 654 systemFolder = ( File ) findFolder.invoke( null, new Object []{kSystemFolderType} ); 655 } 656 catch( IllegalArgumentException iare ) 657 { 658 browser = null; 659 errorMessage = iare.getMessage(); 660 return browser; 661 } 662 catch( IllegalAccessException iae ) 663 { 664 browser = null; 665 errorMessage = iae.getMessage(); 666 return browser; 667 } 668 catch( InvocationTargetException ite ) 669 { 670 browser = null; 671 errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); 672 return browser; 673 } 674 String [] systemFolderFiles = systemFolder.list(); 675 for( int i = 0; i < systemFolderFiles.length; i++ ) 677 { 678 try 679 { 680 File file = new File ( systemFolder, systemFolderFiles[i] ); 681 if( !file.isFile() ) 682 { 683 continue; 684 } 685 Object fileType = getFileType.invoke( null, new Object []{file} ); 691 if( FINDER_TYPE.equals( fileType.toString() ) ) 692 { 693 Object fileCreator = getFileCreator.invoke( null, new Object []{file} ); 694 if( FINDER_CREATOR.equals( fileCreator.toString() ) ) 695 { 696 browser = file.toString(); 697 return browser; 699 } 700 } 701 } 702 catch( IllegalArgumentException iare ) 703 { 704 browser = browser; 705 errorMessage = iare.getMessage(); 706 return null; 707 } 708 catch( IllegalAccessException iae ) 709 { 710 browser = null; 711 errorMessage = iae.getMessage(); 712 return browser; 713 } 714 catch( InvocationTargetException ite ) 715 { 716 browser = null; 717 errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); 718 return browser; 719 } 720 } 721 browser = null; 722 break; 723 case MRJ_3_0: 724 case MRJ_3_1: 725 browser = ""; 726 break; 728 case WINDOWS_NT: 729 browser = "cmd.exe"; 730 break; 731 case WINDOWS_9x: 732 browser = "command.com"; 733 break; 734 case OTHER: 735 default: 736 browser = "netscape"; 737 break; 738 } 739 return browser; 740 } 741 742 static 743 { 744 loadedWithoutErrors = true; 745 String osName = System.getProperty( "os.name" ); 746 if( osName.startsWith( "Mac OS" ) ) 747 { 748 String mrjVersion = System.getProperty( "mrj.version" ); 749 String majorMRJVersion = mrjVersion.substring( 0, 3 ); 750 try 751 { 752 double version = Double.valueOf( majorMRJVersion ).doubleValue(); 753 if( version == 2 ) 754 { 755 jvm = MRJ_2_0; 756 } 757 else if( version >= 2.1 && version < 3 ) 758 { 759 jvm = MRJ_2_1; 763 } 764 else if( version == 3.0 ) 765 { 766 jvm = MRJ_3_0; 767 } 768 else if( version >= 3.1 ) 769 { 770 jvm = MRJ_3_1; 772 } 773 else 774 { 775 loadedWithoutErrors = false; 776 errorMessage = "Unsupported MRJ version: " + version; 777 } 778 } 779 catch( NumberFormatException nfe ) 780 { 781 loadedWithoutErrors = false; 782 errorMessage = "Invalid MRJ version: " + mrjVersion; 783 } 784 } 785 else if( osName.startsWith( "Windows" ) ) 786 { 787 if( osName.indexOf( "9" ) != -1 ) 788 { 789 jvm = WINDOWS_9x; 790 } 791 else 792 { 793 jvm = WINDOWS_NT; 794 } 795 } 796 else 797 { 798 jvm = OTHER; 799 } 800 801 if( loadedWithoutErrors ) 802 { 803 loadedWithoutErrors = loadClasses(); 805 } 806 } 807 } 808 | Popular Tags |