KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > Ostermiller > util > Browser


1 /*
2  * Control a web browser from your java application.
3  * Copyright (C) 2001-2002 Stephen Ostermiller
4  * http://ostermiller.org/contact.pl?regarding=Java+Utilities
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * See COPYING.TXT for details.
17  */

18 package com.Ostermiller.util;
19
20 import java.io.*;
21 import java.text.MessageFormat JavaDoc;
22 import java.net.URL JavaDoc;
23 import java.net.URLDecoder JavaDoc;
24 import java.net.URLClassLoader JavaDoc;
25 import javax.swing.*;
26 import java.awt.*;
27 import java.awt.event.*;
28 import java.util.Properties JavaDoc;
29 import java.util.Vector JavaDoc;
30 import java.util.ResourceBundle JavaDoc;
31 import java.util.Locale JavaDoc;
32 import java.io.StringReader JavaDoc;
33 import java.lang.reflect.*;
34
35 /**
36  * Allows URLs to be opened in the system browser on Windows and Unix.
37  * More information about this class is available from <a target="_top" HREF=
38  * "http://ostermiller.org/utils/Browser.html">ostermiller.org</a>.
39  *
40  * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
41  * @since ostermillerutils 1.00.00
42  */

43 public class Browser {
44
45     /**
46      * The dialog that allows user configuration of the options for this class.
47      *
48      * @since ostermillerutils 1.00.00
49      */

50     protected static BrowserDialog dialog;
51
52     /**
53      * Locale specific strings displayed to the user.
54      *
55      * @since ostermillerutils 1.00.00
56      */

57     protected static ResourceBundle JavaDoc labels = ResourceBundle.getBundle("com.Ostermiller.util.Browser", Locale.getDefault());
58
59     /**
60      * Set the locale used for getting localized
61      * strings.
62      *
63      * @param locale Locale used to for i18n.
64      *
65      * @since ostermillerutils 1.00.00
66      */

67     public static void setLocale(Locale JavaDoc locale){
68         labels = ResourceBundle.getBundle("com.Ostermiller.util.Browser", locale);
69     }
70
71     /**
72      * A list of commands to try in order to display the url.
73      * The url is put into the command using MessageFormat, so
74      * the URL will be specified as {0} in the command.
75      * Some examples of commands to try might be:<br>
76      * <code>rundll32 url.dll,FileProtocolHandler {0}</code></br>
77      * <code>netscape {0}</code><br>
78      * These commands are passed in order to exec until something works
79      * when displayURL is used.
80      *
81      * @since ostermillerutils 1.00.00
82      */

83     public static String JavaDoc[] exec = null;
84
85     /**
86      * Determine appropriate commands to start a browser on the current
87      * operating system. On windows: <br>
88      * <code>rundll32 url.dll,FileProtocolHandler {0}</code></br>
89      * On other operating systems, the "which" command is used to
90      * test if Mozilla, netscape, and lynx(xterm) are available (in that
91      * order).
92      *
93      * @since ostermillerutils 1.00.00
94      */

95     public static void init(){
96         exec = defaultCommands();
97     }
98
99     /**
100      * Retrieve the default commands to open a browser for this system.
101      *
102      * @since ostermillerutils 1.00.00
103      */

104     public static String JavaDoc[] defaultCommands(){
105         String JavaDoc[] exec = null;
106         if ( System.getProperty("os.name").startsWith("Windows")){
107             exec = new String JavaDoc[]{
108                 "rundll32 url.dll,FileProtocolHandler {0}",
109             };
110         } else if (System.getProperty("os.name").startsWith("Mac")){
111             Vector JavaDoc<String JavaDoc> browsers = new Vector JavaDoc<String JavaDoc>();
112             try {
113                 Process JavaDoc p = Runtime.getRuntime().exec("which open");
114                 if (p.waitFor() == 0){
115                     browsers.add("open {0}");
116                 }
117             } catch (IOException e){
118             } catch (InterruptedException JavaDoc e){
119             }
120             if (browsers.size() == 0){
121                 exec = null;
122             } else {
123                 exec = (String JavaDoc[])browsers.toArray(new String JavaDoc[0]);
124             }
125         } else {
126             Vector JavaDoc<String JavaDoc> browsers = new Vector JavaDoc<String JavaDoc>();
127             try {
128                 Process JavaDoc p = Runtime.getRuntime().exec("which firebird");
129                 if (p.waitFor() == 0){
130                     browsers.add("firebird -remote openURL({0})");
131                     browsers.add("firebird {0}");
132                 }
133             } catch (IOException e){
134             } catch (InterruptedException JavaDoc e){
135             }try {
136                 Process JavaDoc p = Runtime.getRuntime().exec("which mozilla");
137                 if (p.waitFor() == 0){
138                     browsers.add("mozilla -remote openURL({0})");
139                     browsers.add("mozilla {0}");
140                 }
141             } catch (IOException e){
142             } catch (InterruptedException JavaDoc e){
143             }
144             try {
145                 Process JavaDoc p = Runtime.getRuntime().exec("which opera");
146                 if (p.waitFor() == 0){
147                     browsers.add("opera -remote openURL({0})");
148                     browsers.add("opera {0}");
149                 }
150             } catch (IOException e){
151             } catch (InterruptedException JavaDoc e){
152             }
153             try {
154                 Process JavaDoc p = Runtime.getRuntime().exec("which galeon");
155                 if (p.waitFor() == 0){
156                     browsers.add("galeon {0}");
157                 }
158             } catch (IOException e){
159             } catch (InterruptedException JavaDoc e){
160             }
161             try {
162                 Process JavaDoc p = Runtime.getRuntime().exec("which konqueror");
163                 if (p.waitFor() == 0){
164                     browsers.add("konqueror {0}");
165                 }
166             } catch (IOException e){
167             } catch (InterruptedException JavaDoc e){
168             }
169             try {
170                 Process JavaDoc p = Runtime.getRuntime().exec("which netscape");
171                 if (p.waitFor() == 0){
172                     browsers.add("netscape -remote openURL({0})");
173                     browsers.add("netscape {0}");
174                 }
175             } catch (IOException e){
176             } catch (InterruptedException JavaDoc e){
177             }
178             try {
179                 Process JavaDoc p = Runtime.getRuntime().exec("which xterm");
180                 if (p.waitFor() == 0){
181                     p = Runtime.getRuntime().exec("which lynx");
182                     if (p.waitFor() == 0){
183                         browsers.add("xterm -e lynx {0}");
184                     }
185                 }
186             } catch (IOException e){
187             } catch (InterruptedException JavaDoc e){
188             }
189             if (browsers.size() == 0){
190                 exec = null;
191             } else {
192                 exec = (String JavaDoc[])browsers.toArray(new String JavaDoc[0]);
193             }
194         }
195         return exec;
196     }
197
198     /**
199      * Save the options used to the given properties file.
200      * Property names used will all start with com.Ostermiller.util.Browser
201      * Properties are saved in such a way that a call to load(props); will
202      * restore the state of this class.
203      * If the default commands to open a browser are being used then
204      * they are not saved in the properties file, assuming that the user
205      * will want to use the defaults next time even if the defaults change.
206      *
207      * @param props properties file to which configuration is saved.
208      *
209      * @since ostermillerutils 1.00.00
210      */

211     public static void save(Properties JavaDoc props){
212         boolean saveBrowser = false;
213         if (Browser.exec != null && Browser.exec.length > 0){
214             String JavaDoc[] exec = Browser.defaultCommands();
215             if (exec != null && exec.length == Browser.exec.length){
216                 for (int i=0; i<exec.length; i++){
217                     if (!exec[i].equals(Browser.exec[i])){
218                         saveBrowser = true;
219                     }
220                 }
221             } else {
222                 saveBrowser = true;
223             }
224         }
225         if (saveBrowser){
226             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
227             for (int i=0; Browser.exec != null && i < Browser.exec.length; i++){
228                 sb.append(Browser.exec[i]).append('\n');
229             }
230             props.put("com.Ostermiller.util.Browser.open", sb.toString());
231         } else {
232             props.remove("com.Ostermiller.util.Browser.open");
233         }
234     }
235
236     /**
237      * Load the options for this class from the given properties file.
238      * This method is designed to work with the save(props) method. All
239      * properties used will start with com.Ostermiller.util.Browser. If
240      * no configuration is found, the default configuration will be used.
241      * If this method is used, a call to Browser.init(); is not needed.
242      *
243      * @param props properties file from which configuration is loaded.
244      *
245      * @since ostermillerutils 1.00.00
246      */

247     public static void load(Properties JavaDoc props){
248         if (props.containsKey("com.Ostermiller.util.Browser.open")){
249             java.util.StringTokenizer JavaDoc tok = new java.util.StringTokenizer JavaDoc(props.getProperty("com.Ostermiller.util.Browser.open"), "\r\n", false);
250             int count = tok.countTokens();
251             String JavaDoc[] exec = new String JavaDoc[count];
252             for (int i=0; i < count; i++){
253                 exec[i] = tok.nextToken();
254             }
255             Browser.exec = exec;
256         } else {
257             Browser.init();
258         }
259     }
260
261     /**
262      * Display a URL in the system browser.
263      *
264      * Browser.init() should be called before calling this function or
265      * Browser.exec should be set explicitly.
266      *
267      * For security reasons, the URL will may not be passed directly to the
268      * browser as it is passed to this method. The URL may be made safe for
269      * the exec command by URLEncoding the URL before passing it.
270      *
271      * @param url the url to display
272      * @throws IOException if the url is not valid or the browser fails to star
273      *
274      * @since ostermillerutils 1.00.00
275      */

276     public static void displayURL(String JavaDoc url) throws IOException {
277         if (exec == null || exec.length == 0){
278             if (System.getProperty("os.name").startsWith("Mac")){
279                 boolean success = false;
280             try {
281                 Class JavaDoc nSWorkspace;
282                     if (new File("/System/Library/Java/com/apple/cocoa/application/NSWorkspace.class").exists()){
283                          // Mac OS X has NSWorkspace, but it is not in the classpath, add it.
284
ClassLoader JavaDoc classLoader = new URLClassLoader JavaDoc(new URL JavaDoc[]{new File("/System/Library/Java").toURL()});
285                          nSWorkspace = Class.forName("com.apple.cocoa.application.NSWorkspace", true, classLoader);
286                     } else {
287                          nSWorkspace = Class.forName("com.apple.cocoa.application.NSWorkspace");
288                     }
289                     Method sharedWorkspace = nSWorkspace.getMethod("sharedWorkspace", new Class JavaDoc[] {});
290                     Object JavaDoc workspace = sharedWorkspace.invoke(null, new Object JavaDoc[] {});
291                     Method openURL = nSWorkspace.getMethod("openURL", new Class JavaDoc[] {Class.forName("java.net.URL")});
292                     success = ((Boolean JavaDoc)openURL.invoke(workspace, new Object JavaDoc[] {new java.net.URL JavaDoc(url)})).booleanValue();
293                 //success = com.apple.cocoa.application.NSWorkspace.sharedWorkspace().openURL(new java.net.URL(url));
294
} catch (Exception JavaDoc x) {}
295                 if (!success){
296                     try {
297                          Class JavaDoc mrjFileUtils = Class.forName("com.apple.mrj.MRJFileUtils");
298                          Method openURL = mrjFileUtils.getMethod("openURL", new Class JavaDoc[] {Class.forName("java.lang.String")});
299                          openURL.invoke(null, new Object JavaDoc[] {url});
300                          //com.apple.mrj.MRJFileUtils.openURL(url);
301
} catch (Exception JavaDoc x){
302                          System.err.println(x.getMessage());
303                          throw new IOException(labels.getString("failed"));
304                     }
305                 }
306             } else {
307                 throw new IOException(labels.getString("nocommand"));
308             }
309         } else {
310             // for security, see if the url is valid.
311
// this is primarily to catch an attack in which the url
312
// starts with a - to fool the command line flags, bu
313
// it could catch other stuff as well, and will throw a
314
// MalformedURLException which will give the caller of this
315
// function useful information.
316
new URL JavaDoc(url);
317             // escape any weird characters in the url. This is primarily
318
// to prevent an attacker from putting in spaces
319
// that might fool exec into allowing
320
// the attacker to execute arbitrary code.
321
StringBuffer JavaDoc sb = new StringBuffer JavaDoc(url.length());
322             for (int i=0; i<url.length(); i++){
323                 char c = url.charAt(i);
324                 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
325                         || c == '.' || c == ':' || c == '&' || c == '@' || c == '/' || c == '?'
326                         || c == '%' || c =='+' || c == '=' || c == '#' || c == '-' || c == '\\'){
327                     //characters that are necessary for URLs and should be safe
328
//to pass to exec. Exec uses a default string tokenizer with
329
//the default arguments (whitespace) to separate command line
330
//arguments, so there should be no problem with anything bu
331
//whitespace.
332
sb.append(c);
333                 } else {
334                     c = (char)(c & 0xFF); // get the lowest 8 bits (URLEncoding)
335
if (c < 0x10){
336                         sb.append("%0" + Integer.toHexString(c));
337                     } else {
338                         sb.append("%" + Integer.toHexString(c));
339                     }
340                 }
341             }
342             String JavaDoc[] messageArray = new String JavaDoc[1];
343             messageArray[0] = sb.toString();
344             String JavaDoc command = null;
345             boolean found = false;
346             // try each of the exec commands until something works
347
try {
348                 for (int i=0; i<exec.length && !found; i++){
349                     try {
350                         // stick the url into the command
351
command = MessageFormat.format(exec[i], (Object JavaDoc[])messageArray);
352                         // parse the command line.
353
Vector JavaDoc<String JavaDoc> argsVector = new Vector JavaDoc<String JavaDoc>();
354                         BrowserCommandLexer lex = new BrowserCommandLexer(new StringReader JavaDoc(command));
355                         String JavaDoc t;
356                         while ((t = lex.getNextToken()) != null) {
357                             argsVector.add(t);
358                         }
359                         String JavaDoc[] args = new String JavaDoc[argsVector.size()];
360                         args = (String JavaDoc[])argsVector.toArray(args);
361                         // the windows url protocol handler doesn't work well with file URLs.
362
// Correct those problems here before continuing
363
// Java File.toURL() gives only one / following file: bu
364
// we need two.
365
// If there are escaped characters in the url, we will have
366
// to create an Internet shortcut and open that, as the command
367
// line version of the rundll doesn't like them.
368
boolean useShortCut = false;
369                         if (args[0].equals("rundll32") && args[1].equals("url.dll,FileProtocolHandler")){
370                             if (args[2].startsWith("file:/")){
371                                 if (args[2].charAt(6) != '/'){
372                                     args[2] = "file://" + args[2].substring(6);
373                                 }
374                                 if (args[2].charAt(7) != '/'){
375                                     args[2] = "file:///" + args[2].substring(7);
376                                 }
377                                 useShortCut = true;
378                             } else if (args[2].toLowerCase().endsWith("html") || args[2].toLowerCase().endsWith("htm")){
379                                 useShortCut = true;
380                             }
381                         }
382                         if (useShortCut){
383                             File shortcut = File.createTempFile("OpenInBrowser", ".url");
384                             shortcut = shortcut.getCanonicalFile();
385                             shortcut.deleteOnExit();
386                             PrintWriter out = new PrintWriter(new FileWriter(shortcut));
387                             out.println("[InternetShortcut]");
388                             out.println("URL=" + args[2]);
389                             out.close();
390                             args[2] = shortcut.getCanonicalPath();
391                         }
392                         // start the browser
393
Process JavaDoc p = Runtime.getRuntime().exec(args);
394
395                         // give the browser a bit of time to fail.
396
// I have found that sometimes sleep doesn't work
397
// the first time, so do it twice. My tests
398
// seem to show that 1000 milliseconds is enough
399
// time for the browsers I'm using.
400
for (int j=0; j<2; j++){
401                              try{
402                                     Thread.currentThread().sleep(1000);
403                              } catch (InterruptedException JavaDoc inte){
404                              }
405                         }
406                         if (p.exitValue() == 0){
407                              // this is a weird case. The browser exited after
408
// a couple seconds saying that it successfully
409
// displayed the url. Either the browser is lying
410
// or the user closed it *really* quickly. Oh well.
411
found = true;
412                         }
413                     } catch (IOException x){
414                         // the command was not a valid command.
415
System.err.println(labels.getString("warning") + " " + x.getMessage());
416                     }
417                 }
418                 if (!found){
419                     // we never found a command that didn't terminate with an error.
420
throw new IOException(labels.getString("failed"));
421                 }
422             } catch (IllegalThreadStateException JavaDoc e){
423                 // the browser is still running. This is a good sign.
424
// lets just say that it is displaying the url right now!
425
}
426         }
427     }
428
429     /**
430      * Display the URLs, each in their own window, in the system browser.
431      *
432      * Browser.init() should be called before calling this function or
433      * Browser.exec should be set explicitly.
434      *
435      * If more than one URL is given an HTML page containing JavaScript will
436      * be written to the local drive, that page will be opened, and it will
437      * open the rest of the URLs.
438      *
439      * @param urls the list of urls to display
440      * @throws IOException if the url is not valid or the browser fails to star
441      *
442      * @since ostermillerutils 1.00.00
443      */

