Yes, this is platform-specific code, and yes, it may rely on classes on certain platforms that are not part of the standard JDK. What we're trying to do, though, is to take something that's frequently desirable but inherently platform-specific -- opening a default browser -- and allow programmers (you, for example) to do so without worrying about dropping into native code or doing anything else similarly evil.
Anyway, this code is completely in Java and will run on all JDK 1.1-compliant systems without modification or a need for additional libraries. All classes that are required on certain platforms to allow this to run are dynamically loaded at runtime via reflection and, if not found, will not cause this to do anything other than returning an error when opening the browser.
There are certain system requirements for this class, as it's running through Runtime.exec(), which is Java's way of making a native system call. Currently, this requires that a Macintosh have a Finder which supports the GURL event, which is true for Mac OS 8.0 and 8.1 systems that have the Internet Scripting AppleScript dictionary installed in the Scripting Additions folder in the Extensions folder (which is installed by default as far as I know under Mac OS 8.0 and 8.1), and for all Mac OS 8.5 and later systems. On Windows, it only runs under Win32 systems (Windows 95, 98, and NT 4.0, as well as later versions of all). On other systems, this drops back from the inherently platform-sensitive concept of a default browser and simply attempts to launch Netscape via a shell command.
This code is Copyright 1999-2001 by Eric Albert (ejalbert@cs.stanford.edu) and may be redistributed or modified in any form without restrictions as long as the portion of this comment from this paragraph through the end of the comment is not removed. The author requests that he be notified of any application, applet, or other binary that makes use of this code, but that's more out of curiosity than anything and is not required. This software includes no warranty. The author is not repsonsible for any loss of data or functionality or any adverse or unexpected effects of using this software.
Credits:
Steven Spencer, JavaWorld magazine (Java Tip 66)
Thanks also to Ron B. Yeh, Eric Shapiro, Ben Engber, Paul Teitlebaum, Andrea Cantatore, Larry Barowski, Trevor Bedzek, Frank Miedrich, and Ron Rabakukk
Definition at line 54 of file BrowserLauncher.java.
Static Public Member Functions | |
| void | openURL (String url) throws IOException |
Static Package Functions | |
| [static initializer] | |
|
|
An initialization block that determines the operating system and loads the necessary runtime data. |
|
|
Attempts to open the default web browser to the given URL.
Definition at line 472 of file BrowserLauncher.java.
00472 {
00473 if (!loadedWithoutErrors) {
00474 throw new IOException("Exception in finding browser: " + errorMessage);
00475 }
00476 Object browser = locateBrowser();
00477 if (browser == null) {
00478 throw new IOException("Unable to locate browser: " + errorMessage);
00479 }
00480
00481 switch (jvm) {
00482 case MRJ_2_0:
00483 Object aeDesc = null;
00484 try {
00485 aeDesc = aeDescConstructor.newInstance(new Object[] { url });
00486 putParameter.invoke(browser, new Object[] { keyDirectObject, aeDesc });
00487 sendNoReply.invoke(browser, new Object[] { });
00488 } catch (InvocationTargetException ite) {
00489 throw new IOException("InvocationTargetException while creating AEDesc: " + ite.getMessage());
00490 } catch (IllegalAccessException iae) {
00491 throw new IOException("IllegalAccessException while building AppleEvent: " + iae.getMessage());
00492 } catch (InstantiationException ie) {
00493 throw new IOException("InstantiationException while creating AEDesc: " + ie.getMessage());
00494 } finally {
00495 aeDesc = null; // Encourage it to get disposed if it was created
00496 browser = null; // Ditto
00497 }
00498 break;
00499 case MRJ_2_1:
00500 Runtime.getRuntime().exec(new String[] { (String) browser, url } );
00501 break;
00502 case MRJ_3_0:
00503 int[] instance = new int[1];
00504 int result = ICStart(instance, 0);
00505 if (result == 0) {
00506 int[] selectionStart = new int[] { 0 };
00507 byte[] urlBytes = url.getBytes();
00508 int[] selectionEnd = new int[] { urlBytes.length };
00509 result = ICLaunchURL(instance[0], new byte[] { 0 }, urlBytes,
00510 urlBytes.length, selectionStart,
00511 selectionEnd);
00512 if (result == 0) {
00513 // Ignore the return value; the URL was launched successfully
00514 // regardless of what happens here.
00515 ICStop(instance);
00516 } else {
00517 throw new IOException("Unable to launch URL: " + result);
00518 }
00519 } else {
00520 throw new IOException("Unable to create an Internet Config instance: " + result);
00521 }
00522 break;
00523 case MRJ_3_1:
00524 try {
00525 openURL.invoke(null, new Object[] { url });
00526 } catch (InvocationTargetException ite) {
00527 throw new IOException("InvocationTargetException while calling openURL: " + ite.getMessage());
00528 } catch (IllegalAccessException iae) {
00529 throw new IOException("IllegalAccessException while calling openURL: " + iae.getMessage());
00530 }
00531 break;
00532 case WINDOWS_NT:
00533 case WINDOWS_9x:
00534 // Add quotes around the URL to allow ampersands and other special
00535 // characters to work.
00536 Process process = Runtime.getRuntime().exec(new String[] { (String) browser,
00537 FIRST_WINDOWS_PARAMETER,
00538 SECOND_WINDOWS_PARAMETER,
00539 THIRD_WINDOWS_PARAMETER,
00540 '"' + url + '"' });
00541 // This avoids a memory leak on some versions of Java on Windows.
00542 // That's hinted at in <http://developer.java.sun.com/developer/qow/archive/68/>.
00543 try {
00544 process.waitFor();
00545 process.exitValue();
00546 } catch (InterruptedException ie) {
00547 throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
00548 }
00549 break;
00550 case OTHER:
00551 // Assume that we're on Unix and that Netscape is installed
00552
00553 // First, attempt to open the URL in a currently running session of Netscape
00554 process = Runtime.getRuntime().exec(new String[] { (String) browser,
00555 NETSCAPE_REMOTE_PARAMETER,
00556 NETSCAPE_OPEN_PARAMETER_START +
00557 url +
00558 NETSCAPE_OPEN_PARAMETER_END });
00559 try {
00560 int exitCode = process.waitFor();
00561 if (exitCode != 0) { // if Netscape was not open
00562 Runtime.getRuntime().exec(new String[] { (String) browser, url });
00563 }
00564 } catch (InterruptedException ie) {
00565 throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
00566 }
00567 break;
00568 default:
00569 // This should never occur, but if it does, we'll try the simplest thing possible
00570 Runtime.getRuntime().exec(new String[] { (String) browser, url });
00571 break;
00572 }
00573 }
|