1 22 23 package luxor.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 179 182 private static Constructor aeDescConstructor; 183 184 187 private static Constructor aeTargetConstructor; 188 189 192 private static Constructor appleEventConstructor; 193 194 197 private static Object browser; 198 199 203 private static String errorMessage; 204 205 208 private static Method findFolder; 209 210 213 private static Method getFileCreator; 214 215 218 private static Method getFileType; 219 220 225 private static int jvm; 226 227 230 private static Integer kAnyTransactionID; 231 232 235 private static Integer kAutoGenerateReturnID; 236 237 240 private static Object kSystemFolderType; 241 242 245 private static Integer keyDirectObject; 246 247 250 private static Object linkage; 251 252 259 private static boolean loadedWithoutErrors; 260 261 264 private static Method makeOSType; 265 266 269 private static Class mrjFileUtilsClass; 270 271 274 private static Class mrjOSTypeClass; 275 276 279 private static Method openURL; 280 281 284 private static Method putParameter; 285 286 289 private static Method sendNoReply; 290 291 294 private BrowserLauncher() { } 295 296 303 public static void openURL( String url ) throws IOException 304 { 305 if( !loadedWithoutErrors ) 306 { 307 throw new IOException ( "Exception in finding browser: " + errorMessage ); 308 } 309 Object browser = locateBrowser(); 310 if( browser == null ) 311 { 312 throw new IOException ( "Unable to locate browser: " + errorMessage ); 313 } 314 315 switch ( jvm ) 316 { 317 case MRJ_2_0: 318 Object aeDesc = null; 319 try 320 { 321 aeDesc = aeDescConstructor.newInstance( new Object []{url} ); 322 putParameter.invoke( browser, new Object []{keyDirectObject, aeDesc} ); 323 sendNoReply.invoke( browser, new Object []{} ); 324 } 325 catch( InvocationTargetException ite ) 326 { 327 throw new IOException ( "InvocationTargetException while creating AEDesc: " + ite.getMessage() ); 328 } 329 catch( IllegalAccessException iae ) 330 { 331 throw new IOException ( "IllegalAccessException while building AppleEvent: " + iae.getMessage() ); 332 } 333 catch( InstantiationException ie ) 334 { 335 throw new IOException ( "InstantiationException while creating AEDesc: " + ie.getMessage() ); 336 } 337 finally 338 { 339 aeDesc = null; 340 browser = null; 342 } 344 break; 345 case MRJ_2_1: 346 Runtime.getRuntime().exec( new String []{( String ) browser, url} ); 347 break; 348 case MRJ_3_0: 349 int[] instance = new int[1]; 350 int result = ICStart( instance, 0 ); 351 if( result == 0 ) 352 { 353 int[] selectionStart = new int[]{0}; 354 byte[] urlBytes = url.getBytes(); 355 int[] selectionEnd = new int[]{urlBytes.length}; 356 result = ICLaunchURL( instance[0], new byte[]{0}, urlBytes, 357 urlBytes.length, selectionStart, 358 selectionEnd ); 359 if( result == 0 ) 360 { 361 ICStop( instance ); 364 } 365 else 366 { 367 throw new IOException ( "Unable to launch URL: " + result ); 368 } 369 } 370 else 371 { 372 throw new IOException ( "Unable to create an Internet Config instance: " + result ); 373 } 374 break; 375 case MRJ_3_1: 376 try 377 { 378 openURL.invoke( null, new Object []{url} ); 379 } 380 catch( InvocationTargetException ite ) 381 { 382 throw new IOException ( "InvocationTargetException while calling openURL: " + ite.getMessage() ); 383 } 384 catch( IllegalAccessException iae ) 385 { 386 throw new IOException ( "IllegalAccessException while calling openURL: " + iae.getMessage() ); 387 } 388 break; 389 case WINDOWS_NT: 390 case WINDOWS_9x: 391 Process process = Runtime.getRuntime().exec( new String []{( String ) browser, 394 FIRST_WINDOWS_PARAMETER, 395 SECOND_WINDOWS_PARAMETER, 396 THIRD_WINDOWS_PARAMETER, 397 '"' + url + '"'} ); 398 try 401 { 402 process.waitFor(); 403 process.exitValue(); 404 } 405 catch( InterruptedException ie ) 406 { 407 throw new IOException ( "InterruptedException while launching browser: " + ie.getMessage() ); 408 } 409 break; 410 case OTHER: 411 413 process = Runtime.getRuntime().exec( new String []{( String ) browser, 415 NETSCAPE_REMOTE_PARAMETER, 416 NETSCAPE_OPEN_PARAMETER_START + 417 url + 418 NETSCAPE_OPEN_PARAMETER_END} ); 419 try 420 { 421 int exitCode = process.waitFor(); 422 if( exitCode != 0 ) 423 { 424 Runtime.getRuntime().exec( new String []{( String ) browser, url} ); 426 } 427 } 428 catch( InterruptedException ie ) 429 { 430 throw new IOException ( "InterruptedException while launching browser: " + ie.getMessage() ); 431 } 432 break; 433 default: 434 Runtime.getRuntime().exec( new String []{( String ) browser, url} ); 436 break; 437 } 438 } 439 440 private native static int ICLaunchURL( int instance, byte[] hint, byte[] data, int len, 441 int[] selectionStart, int[] selectionEnd ); 442 443 447 private native static int ICStart( int[] instance, int signature ); 448 449 private native static int ICStop( int[] instance ); 450 451 458 private static boolean loadClasses() 459 { 460 switch ( jvm ) 461 { 462 case MRJ_2_0: 463 try 464 { 465 Class aeTargetClass = Class.forName( "com.apple.MacOS.AETarget" ); 466 Class osUtilsClass = Class.forName( "com.apple.MacOS.OSUtils" ); 467 Class appleEventClass = Class.forName( "com.apple.MacOS.AppleEvent" ); 468 Class aeClass = Class.forName( "com.apple.MacOS.ae" ); 469 aeDescClass = Class.forName( "com.apple.MacOS.AEDesc" ); 470 471 aeTargetConstructor = aeTargetClass.getDeclaredConstructor( new Class []{int.class} ); 472 appleEventConstructor = appleEventClass.getDeclaredConstructor( new Class []{int.class, int.class, aeTargetClass, int.class, int.class} ); 473 aeDescConstructor = aeDescClass.getDeclaredConstructor( new Class []{String .class} ); 474 475 makeOSType = osUtilsClass.getDeclaredMethod( "makeOSType", new Class []{String .class} ); 476 putParameter = appleEventClass.getDeclaredMethod( "putParameter", new Class []{int.class, aeDescClass} ); 477 sendNoReply = appleEventClass.getDeclaredMethod( "sendNoReply", new Class []{} ); 478 479 Field keyDirectObjectField = aeClass.getDeclaredField( "keyDirectObject" ); 480 keyDirectObject = ( Integer ) keyDirectObjectField.get( null ); 481 Field autoGenerateReturnIDField = appleEventClass.getDeclaredField( "kAutoGenerateReturnID" ); 482 kAutoGenerateReturnID = ( Integer ) autoGenerateReturnIDField.get( null ); 483 Field anyTransactionIDField = appleEventClass.getDeclaredField( "kAnyTransactionID" ); 484 kAnyTransactionID = ( Integer ) anyTransactionIDField.get( null ); 485 } 486 catch( ClassNotFoundException cnfe ) 487 { 488 errorMessage = cnfe.getMessage(); 489 return false; 490 } 491 catch( NoSuchMethodException nsme ) 492 { 493 errorMessage = nsme.getMessage(); 494 return false; 495 } 496 catch( NoSuchFieldException nsfe ) 497 { 498 errorMessage = nsfe.getMessage(); 499 return false; 500 } 501 catch( IllegalAccessException iae ) 502 { 503 errorMessage = iae.getMessage(); 504 return false; 505 } 506 break; 507 case MRJ_2_1: 508 try 509 { 510 mrjFileUtilsClass = Class.forName( "com.apple.mrj.MRJFileUtils" ); 511 mrjOSTypeClass = Class.forName( "com.apple.mrj.MRJOSType" ); 512 Field systemFolderField = mrjFileUtilsClass.getDeclaredField( "kSystemFolderType" ); 513 kSystemFolderType = systemFolderField.get( null ); 514 findFolder = mrjFileUtilsClass.getDeclaredMethod( "findFolder", new Class []{mrjOSTypeClass} ); 515 getFileCreator = mrjFileUtilsClass.getDeclaredMethod( "getFileCreator", new Class []{File .class} ); 516 getFileType = mrjFileUtilsClass.getDeclaredMethod( "getFileType", new Class []{File .class} ); 517 } 518 catch( ClassNotFoundException cnfe ) 519 { 520 errorMessage = cnfe.getMessage(); 521 return false; 522 } 523 catch( NoSuchFieldException nsfe ) 524 { 525 errorMessage = nsfe.getMessage(); 526 return false; 527 } 528 catch( NoSuchMethodException nsme ) 529 { 530 errorMessage = nsme.getMessage(); 531 return false; 532 } 533 catch( SecurityException se ) 534 { 535 errorMessage = se.getMessage(); 536 return false; 537 } 538 catch( IllegalAccessException iae ) 539 { 540 errorMessage = iae.getMessage(); 541 return false; 542 } 543 break; 544 case MRJ_3_0: 545 try 546 { 547 Class linker = Class.forName( "com.apple.mrj.jdirect.Linker" ); 548 Constructor constructor = linker.getConstructor( new Class []{Class .class} ); 549 linkage = constructor.newInstance( new Object []{BrowserLauncher.class} ); 550 } 551 catch( ClassNotFoundException cnfe ) 552 { 553 errorMessage = cnfe.getMessage(); 554 return false; 555 } 556 catch( NoSuchMethodException nsme ) 557 { 558 errorMessage = nsme.getMessage(); 559 return false; 560 } 561 catch( InvocationTargetException ite ) 562 { 563 errorMessage = ite.getMessage(); 564 return false; 565 } 566 catch( InstantiationException ie ) 567 { 568 errorMessage = ie.getMessage(); 569 return false; 570 } 571 catch( IllegalAccessException iae ) 572 { 573 errorMessage = iae.getMessage(); 574 return false; 575 } 576 break; 577 case MRJ_3_1: 578 try 579 { 580 mrjFileUtilsClass = Class.forName( "com.apple.mrj.MRJFileUtils" ); 581 openURL = mrjFileUtilsClass.getDeclaredMethod( "openURL", new Class []{String .class} ); 582 } 583 catch( ClassNotFoundException cnfe ) 584 { 585 errorMessage = cnfe.getMessage(); 586 return false; 587 } 588 catch( NoSuchMethodException nsme ) 589 { 590 errorMessage = nsme.getMessage(); 591 return false; 592 } 593 break; 594 default: 595 break; 596 } 597 return true; 598 } 599 600 611 private static Object locateBrowser() 612 { 613 if( browser != null ) 614 { 615 return browser; 616 } 617 switch ( jvm ) 618 { 619 case MRJ_2_0: 620 try 621 { 622 Integer finderCreatorCode = ( Integer ) makeOSType.invoke( null, new Object []{FINDER_CREATOR} ); 623 Object aeTarget = aeTargetConstructor.newInstance( new Object []{finderCreatorCode} ); 624 Integer gurlType = ( Integer ) makeOSType.invoke( null, new Object []{GURL_EVENT} ); 625 Object appleEvent = appleEventConstructor.newInstance( new Object []{gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID} ); 626 return appleEvent; 632 } 633 catch( IllegalAccessException iae ) 634 { 635 browser = null; 636 errorMessage = iae.getMessage(); 637 return browser; 638 } 639 catch( InstantiationException ie ) 640 { 641 browser = null; 642 errorMessage = ie.getMessage(); 643 return browser; 644 } 645 catch( InvocationTargetException ite ) 646 { 647 browser = null; 648 errorMessage = ite.getMessage(); 649 return browser; 650 } 651 case MRJ_2_1: 652 File systemFolder; 653 try 654 { 655 systemFolder = ( File ) findFolder.invoke( null, new Object []{kSystemFolderType} ); 656 } 657 catch( IllegalArgumentException iare ) 658 { 659 browser = null; 660 errorMessage = iare.getMessage(); 661 return browser; 662 } 663 catch( IllegalAccessException iae ) 664 { 665 browser = null; 666 errorMessage = iae.getMessage(); 667 return browser; 668 } 669 catch( InvocationTargetException ite ) 670 { 671 browser = null; 672 errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); 673 return browser; 674 } 675 String [] systemFolderFiles = systemFolder.list(); 676 for( int i = 0; i < systemFolderFiles.length; i++ ) 678 { 679 try 680 { 681 File file = new File ( systemFolder, systemFolderFiles[i] ); 682 if( !file.isFile() ) 683 { 684 continue; 685 } 686 Object fileType = getFileType.invoke( null, new Object []{file} ); 692 if( FINDER_TYPE.equals( fileType.toString() ) ) 693 { 694 Object fileCreator = getFileCreator.invoke( null, new Object []{file} ); 695 if( FINDER_CREATOR.equals( fileCreator.toString() ) ) 696 { 697 browser = file.toString(); 698 return browser; 700 } 701 } 702 } 703 catch( IllegalArgumentException iare ) 704 { 705 browser = browser; 706 errorMessage = iare.getMessage(); 707 return null; 708 } 709 catch( IllegalAccessException iae ) 710 { 711 browser = null; 712 errorMessage = iae.getMessage(); 713 return browser; 714 } 715 catch( InvocationTargetException ite ) 716 { 717 browser = null; 718 errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); 719 return browser; 720 } 721 } 722 browser = null; 723 break; 724 case MRJ_3_0: 725 case MRJ_3_1: 726 browser = ""; 727 break; 729 case WINDOWS_NT: 730 browser = "cmd.exe"; 731 break; 732 case WINDOWS_9x: 733 browser = "command.com"; 734 break; 735 case OTHER: 736 default: 737 browser = "netscape"; 738 break; 739 } 740 return browser; 741 } 742 743 static 744 { 745 loadedWithoutErrors = true; 746 String osName = System.getProperty( "os.name" ); 747 if( osName.startsWith( "Mac OS" ) ) 748 { 749 String mrjVersion = System.getProperty( "mrj.version" ); 750 String majorMRJVersion = mrjVersion.substring( 0, 3 ); 751 try 752 { 753 double version = Double.valueOf( majorMRJVersion ).doubleValue(); 754 if( version == 2 ) 755 { 756 jvm = MRJ_2_0; 757 } 758 else if( version >= 2.1 && version < 3 ) 759 { 760 jvm = MRJ_2_1; 764 } 765 else if( version == 3.0 ) 766 { 767 jvm = MRJ_3_0; 768 } 769 else if( version >= 3.1 ) 770 { 771 jvm = MRJ_3_1; 773 } 774 else 775 { 776 loadedWithoutErrors = false; 777 errorMessage = "Unsupported MRJ version: " + version; 778 } 779 } 780 catch( NumberFormatException nfe ) 781 { 782 loadedWithoutErrors = false; 783 errorMessage = "Invalid MRJ version: " + mrjVersion; 784 } 785 } 786 else if( osName.startsWith( "Windows" ) ) 787 { 788 if( osName.indexOf( "9" ) != -1 ) 789 { 790 jvm = WINDOWS_9x; 791 } 792 else 793 { 794 jvm = WINDOWS_NT; 795 } 796 } 797 else 798 { 799 jvm = OTHER; 800 } 801 802 if( loadedWithoutErrors ) 803 { 804 loadedWithoutErrors = loadClasses(); 806 } 807 } 808 } 809 | Popular Tags |