444     public static void displayURLs(String JavaDoc[] urls) throws IOException {
445         if (urls == null || urls.length == 0){
446             return;
447         }
448         if (urls.length == 1){
449             displayURL(urls[0]);
450             return;
451         }
452         File shortcut = File.createTempFile("DisplayURLs", ".html");
453         shortcut = shortcut.getCanonicalFile();
454         shortcut.deleteOnExit();
455         PrintWriter out = new PrintWriter(new FileWriter(shortcut));
456         out.println("<html>");
457         out.println("<head>");
458         out.println("<title>" + labels.getString("html.openurls") + "</title>");
459         out.println("<script language=\"javascript\" type=\"text/javascript\">");
460         out.println("function displayURLs(){");
461         for (int i=1; i<urls.length; i++){
462             out.println("window.open(\"" + urls[i] + "\", \"_blank\", \"toolbar=yes,location=yes,directories=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes\");");
463         }
464         out.println("location.href=\"" + urls[0] + "\";");
465         out.println("}");
466         out.println("</script>");
467         out.println("</head>");
468         out.println("<body onload=\"javascript:displayURLs()\">");
469         out.println("<noscript>");
470         for (int i=0; i<urls.length; i++){
471             out.println("<a target=\"_blank\" HREF=\"" + urls[i] + "\">" + urls[i] + "</a><br>");
472         }
473         out.println("</noscript>");
474         out.println("</body>");
475         out.println("</html>");
476         out.close();
477         displayURL(shortcut.toURL().toString());
478     }
479
480     /**
481      * Display the URL in a new window.
482      *
483      * Uses javascript to check history.length to determine if the browser opened a
484      * new window already. If it did, the url is shown in that window, if not, it is
485      * shown in new window.
486      *
487      * Some browsers do not allow the length of history to be viewed by a web page. In that
488      * case, the url will be displayed in the current window.
489      *
490      * Browser.init() should be called before calling this function or
491      * Browser.exec should be set explicitly.
492      *
493      * @param url the url to display in a new window.
494      * @throws IOException if the url is not valid or the browser fails to star
495      *
496      * @since ostermillerutils 1.00.00
497      */

