00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 package luxor.browser.albert;
00024
00025
import java.io.File;
00026
import java.io.FileNotFoundException;
00027
import java.io.IOException;
00028
import java.lang.reflect.Constructor;
00029
import java.lang.reflect.Field;
00030
import java.lang.reflect.InvocationTargetException;
00031
import java.lang.reflect.Method;
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 public class BrowserLauncher
00088 {
00089
00090
00091
00092
00093
00094 private final static String
FINDER_CREATOR =
"MACS";
00095
00096
00097
00098
00099
00100 private final static String
FINDER_TYPE =
"FNDR";
00101
00102
00103
00104
00105
00106 private final static String
FIRST_WINDOWS_PARAMETER =
"/c";
00107
00108
00109
00110
00111 private final static String
GURL_EVENT =
"GURL";
00112
00113
00114
00115
00116 private final static String
JDirect_MacOSX =
"/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox";
00117
00118
00119
00120
00121 private final static int MRJ_2_0 = 0;
00122
00123
00124
00125
00126 private final static int MRJ_2_1 = 1;
00127
00128
00129
00130
00131 private final static int MRJ_3_0 = 3;
00132
00133
00134
00135
00136 private final static int MRJ_3_1 = 4;
00137 private final static String
NETSCAPE_OPEN_PARAMETER_END =
")'";
00138 private final static String
NETSCAPE_OPEN_PARAMETER_START =
"'openURL(";
00139
00140
00141
00142
00143
00144 private final static String
NETSCAPE_REMOTE_PARAMETER =
"-remote";
00145
00146
00147
00148
00149 private final static int OTHER = -1;
00150
00151
00152
00153
00154 private final static String
SECOND_WINDOWS_PARAMETER =
"start";
00155
00156
00157
00158
00159
00160
00161 private final static String
THIRD_WINDOWS_PARAMETER =
"\"\"";
00162
00163
00164
00165
00166 private final static int WINDOWS_9x = 6;
00167
00168
00169
00170
00171 private final static int WINDOWS_NT = 5;
00172
00173
00174
00175
00176 private static Class
aeDescClass;
00177
00178
00179
00180
00181
00182 private static Constructor
aeDescConstructor;
00183
00184
00185
00186
00187 private static Constructor
aeTargetConstructor;
00188
00189
00190
00191
00192 private static Constructor
appleEventConstructor;
00193
00194
00195
00196
00197 private static Object
browser;
00198
00199
00200
00201
00202
00203 private static String
errorMessage;
00204
00205
00206
00207
00208 private static Method
findFolder;
00209
00210
00211
00212
00213 private static Method
getFileCreator;
00214
00215
00216
00217
00218 private static Method
getFileType;
00219
00220
00221
00222
00223
00224
00225 private static int jvm;
00226
00227
00228
00229
00230 private static Integer
kAnyTransactionID;
00231
00232
00233
00234
00235 private static Integer
kAutoGenerateReturnID;
00236
00237
00238
00239
00240 private static Object
kSystemFolderType;
00241
00242
00243
00244
00245 private static Integer
keyDirectObject;
00246
00247
00248
00249
00250 private static Object
linkage;
00251
00252
00253
00254
00255
00256
00257
00258
00259 private static boolean loadedWithoutErrors;
00260
00261
00262
00263
00264 private static Method
makeOSType;
00265
00266
00267
00268
00269 private static Class
mrjFileUtilsClass;
00270
00271
00272
00273
00274 private static Class
mrjOSTypeClass;
00275
00276
00277
00278
00279 private static Method
openURL;
00280
00281
00282
00283
00284 private static Method
putParameter;
00285
00286
00287
00288
00289 private static Method
sendNoReply;
00290
00291
00292
00293
00294 private BrowserLauncher() { }
00295
00296
00297
00298
00299
00300
00301
00302
00303 public static void openURL( String url )
throws IOException
00304 {
00305
if( !
loadedWithoutErrors )
00306 {
00307
throw new IOException(
"Exception in finding browser: " +
errorMessage );
00308 }
00309 Object
browser =
locateBrowser();
00310
if( browser == null )
00311 {
00312
throw new IOException(
"Unable to locate browser: " +
errorMessage );
00313 }
00314
00315
switch (
jvm )
00316 {
00317
case MRJ_2_0:
00318 Object aeDesc = null;
00319
try
00320 {
00321 aeDesc =
aeDescConstructor.newInstance(
new Object[]{url} );
00322
putParameter.invoke( browser,
new Object[]{
keyDirectObject, aeDesc} );
00323
sendNoReply.invoke( browser,
new Object[]{} );
00324 }
00325
catch( InvocationTargetException ite )
00326 {
00327
throw new IOException(
"InvocationTargetException while creating AEDesc: " + ite.getMessage() );
00328 }
00329
catch( IllegalAccessException iae )
00330 {
00331
throw new IOException(
"IllegalAccessException while building AppleEvent: " + iae.getMessage() );
00332 }
00333
catch( InstantiationException ie )
00334 {
00335
throw new IOException(
"InstantiationException while creating AEDesc: " + ie.getMessage() );
00336 }
00337 finally
00338 {
00339 aeDesc = null;
00340
00341 browser = null;
00342
00343 }
00344
break;
00345
case MRJ_2_1:
00346 Runtime.getRuntime().exec(
new String[]{( String ) browser, url} );
00347
break;
00348
case MRJ_3_0:
00349
int[] instance =
new int[1];
00350
int result =
ICStart( instance, 0 );
00351
if( result == 0 )
00352 {
00353
int[] selectionStart =
new int[]{0};
00354 byte[] urlBytes = url.getBytes();
00355
int[] selectionEnd =
new int[]{urlBytes.length};
00356 result =
ICLaunchURL( instance[0],
new byte[]{0}, urlBytes,
00357 urlBytes.length, selectionStart,
00358 selectionEnd );
00359
if( result == 0 )
00360 {
00361
00362
00363
ICStop( instance );
00364 }
00365
else
00366 {
00367
throw new IOException(
"Unable to launch URL: " + result );
00368 }
00369 }
00370
else
00371 {
00372
throw new IOException(
"Unable to create an Internet Config instance: " + result );
00373 }
00374
break;
00375
case MRJ_3_1:
00376
try
00377 {
00378 openURL.invoke( null,
new Object[]{url} );
00379 }
00380
catch( InvocationTargetException ite )
00381 {
00382
throw new IOException(
"InvocationTargetException while calling openURL: " + ite.getMessage() );
00383 }
00384
catch( IllegalAccessException iae )
00385 {
00386
throw new IOException(
"IllegalAccessException while calling openURL: " + iae.getMessage() );
00387 }
00388
break;
00389
case WINDOWS_NT:
00390
case WINDOWS_9x:
00391
00392
00393 Process process = Runtime.getRuntime().exec(
new String[]{( String ) browser,
00394
FIRST_WINDOWS_PARAMETER,
00395
SECOND_WINDOWS_PARAMETER,
00396
THIRD_WINDOWS_PARAMETER,
00397
'"' + url +
'"'} );
00398
00399
00400
try
00401 {
00402 process.waitFor();
00403 process.exitValue();
00404 }
00405
catch( InterruptedException ie )
00406 {
00407
throw new IOException(
"InterruptedException while launching browser: " + ie.getMessage() );
00408 }
00409
break;
00410
case OTHER:
00411
00412
00413
00414 process = Runtime.getRuntime().exec(
new String[]{( String ) browser,
00415
NETSCAPE_REMOTE_PARAMETER,
00416
NETSCAPE_OPEN_PARAMETER_START +
00417 url +
00418
NETSCAPE_OPEN_PARAMETER_END} );
00419
try
00420 {
00421
int exitCode = process.waitFor();
00422
if( exitCode != 0 )
00423 {
00424
00425 Runtime.getRuntime().exec(
new String[]{( String ) browser, url} );
00426 }
00427 }
00428
catch( InterruptedException ie )
00429 {
00430
throw new IOException(
"InterruptedException while launching browser: " + ie.getMessage() );
00431 }
00432
break;
00433
default:
00434
00435 Runtime.getRuntime().exec(
new String[]{( String ) browser, url} );
00436
break;
00437 }
00438 }
00439
00440
private native
static int ICLaunchURL(
int instance, byte[] hint, byte[] data,
int len,
00441
int[] selectionStart,
int[] selectionEnd );
00442
00443
00444
00445
00446
00447
private native
static int ICStart(
int[] instance,
int signature );
00448
00449
private native
static int ICStop(
int[] instance );
00450
00451
00452
00453
00454
00455
00456
00457
00458 private static boolean loadClasses()
00459 {
00460
switch (
jvm )
00461 {
00462
case MRJ_2_0:
00463
try
00464 {
00465 Class aeTargetClass = Class.forName(
"com.apple.MacOS.AETarget" );
00466 Class osUtilsClass = Class.forName(
"com.apple.MacOS.OSUtils" );
00467 Class appleEventClass = Class.forName(
"com.apple.MacOS.AppleEvent" );
00468 Class aeClass = Class.forName(
"com.apple.MacOS.ae" );
00469
aeDescClass = Class.forName(
"com.apple.MacOS.AEDesc" );
00470
00471
aeTargetConstructor = aeTargetClass.getDeclaredConstructor(
new Class[]{
int.
class} );
00472
appleEventConstructor = appleEventClass.getDeclaredConstructor(
new Class[]{
int.
class,
int.
class, aeTargetClass,
int.
class,
int.
class} );
00473
aeDescConstructor =
aeDescClass.getDeclaredConstructor(
new Class[]{String.class} );
00474
00475
makeOSType = osUtilsClass.getDeclaredMethod(
"makeOSType",
new Class[]{String.class} );
00476
putParameter = appleEventClass.getDeclaredMethod(
"putParameter",
new Class[]{
int.
class,
aeDescClass} );
00477
sendNoReply = appleEventClass.getDeclaredMethod(
"sendNoReply",
new Class[]{} );
00478
00479 Field keyDirectObjectField = aeClass.getDeclaredField(
"keyDirectObject" );
00480
keyDirectObject = ( Integer ) keyDirectObjectField.get( null );
00481 Field autoGenerateReturnIDField = appleEventClass.getDeclaredField(
"kAutoGenerateReturnID" );
00482
kAutoGenerateReturnID = ( Integer ) autoGenerateReturnIDField.get( null );
00483 Field anyTransactionIDField = appleEventClass.getDeclaredField(
"kAnyTransactionID" );
00484
kAnyTransactionID = ( Integer ) anyTransactionIDField.get( null );
00485 }
00486
catch( ClassNotFoundException cnfe )
00487 {
00488 errorMessage = cnfe.getMessage();
00489
return false;
00490 }
00491
catch( NoSuchMethodException nsme )
00492 {
00493 errorMessage = nsme.getMessage();
00494
return false;
00495 }
00496
catch( NoSuchFieldException nsfe )
00497 {
00498 errorMessage = nsfe.getMessage();
00499
return false;
00500 }
00501
catch( IllegalAccessException iae )
00502 {
00503 errorMessage = iae.getMessage();
00504
return false;
00505 }
00506
break;
00507
case MRJ_2_1:
00508
try
00509 {
00510
mrjFileUtilsClass = Class.forName(
"com.apple.mrj.MRJFileUtils" );
00511
mrjOSTypeClass = Class.forName(
"com.apple.mrj.MRJOSType" );
00512 Field systemFolderField =
mrjFileUtilsClass.getDeclaredField(
"kSystemFolderType" );
00513
kSystemFolderType = systemFolderField.get( null );
00514
findFolder =
mrjFileUtilsClass.getDeclaredMethod(
"findFolder",
new Class[]{mrjOSTypeClass} );
00515
getFileCreator =
mrjFileUtilsClass.getDeclaredMethod(
"getFileCreator",
new Class[]{File.class} );
00516
getFileType =
mrjFileUtilsClass.getDeclaredMethod(
"getFileType",
new Class[]{File.class} );
00517 }
00518
catch( ClassNotFoundException cnfe )
00519 {
00520 errorMessage = cnfe.getMessage();
00521
return false;
00522 }
00523
catch( NoSuchFieldException nsfe )
00524 {
00525 errorMessage = nsfe.getMessage();
00526
return false;
00527 }
00528
catch( NoSuchMethodException nsme )
00529 {
00530 errorMessage = nsme.getMessage();
00531
return false;
00532 }
00533
catch( SecurityException se )
00534 {
00535 errorMessage = se.getMessage();
00536
return false;
00537 }
00538
catch( IllegalAccessException iae )
00539 {
00540 errorMessage = iae.getMessage();
00541
return false;
00542 }
00543
break;
00544
case MRJ_3_0:
00545
try
00546 {
00547 Class linker = Class.forName(
"com.apple.mrj.jdirect.Linker" );
00548 Constructor constructor = linker.getConstructor(
new Class[]{Class.class} );
00549 linkage = constructor.newInstance(
new Object[]{BrowserLauncher.class} );
00550 }
00551
catch( ClassNotFoundException cnfe )
00552 {
00553 errorMessage = cnfe.getMessage();
00554
return false;
00555 }
00556
catch( NoSuchMethodException nsme )
00557 {
00558 errorMessage = nsme.getMessage();
00559
return false;
00560 }
00561
catch( InvocationTargetException ite )
00562 {
00563 errorMessage = ite.getMessage();
00564
return false;
00565 }
00566
catch( InstantiationException ie )
00567 {
00568 errorMessage = ie.getMessage();
00569
return false;
00570 }
00571
catch( IllegalAccessException iae )
00572 {
00573 errorMessage = iae.getMessage();
00574
return false;
00575 }
00576
break;
00577
case MRJ_3_1:
00578
try
00579 {
00580 mrjFileUtilsClass = Class.forName(
"com.apple.mrj.MRJFileUtils" );
00581 openURL = mrjFileUtilsClass.getDeclaredMethod(
"openURL",
new Class[]{String.class} );
00582 }
00583
catch( ClassNotFoundException cnfe )
00584 {
00585 errorMessage = cnfe.getMessage();
00586
return false;
00587 }
00588
catch( NoSuchMethodException nsme )
00589 {
00590 errorMessage = nsme.getMessage();
00591
return false;
00592 }
00593
break;
00594
default:
00595
break;
00596 }
00597
return true;
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 private static Object locateBrowser()
00612 {
00613
if( browser != null )
00614 {
00615
return browser;
00616 }
00617
switch ( jvm )
00618 {
00619
case MRJ_2_0:
00620
try
00621 {
00622 Integer finderCreatorCode = ( Integer ) makeOSType.invoke( null,
new Object[]{FINDER_CREATOR} );
00623 Object aeTarget = aeTargetConstructor.newInstance(
new Object[]{finderCreatorCode} );
00624 Integer gurlType = ( Integer ) makeOSType.invoke( null,
new Object[]{GURL_EVENT} );
00625 Object appleEvent = appleEventConstructor.newInstance(
new Object[]{gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID} );
00626
00627
00628
00629
00630
00631
return appleEvent;
00632 }
00633
catch( IllegalAccessException iae )
00634 {
00635 browser = null;
00636 errorMessage = iae.getMessage();
00637
return browser;
00638 }
00639
catch( InstantiationException ie )
00640 {
00641 browser = null;
00642 errorMessage = ie.getMessage();
00643
return browser;
00644 }
00645
catch( InvocationTargetException ite )
00646 {
00647 browser = null;
00648 errorMessage = ite.getMessage();
00649
return browser;
00650 }
00651
case MRJ_2_1:
00652 File systemFolder;
00653
try
00654 {
00655 systemFolder = ( File ) findFolder.invoke( null,
new Object[]{kSystemFolderType} );
00656 }
00657
catch( IllegalArgumentException iare )
00658 {
00659 browser = null;
00660 errorMessage = iare.getMessage();
00661
return browser;
00662 }
00663
catch( IllegalAccessException iae )
00664 {
00665 browser = null;
00666 errorMessage = iae.getMessage();
00667
return browser;
00668 }
00669
catch( InvocationTargetException ite )
00670 {
00671 browser = null;
00672 errorMessage = ite.getTargetException().getClass() +
": " + ite.getTargetException().getMessage();
00673
return browser;
00674 }
00675 String[] systemFolderFiles = systemFolder.list();
00676
00677
for(
int i = 0; i < systemFolderFiles.length; i++ )
00678 {
00679
try
00680 {
00681 File file =
new File( systemFolder, systemFolderFiles[i] );
00682
if( !file.isFile() )
00683 {
00684
continue;
00685 }
00686
00687
00688
00689
00690
00691 Object fileType = getFileType.invoke( null,
new Object[]{file} );
00692
if( FINDER_TYPE.equals( fileType.toString() ) )
00693 {
00694 Object fileCreator = getFileCreator.invoke( null,
new Object[]{file} );
00695
if( FINDER_CREATOR.equals( fileCreator.toString() ) )
00696 {
00697 browser = file.toString();
00698
00699
return browser;
00700 }
00701 }
00702 }
00703
catch( IllegalArgumentException iare )
00704 {
00705 browser = browser;
00706 errorMessage = iare.getMessage();
00707
return null;
00708 }
00709
catch( IllegalAccessException iae )
00710 {
00711 browser = null;
00712 errorMessage = iae.getMessage();
00713
return browser;
00714 }
00715
catch( InvocationTargetException ite )
00716 {
00717 browser = null;
00718 errorMessage = ite.getTargetException().getClass() +
": " + ite.getTargetException().getMessage();
00719
return browser;
00720 }
00721 }
00722 browser = null;
00723
break;
00724
case MRJ_3_0:
00725
case MRJ_3_1:
00726 browser =
"";
00727
00728
break;
00729
case WINDOWS_NT:
00730 browser =
"cmd.exe";
00731
break;
00732
case WINDOWS_9x:
00733 browser =
"command.com";
00734
break;
00735
case OTHER:
00736
default:
00737 browser =
"netscape";
00738
break;
00739 }
00740
return browser;
00741 }
00742
00743
static
00744 {
00745 loadedWithoutErrors =
true;
00746 String osName = System.getProperty(
"os.name" );
00747
if( osName.startsWith(
"Mac OS" ) )
00748 {
00749 String mrjVersion = System.getProperty(
"mrj.version" );
00750 String majorMRJVersion = mrjVersion.substring( 0, 3 );
00751
try
00752 {
00753
double version = Double.valueOf( majorMRJVersion ).doubleValue();
00754
if( version == 2 )
00755 {
00756 jvm = MRJ_2_0;
00757 }
00758
else if( version >= 2.1 && version < 3 )
00759 {
00760
00761
00762
00763 jvm = MRJ_2_1;
00764 }
00765
else if( version == 3.0 )
00766 {
00767 jvm = MRJ_3_0;
00768 }
00769
else if( version >= 3.1 )
00770 {
00771
00772 jvm = MRJ_3_1;
00773 }
00774
else
00775 {
00776 loadedWithoutErrors =
false;
00777 errorMessage =
"Unsupported MRJ version: " + version;
00778 }
00779 }
00780
catch( NumberFormatException nfe )
00781 {
00782 loadedWithoutErrors =
false;
00783 errorMessage =
"Invalid MRJ version: " + mrjVersion;
00784 }
00785 }
00786
else if( osName.startsWith(
"Windows" ) )
00787 {
00788
if( osName.indexOf(
"9" ) != -1 )
00789 {
00790 jvm = WINDOWS_9x;
00791 }
00792
else
00793 {
00794 jvm = WINDOWS_NT;
00795 }
00796 }
00797
else
00798 {
00799 jvm = OTHER;
00800 }
00801
00802
if( loadedWithoutErrors )
00803 {
00804
00805 loadedWithoutErrors = loadClasses();
00806 }
00807 }
00808 }