// BlogBridge -- RSS feed reader, manager, and web based service // Copyright (C) 2002-2006 by R. Pito Salas // // This program is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software Foundation; // either version 2 of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along with this program; // if not, write to the Free Software Foundation, Inc., 59 Temple Place, // Suite 330, Boston, MA 02111-1307 USA // // Contact: R. Pito Salas // mailto:pitosalas@users.sourceforge.net // More information: about BlogBridge // http://www.blogbridge.com // http://sourceforge.net/projects/blogbridge // // $Id: BrowserLauncher.java,v 1.26 2007/05/18 08:09:42 spyromus Exp $ // package com.salas.bb.utils; import com.jgoodies.uif.util.SystemUtils; import com.salas.bb.domain.prefs.UserPreferences; import com.salas.bb.utils.i18n.Strings; import com.salas.bbnative.OpenURL; import javax.jnlp.BasicService; import javax.jnlp.ServiceManager; import javax.jnlp.UnavailableServiceException; import javax.swing.*; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * BrowserLauncher is intended to cover internal implementation of calling default * client browser. */ public abstract class BrowserLauncher { private static final Logger LOG = Logger.getLogger(BrowserLauncher.class.getName()); private static final String THREAD_NAME = "Starting Browser"; private static BasicService basicService; private static boolean nativeErrored = false; private static final List MOZILLA_TYPE_BROWSERS; // Initialize service static { MOZILLA_TYPE_BROWSERS = new ArrayList(); MOZILLA_TYPE_BROWSERS.add("netscape"); MOZILLA_TYPE_BROWSERS.add("mozilla"); MOZILLA_TYPE_BROWSERS.add("firefox"); try { basicService = (BasicService)ServiceManager.lookup("javax.jnlp.BasicService"); } catch (UnavailableServiceException e) { // Leave NULL if JNLP is not available basicService = null; } } private BrowserLauncher() { // Hidden constructor of utility class. } /** * Calls the default handler to show the window for the letter sending. * * @param recepient the recepient address or NULL for default 'some@address.org'; * @param subject the subject of a letter. * @param body the text to send in a body. * @param browserExecutable the executable to use or NULL for platform default. */ public static void emailThis(String recepient, String subject, String body, String browserExecutable) { recepient = recepient == null ? "" : recepient.trim(); String mailto = "mailto:" + recepient + "?subject=" + (subject == null ? "" : StringUtils.encodeForURL(subject).replaceAll("\\+", "%20")) + "&body=" + (body == null ? "" : StringUtils.encodeForURL(body).replaceAll("\\+", "%20")); try { showDocument(new URL(mailto), browserExecutable); } catch (MalformedURLException e) { LOG.log(Level.SEVERE, "Failed to build up the mailto-URL.", e); } } /** * Shows document in default user browser. * * @param url URL to show. * @param browserExecutable executable path to start in non-WebStart case. */ public static void showDocument(final URL url, final String browserExecutable) { if (LOG.isLoggable(Level.FINEST)) LOG.finest("URL: " + url); new Thread(new Runnable() { public void run() { showDocument0(browserExecutable, url); } }, THREAD_NAME).start(); } private static void showDocument0(String browserExecutable, URL url) { if (showDocumentUsingNativeBrowser(browserExecutable, url)) return; // If application was started not using WebStart then we cannot // show links in default browser. if (!isUsingJWSBrowser()) { browserExecutable = getCorrectBrowserExecutable(browserExecutable); try { if (browserExecutable != null && MOZILLA_TYPE_BROWSERS.contains(browserExecutable.toLowerCase())) { showDocumentInMozilla(url, browserExecutable); } else { // General purpose launch operation Runtime.getRuntime().exec(convertToFullCommand(browserExecutable, url)); } } catch (IOException e) { JOptionPane.showMessageDialog(null, Strings.message("launch.browser.dialog.text"), Strings.message("launch.browser.dialog.title"), JOptionPane.INFORMATION_MESSAGE); } } else { // Open document basicService.showDocument(url); } } /** * Try calling native browser. * * @param browserExecutable browser executable. * @param url URL to open. * * @return <code>TRUE</code> if opening was successful. */ private static boolean showDocumentUsingNativeBrowser(String browserExecutable, URL url) { boolean success = false; if (!nativeErrored && SystemUtils.IS_OS_WINDOWS && StringUtils.isEmpty(browserExecutable)) { try { OpenURL.openURL(url, false); success = true; } catch (UnsatisfiedLinkError e) { nativeErrored = true; } catch (Throwable e) { LOG.log(Level.SEVERE, "Failed to use native browser", e); } } return success; } /** * Make an attempt to start mozilla-type browser. * * @param url URL to display. * @param browserExecutable browser executible. * * @throws IOException in case of any I/O exception. */ private static void showDocumentInMozilla(URL url, String browserExecutable) throws IOException { // cmd = 'netscape/mozilla/firefox -remote openURL(http://www.javaworld.com)' String urls = url.toString().replaceAll("\\s", "%20"); String cmd = browserExecutable + " -remote openURL(" + urls + ")"; Process p = Runtime.getRuntime().exec(cmd); try { // wait for exit code -- if it's 0, command worked, // otherwise we need to start the browser up. int exitCode = p.waitFor(); if (exitCode != 0) { // Command failed, start up the browser // cmd = 'netscape/mozilla/firefox http://www.javaworld.com' cmd = browserExecutable + " " + urls; Runtime.getRuntime().exec(cmd); } } catch (InterruptedException x) { LOG.log(Level.WARNING, MessageFormat.format(Strings.error("error.calling.browser"), new Object[] { cmd }), x); } } /** * Returns TRUE when will be using JWS browser. * * @return TRUE when will be using JWS browser. */ public static boolean isUsingJWSBrowser() { return basicService != null && basicService.isWebBrowserSupported(); } static String convertToFullCommand(String browserExecutable, final URL url) { if (browserExecutable == null || url == null) return null; // Append mark if there's no URL marks found if (browserExecutable.indexOf("$URL$") == -1) { browserExecutable += " $URL$"; } // Escape URL string String urlString = url.toString().replaceAll("\\s", "%20"); urlString = urlString.replaceAll("\\\\", "\\\\\\\\"); urlString = urlString.replaceAll("\\$", "\\\\\\$"); return browserExecutable.replaceAll("\\$URL\\$", urlString); } /** * Returns true if running under JWS. * * @return true if running under JWS. */ public static boolean isRunningUnderJWS() { return basicService != null; } /** * Corrects browser executable path. If path is not specified or empty it * is taken from <code>OSSettings</code>. * * @param browserExecutable current executable. * * @return corrected. */ public static String getCorrectBrowserExecutable(String browserExecutable) { // If there's no browser executable specified then try to get default browser. if (StringUtils.isEmpty(browserExecutable)) { browserExecutable = OSSettings.getDefaultBrowserPath(); } return browserExecutable == null ? null : browserExecutable.trim(); } /** * Listens for clicks over the links and call external browser for them. */ public static class LinkListener implements HyperlinkListener { private UserPreferences preferences; /** * Creates listener which takes browser executable from preferences. * * @param aPreferences preferences. */ public LinkListener(UserPreferences aPreferences) { preferences = aPreferences; } /** * Called when a hypertext link is updated. * * @param e the event responsible for the update */ public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) return; showDocument(e.getURL(), preferences.getInternetBrowser()); } } }