498     public static void displayURLinNew(String JavaDoc url) throws IOException {
499         displayURLsinNew (new String JavaDoc[] {url});
500     }
501
502     /**
503      * Display the URLs, each in their own window, in the system browser and the first in
504      * the named window.
505      *
506      * The first URL will only be opened in the named window if the browser did no
507      * open it in a new window to begin with.
508      *
509      * Browser.init() should be called before calling this function or
510      * Browser.exec should be set explicitly.
511      *
512      * An html page containing javascript will
513      * be written to the local drive, that page will be opened, and it will
514      * open all the urls.
515      *
516      * @param urls the list of urls to display
517      * @throws IOException if the url is not valid or the browser fails to star
518      *
519      * @since ostermillerutils 1.00.00
520      */

521     public static void displayURLsinNew(String JavaDoc[] urls) throws IOException {
522         if (urls == null || urls.length == 0){
523             return;
524         }
525         File shortcut = File.createTempFile("DisplayURLs", ".html");
526         shortcut.deleteOnExit();
527         shortcut = shortcut.getCanonicalFile();
528         PrintWriter out = new PrintWriter(new FileWriter(shortcut));
529         out.println("<html>");
530         out.println("<head>");
531         out.println("<title>" + labels.getString("html.openurls") + "</title>");
532         out.println("<script language=\"javascript\" type=\"text/javascript\">");
533         out.println("function displayURLs(){");
534         out.println("var hlength = 0;");
535         out.println("try {");
536         out.println("hlength = history.length;");
537         out.println("} catch (e) {}");
538         out.println("if (hlength>0) {");
539         out.println("window.open(\"" + urls[0] + "\", \"_blank\", \"toolbar=yes,location=yes,directories=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes\");");
540         out.println("}");
541         for (int i=1; i<urls.length; i++){
542             out.println("window.open(\"" + urls[i] + "\", \"_blank\", \"toolbar=yes,location=yes,directories=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes\");");
543         }
544         out.println("if (hlength==0) {");
545         out.println("location.href=\"" + urls[0] + "\";");
546         out.println("} else {");
547         out.println("history.back()");
548         out.println("}");
549         out.println("}");
550         out.println("</script>");
551         out.println("</head>");
552         out.println("<body onload=\"javascript:displayURLs()\">");
553         out.println("<noscript>");
554         for (int i=0; i<urls.length; i++){
555             out.println("<a target=\"_blank\" HREF=\"" + urls[i] + "\">" + urls[i] + "</a><br>");
556         }
557         out.println("</noscript>");
558         out.println("</body>");
559         out.println("</html>");
560         out.close();
561         displayURL(shortcut.toURL().toString());
562     }
563
564     /**
565      * Display the URL in the named window.
566      *
567      * If the browser opens a new window by default, this will likely cause a duplicate window
568      * to be opened.
569      *
570      * Browser.init() should be called before calling this function or
571      * Browser.exec should be set explicitly.
572      *
573      * @param url the url to display
574      * @param namedWindow the name of the desired window.
575      * @throws IOException if the url is not valid or the browser fails to star
576      *
577      * @since ostermillerutils 1.00.00
578      */

579     public static void displayURL(String JavaDoc url, String JavaDoc namedWindow) throws IOException {
580         displayURLs (new String JavaDoc[] {url}, new String JavaDoc[] {namedWindow});
581     }
582
583     /**
584      * Display the URLs in the named windows.
585      *
586      * If the browser opens a new window by default, this will likely cause a duplicate window
587      * to be opened. This method relies on the browser to support javascript.
588      *
589      * Browser.init() should be called before calling this function or
590      * Browser.exec should be set explicitly.
591      *
592      * Extra names for windows will be ignored, and if there are too few names, the remaining
593      * windows will be named "_blank".
594      *
595      * @param urls the list of urls to display
596      * @param namedWindows the list of names for the windows.
597      * @throws IOException if the url is not valid or the browser fails to star
598      *
599      * @since ostermillerutils 1.00.00
600      */

601     public static void displayURLs(String JavaDoc[] urls, String JavaDoc[] namedWindows) throws IOException {
602         if (urls == null || urls.length == 0){
603             return;
604         }
605         File shortcut = File.createTempFile("DisplayURLs", ".html");
606         shortcut.deleteOnExit();
607         shortcut = shortcut.getCanonicalFile();
608         PrintWriter out = new PrintWriter(new FileWriter(shortcut));
609         out.println("<html>");
610         out.println("<head>");
611         out.println("<title>" + labels.getString("html.openurls") + "</title>");
612         out.println("<base target=\"" + ((namedWindows==null||namedWindows.length==0||namedWindows[0]==null)?"_blank":namedWindows[0]) + "\">");
613         out.println("<script language=\"javascript\" type=\"text/javascript\">");
614         for (int i=1; i<urls.length; i++){
615             out.println("window.open(\"" + urls[i] + "\", \"" + ((namedWindows==null||namedWindows.length<=i||namedWindows[i]==null)?"_blank":namedWindows[i]) + "\", \"toolbar=yes,location=yes,directories=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes\");");
616         }
617         out.println("location.href=\"" + urls[0] + "\";");
618         out.println("</script>");
619         out.println("</head>");
620         out.println("<body onload=\"javascript:displayURLs()\">");
621         out.println("<noscript>");
622         for (int i=0; i<urls.length; i++){
623             out.println("<a target=\"" + ((namedWindows==null||namedWindows.length==0||namedWindows[0]==null)?"_blank":namedWindows[0]) + "\" HREF=\"" + urls[i] + "\">" + urls[i] + "</a><br>");
624         }
625         out.println("</noscript>");
626         out.println("</body>");
627         out.println("</html>");
628         out.close();
629         displayURL(shortcut.toURL().toString());
630     }
631
632     /**
633      * Display the URLs the first in the given named window.
634      *
635      * If the browser opens a new window by default, this will likely cause a duplicate window
636      * to be opened. This method relies on the browser to support javascript.
637      *
638      * Browser.init() should be called before calling this function or
639      * Browser.exec should be set explicitly.
640      *
641      * @param urls the list of urls to display
642      * @param namedWindow the name of the first window to use.
643      * @throws IOException if the url is not valid or the browser fails to star
644      *
645      * @since ostermillerutils 1.00.00
646      */

647     public static void displayURLs(String JavaDoc[] urls, String JavaDoc namedWindow) throws IOException {
648         displayURLs(urls, new String JavaDoc[] {namedWindow});
649     }
650
651     /**
652      * Open the url(s) specified on the command line in your browser.
653      *
654      * @param args Command line arguments (URLs)
655      */

656     public static void main(String JavaDoc[] args){
657         try {
658             Browser.init();
659             if (Browser.dialogConfiguration(null)){
660                 if (args.length == 0){
661                     Browser.displayURLs(new String JavaDoc[]{
662                         "http://www.google.com/",
663                         "http://dmoz.org/",
664                         "http://ostermiller.org",
665                     }, "fun");
666                 } else if (args.length == 1){
667                     Browser.displayURL(args[0], "fun");
668                 } else {
669                     Browser.displayURLs(args, "fun");
670                 }
671             }
672             try {
673                 Thread.sleep(10000);
674             } catch (InterruptedException JavaDoc x){
675             }
676         } catch (IOException e){
677             System.err.println(e.getMessage());
678         }
679         System.exit(0);
680     }
681
682     /**
683      * Show a dialog that allows the user to configure the
684      * command lines used for starting a browser on their system.
685      *
686      * @param owner The frame that owns the dialog.
687      *
688      * @since ostermillerutils 1.00.00
689      */

690     public static boolean dialogConfiguration(Frame owner){
691         dialogConfiguration(owner, null);
692         return Browser.dialog.changed();
693     }
694
695     /**
696      * Show a dialog that allows the user to configure the
697      * command lines used for starting a browser on their system.
698      * String used in the dialog are taken from the given
699      * properties. This dialog can be customized or displayed in
700      * multiple languages.
701      * <P>
702      * Properties that are used:
703      * com.Ostermiller.util.BrowserDialog.title<br>
704      * com.Ostermiller.util.BrowserDialog.description<br>
705      * com.Ostermiller.util.BrowserDialog.label<br>
706      * com.Ostermiller.util.BrowserDialog.defaults<br>
707      * com.Ostermiller.util.BrowserDialog.browse<br>
708      * com.Ostermiller.util.BrowserDialog.ok<br>
709      * com.Ostermiller.util.BrowserDialog.cancel<br>
710      *
711      * @param owner The frame that owns this dialog.
712      * @param props contains the strings used in the dialog.
713      * @deprecated Use the com.Ostermiller.util.Browser resource bundle to set strings for the given locale.
714      *
715      * @since ostermillerutils 1.00.00
716      */

717     public static boolean dialogConfiguration(Frame owner, Properties JavaDoc props){
718         if (Browser.dialog == null){
719             Browser.dialog = new BrowserDialog(owner);
720         }
721         if (props != null){
722             Browser.dialog.setProps(props);
723         }
724         Browser.dialog.show();
725         return Browser.dialog.changed();
726     }
727
728     /**
729      * Where the command lines are typed.
730      *
731      * @since ostermillerutils 1.00.00
732      */

733     private static JTextArea description;
734
735     /**
736      * Where the command lines are typed.
737      *
738      * @since ostermillerutils 1.00.00
739      */

740     private static JTextArea commandLinesArea;
741
742     /**
743      * The reset button.
744      *
745      * @since ostermillerutils 1.00.00
746      */

747     private static JButton resetButton;
748
749     /**
750      * The browse button.
751      *
752      * @since ostermillerutils 1.00.00
753      */

754     private static JButton browseButton;
755
756     /**
757      * The label for the field in which the name is typed.
758      *
759      * @since ostermillerutils 1.00.00
760      */

761     private static JLabel commandLinesLabel;
762
763     /**
764      * File dialog for choosing a browser
765      *
766      * @since ostermillerutils 1.00.00
767      */

768     private static JFileChooser fileChooser;
769
770     /**
771      * A panel used in the options dialog. Null until getDialogPanel() is called.
772      */

773     private static JPanel dialogPanel = null;
774     private static Window dialogParent = null;
775
776     /**
777      * If you wish to add to your own dialog box rather than have a separate
778      * one just for the browser, use this method to get a JPanel that can
779      * be added to your own dialog.
780      *
781      * mydialog.add(Browser.getDialogPanel(mydialog));
782      * Browser.initPanel();
783      * mydialog.show();
784      * if (ok_pressed){
785      * &nbsp;&nbsp;Browser.userOKedPanelChanges();
786      * }
787      *
788      * @param parent window into which panel with eventually be placed.
789      * @since ostermillerutils 1.02.22
790      */

791     public static JPanel getDialogPanel(Window parent){
792         dialogParent = parent;
793         if (dialogPanel == null){
794             commandLinesArea = new JTextArea("", 8, 40);
795             JScrollPane scrollpane = new JScrollPane(commandLinesArea);
796             resetButton = new JButton(labels.getString("dialog.reset"));
797             browseButton = new JButton(labels.getString("dialog.browse"));
798             commandLinesLabel = new JLabel(labels.getString("dialog.commandLines"));
799             description = new JTextArea(labels.getString("dialog.description"));
800             description.setEditable(false);
801             description.setOpaque( false );
802
803             ActionListener actionListener = new ActionListener() {
804                 public void actionPerformed(ActionEvent e){
805                     Object JavaDoc source = e.getSource();
806                     if (source == resetButton){
807                         setCommands(Browser.defaultCommands());
808                     } else if (source == browseButton){
809                         if (fileChooser == null){
810                             fileChooser = new JFileChooser();
811                         }
812                         if (fileChooser.showOpenDialog(dialogParent) == JFileChooser.APPROVE_OPTION){
813                             String JavaDoc app = fileChooser.getSelectedFile().getPath();
814                             StringBuffer JavaDoc sb = new StringBuffer JavaDoc(2 * app.length());
815                             for (int i=0; i<app.length(); i++){
816                                 char c = app.charAt(i);
817                                 // escape these two characters so that we can later parse the stuff
818
if (c == '\"' || c == '\\') {
819                                     sb.append('\\');
820                                 }
821                                 sb.append(c);
822                             }
823                             app = sb.toString();
824                             if (app.indexOf(" ") != -1){
825                                 app = '"' + app + '"';
826                             }
827                             String JavaDoc commands = commandLinesArea.getText();
828                             if (commands.length() != 0 && !commands.endsWith("\n") && !commands.endsWith("\r")){
829                                 commands += "\n";
830                             }
831                             commandLinesArea.setText(commands + app + " {0}");
832                         }
833                     }
834                 }
835             };
836
837             GridBagLayout gridbag = new GridBagLayout();
838             GridBagConstraints c = new GridBagConstraints();
839             c.insets.top = 5;
840             c.insets.bottom = 5;
841             dialogPanel = new JPanel(gridbag);
842             dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 5, 20));
843             JLabel label;
844
845
846             c.gridwidth = GridBagConstraints.REMAINDER;
847             c.anchor = GridBagConstraints.WEST;
848             gridbag.setConstraints(description, c);
849             dialogPanel.add(description);
850
851             c.gridy = 1;
852             c.gridwidth = GridBagConstraints.RELATIVE;
853             gridbag.setConstraints(commandLinesLabel, c);
854             dialogPanel.add(commandLinesLabel);
855             JPanel buttonPanel = new JPanel();
856             c.anchor = GridBagConstraints.EAST;
857             browseButton.addActionListener(actionListener);
858             buttonPanel.add(browseButton);
859             resetButton.addActionListener(actionListener);
860             buttonPanel.add(resetButton);
861             gridbag.setConstraints(buttonPanel, c);
862             dialogPanel.add(buttonPanel);
863
864             c.gridy = 2;
865             c.gridwidth = GridBagConstraints.REMAINDER;
866             c.anchor = GridBagConstraints.WEST;
867             gridbag.setConstraints(scrollpane, c);
868             dialogPanel.add(scrollpane);
869         }
870         return dialogPanel;
871     }
872
873
874     /**
875      * A modal dialog that presents configuration option for this class.
876      *
877      * @since ostermillerutils 1.00.00
878      */

879     private static class BrowserDialog extends JDialog {
880
881         /**
882          * The OK button.
883          *
884          * @since ostermillerutils 1.00.00
885          */

886         private JButton okButton;
887
888         /**
889          * The cancel button.
890          *
891          * @since ostermillerutils 1.00.00
892          */

893         private JButton cancelButton;
894
895         /**
896          * The label for the field in which the name is typed.
897          *
898          * @since ostermillerutils 1.00.00
899          */

900         private JLabel commandLinesLabel;
901
902         /**
903          * update this variable when the user makes an action
904          *
905          * @since ostermillerutils 1.00.00
906          */

907         private boolean pressed_OK = false;
908
909
910         /**
911          * Properties that are used:
912          * com.Ostermiller.util.BrowserDialog.title<br>
913          * com.Ostermiller.util.BrowserDialog.description<br>
914          * com.Ostermiller.util.BrowserDialog.label<br>
915          * com.Ostermiller.util.BrowserDialog.defaults<br>
916          * com.Ostermiller.util.BrowserDialog.browse<br>
917          * com.Ostermiller.util.BrowserDialog.ok<br>
918          * com.Ostermiller.util.BrowserDialog.cancel<br>
919          *
920          * @deprecated Use the com.Ostermiller.util.Browser resource bundle to set strings for the given locale.
921          *
922          * @since ostermillerutils 1.00.00
923          */

924         private void setProps(Properties JavaDoc props){
925             if (props.containsKey("com.Ostermiller.util.BrowserDialog.title")){
926                 setTitle(props.getProperty("com.Ostermiller.util.BrowserDialog.title"));
927             }
928             if (props.containsKey("com.Ostermiller.util.BrowserDialog.description")){
929                 description.setText(props.getProperty("com.Ostermiller.util.BrowserDialog.description"));
930             }
931             if (props.containsKey("com.Ostermiller.util.BrowserDialog.label")){
932                 commandLinesLabel.setText(props.getProperty("com.Ostermiller.util.BrowserDialog.label"));
933             }
934             if (props.containsKey("com.Ostermiller.util.BrowserDialog.defaults")){
935                 resetButton.setText(props.getProperty("com.Ostermiller.util.BrowserDialog.defaults"));
936             }
937             if (props.containsKey("com.Ostermiller.util.BrowserDialog.browse")){
938                 browseButton.setText(props.getProperty("com.Ostermiller.util.BrowserDialog.browse"));
939             }
940             if (props.containsKey("com.Ostermiller.util.BrowserDialog.ok")){
941                 okButton.setText(props.getProperty("com.Ostermiller.util.BrowserDialog.ok"));
942             }
943             if (props.containsKey("com.Ostermiller.util.BrowserDialog.cancel")){
944                 cancelButton.setText(props.getProperty("com.Ostermiller.util.BrowserDialog.cancel"));
945             }
946             pack();
947         }
948
949         /**
950          * Whether the user pressed the applied changes.
951          * true if OK was pressed or the user otherwise applied new changes,
952          * false if cancel was pressed or dialog was closed with no changes.
953          * If called before the dialog is displayed and closed, the results
954          * are not defined.
955          *
956          * @returns if the user made changes to the browser configuration.
957          *
958          * @since ostermillerutils 1.00.00
959          */

960         public boolean changed() {
961             return pressed_OK;
962         }
963
964         /**
965          * Create this dialog with the given parent and title.
966          *
967          * @param parent window from which this dialog is launched
968          * @param title the title for the dialog box window
969          *
970          * @since ostermillerutils 1.00.00
971          */

972         public BrowserDialog(Frame parent) {
973             super(parent, labels.getString("dialog.title"), true);
974             setLocationRelativeTo(parent);
975             // super calls dialogInit, so we don't need to do it again.
976
}
977
978         /**
979          * Called by constructors to initialize the dialog.
980          *
981          * @since ostermillerutils 1.00.00
982          */

983         protected void dialogInit(){
984
985             super.dialogInit();
986
987             getContentPane().setLayout(new BorderLayout());
988
989             getContentPane().add(getDialogPanel(this), BorderLayout.CENTER);
990
991             JPanel panel = new JPanel(new FlowLayout());
992             okButton = new JButton(labels.getString("dialog.ok"));
993             okButton.addActionListener(new ActionListener() {
994                 public void actionPerformed(ActionEvent e){
995                     pressed_OK = true;
996                     BrowserDialog.this.setVisible(false);
997                 }
998             });
999             panel.add(okButton);
1000            cancelButton = new JButton(labels.getString("dialog.cancel"));
1001            cancelButton.addActionListener(new ActionListener() {
1002                public void actionPerformed(ActionEvent e){
1003                    pressed_OK = false;
1004                    BrowserDialog.this.setVisible(false);
1005                }
1006            });
1007            panel.add(cancelButton);
1008
1009            getContentPane().add(panel, BorderLayout.SOUTH);
1010
1011            pack();
1012        }
1013
1014        /**
1015         * Shows the dialog.
1016         *
1017         * @since ostermillerutils 1.00.00
1018         * @deprecated use setVisible(true);
1019         */

1020        public void show(){
1021            setVisible(true);
1022        }
1023
1024        public void setVisible(boolean visible){
1025            if (visible){
1026                initPanel();
1027                super.setVisible(true);
1028                if (pressed_OK){
1029                    userOKedPanelChanges();
1030                }
1031            } else {
1032                super.setVisible(false);
1033            }
1034        }
1035
1036
1037    }
1038
1039    private static void setCommands(String JavaDoc[] newExec){
1040        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1041        for (int i=0; newExec != null && i < newExec.length; i++){
1042            sb.append(newExec[i]).append('\n');
1043        }
1044        commandLinesArea.setText(sb.toString());
1045    }
1046
1047    /**
1048     * If you are using the getDialogPanel() method to create your own dialog, this
1049     * method should be called every time before you display the dialog.
1050     *
1051     * mydialog.add(Browser.getDialogPanel(mydialog));
1052     * Browser.initPanel();
1053     * mydialog.show();
1054     * if (ok_pressed){
1055     * &nbsp;&nbsp;Browser.userOKedPanelChanges();
1056     * }
1057     *
1058     * @since ostermillerutils 1.02.22
1059     */

1060    public static void initPanel(){
1061        setCommands(exec);
1062    }
1063
1064    /**
1065     * If you are using the getDialogPanel() method to create your own dialog, this
1066     * method should be called after you display the dialog if the user pressed ok.
1067     *
1068     * mydialog.add(Browser.getDialogPanel(mydialog));
1069     * Browser.initPanel();
1070     * mydialog.show();
1071     * if (ok_pressed){
1072     * &nbsp;&nbsp;Browser.userOKedPanelChanges();
1073     * }
1074     *
1075     * @since ostermillerutils 1.02.22
1076     */

1077    public static void userOKedPanelChanges(){
1078        java.util.StringTokenizer JavaDoc tok = new java.util.StringTokenizer JavaDoc(commandLinesArea.getText(), "\r\n", false);
1079        int count = tok.countTokens();
1080        String JavaDoc[] exec = new String JavaDoc[count];
1081        for (int i=0; i < count; i++){
1082            exec[i] = tok.nextToken();
1083        }
1084        Browser.exec = exec;
1085    }
1086}
1087
Popular Tags