/** * Allows user to target several browsers. The names of potential browsers can be accessed via the * {@link #getBrowserList() getBrowserList} method. * * <p>The browsers from the list will be tried in order (first to last) until one of the calls * succeeds. If all the calls to the requested browsers fail, the code will fail over to the * default browser. * * @param browsers List * @param urlString String * @throws UnsupportedOperatingSystemException * @throws BrowserLaunchingExecutionException * @throws BrowserLaunchingInitializingException */ public void openUrl(List browsers, String urlString) throws UnsupportedOperatingSystemException, BrowserLaunchingExecutionException, BrowserLaunchingInitializingException { if (browsers == null || browsers.isEmpty()) { logger.debug("falling through to non-targetted openUrl"); openUrl(urlString); } else { String protocol = null; try { protocol = getProtocol(urlString); } catch (MalformedURLException malrulex) { throw new BrowserLaunchingExecutionException(malrulex); } Map browserMap = getBrowserMap(); boolean success = false; Iterator iter = browsers.iterator(); while (iter.hasNext() && !success) { WindowsBrowser winBrowser = (WindowsBrowser) browserMap.get(iter.next()); if (winBrowser != null) { success = openUrlWithBrowser(winBrowser, protocol, urlString); } } if (!success) { logger.debug("none of listed browsers succeeded; falling through to non-targetted openUrl"); openUrl(urlString); } } }
/** * Attempts to open a url with the specified browser. This is a utility method called by the * openUrl methods. * * @param winBrowser WindowsBrowser * @param protocol String * @param urlString String * @return boolean * @throws BrowserLaunchingExecutionException */ private boolean openUrlWithBrowser(WindowsBrowser winBrowser, String protocol, String urlString) throws BrowserLaunchingExecutionException { boolean success = false; try { logger.info(winBrowser.getBrowserDisplayName()); logger.info(urlString); logger.info(protocol); String args = getCommandArgs(protocol, winBrowser, urlString, forceNewWindow); if (logger.isDebugEnabled()) { logger.debug(args); } Process process = Runtime.getRuntime().exec(args); // This avoids a memory leak on some versions of Java on Windows. // That's hinted at in <http://developer.java.sun.com/developer/qow/archive/68/>. process.waitFor(); // some browsers (mozilla, firefox) return 1 if you attempt to // open a url and an instance of that browser is already running // not clear why because the call is succeeding, ie the browser // opens the url. // If we don't say 1 is also a success, we get two browser // windows or tabs opened to the url. // // We could make this check smarter in the future if we run // into problems. the winBrowser object could handle the // check to make it browser specific. int exitValue = process.exitValue(); success = exitValue == 0 || exitValue == 1; } // Runtimes may throw InterruptedException // want to catch every possible exception and wrap it catch (Exception e) { throw new BrowserLaunchingExecutionException(e); } return success; }
/** * Opens a url using a specific browser. * * <p>If the specified browser is not available, the method will fall through to calling the * default openUrl method. * * @param browser String * @param urlString String * @throws UnsupportedOperatingSystemException * @throws BrowserLaunchingExecutionException * @throws BrowserLaunchingInitializingException */ public void openUrl(String browser, String urlString) throws UnsupportedOperatingSystemException, BrowserLaunchingExecutionException, BrowserLaunchingInitializingException { if (IBrowserLaunching.BROWSER_DEFAULT.equals(browser) || browser == null) { logger.info("default or null browser target; falling through to non-targetted openUrl"); openUrl(urlString); } else { Map browserMap = getBrowserMap(); WindowsBrowser winBrowser = (WindowsBrowser) browserMap.get(browser); if (winBrowser == null) { logger.info("the available browsers list does not contain: " + browser); logger.info("falling through to non-targetted openUrl"); openUrl(urlString); } else { String protocol = null; try { protocol = getProtocol(urlString); } catch (MalformedURLException malrulex) { throw new BrowserLaunchingExecutionException(malrulex); } boolean successfullLaunch = openUrlWithBrowser(winBrowser, protocol, urlString); if (!successfullLaunch) { logger.debug("falling through to non-targetted openUrl"); openUrl(urlString); } } } }
/** * Initializes the browser launcher from the windows config file. It initializes the browsers to * check list and the command line args to use for version of windows referenced by the * windowsKey. * * @see windowsKey * @throws BrowserLaunchingInitializingException */ public void initialize() throws BrowserLaunchingInitializingException { try { URL configUrl = getClass().getResource(CONFIGFILE_WINDOWS); if (configUrl == null) { throw new BrowserLaunchingInitializingException( "unable to find config file: " + CONFIGFILE_WINDOWS); } Properties configProps = new Properties(); configProps.load(configUrl.openStream()); // get sep char String sepChar = configProps.getProperty(PROP_KEY_DELIMITER); // load different types of browsers Iterator keysIter = configProps.keySet().iterator(); while (keysIter.hasNext()) { String key = (String) keysIter.next(); if (key.startsWith(PROP_KEY_BROWSER_PREFIX)) { WindowsBrowser winBrowser = new WindowsBrowser(sepChar, configProps.getProperty(key)); browsersToCheck.add(winBrowser); } } // load the type of windows based on the windows key String windowsConfigStr = configProps.getProperty(windowsKey, null); if (windowsConfigStr == null) { throw new BrowserLaunchingInitializingException(windowsKey + " is not a valid property"); } String[] winConfigItems = windowsConfigStr.split(sepChar); commandsDefaultBrowser = winConfigItems[0]; commandsTargettedBrowser = winConfigItems[1]; Boolean boolVal = new Boolean(winConfigItems[2]); useRegistry = boolVal.booleanValue(); // check for override of useRegistry from system prop // need to explicitly check BOTH values to filter out // invalid prop values String propValue = System.getProperty(IBrowserLaunching.WINDOWS_BROWSER_DISC_POLICY_PROPERTY, null); if (IBrowserLaunching.WINDOWS_BROWSER_DISC_POLICY_DISK.equals(propValue)) { useRegistry = false; } else if (IBrowserLaunching.WINDOWS_BROWSER_DISC_POLICY_REGISTRY.equals(propValue)) { useRegistry = true; } if (logger.isDebugEnabled()) { logger.debug( "Browser discovery policy property value=" + (propValue == null ? "null" : propValue)); logger.debug("useRegistry=" + Boolean.toString(useRegistry)); } // get info for checking Program Files folder programFilesFolderTemplate = configProps.getProperty("program.files.template", null); driveLetters = configProps.getProperty("drive.letters", null); // set brwosersToCheck to a non-modifiable list browsersToCheck = Collections.unmodifiableList(browsersToCheck); } catch (IOException ioex) { throw new BrowserLaunchingInitializingException(ioex); } }
/** * Use program files folder template from properties file and the list of drive letters from that * properties file * * @return File */ private File getProgramFilesPath() { File progFilesPath = null; if (driveLetters != null && programFilesFolderTemplate != null) { String[] drives = driveLetters.split(";"); for (int idx = 0; idx < drives.length && progFilesPath == null; idx++) { String path = MessageFormat.format(programFilesFolderTemplate, new Object[] {drives[idx]}); File pfPath = new File(path); logger.debug(path); logger.debug(pfPath.getPath()); if (pfPath.exists()) { progFilesPath = pfPath; } } } return progFilesPath; }
/** * Accesses the Windows registry to look for browser exes. The browsers search for are in the * browsersToCheck list. The returned map will use display names and exe names as keys to the * {@link WindowsBrowser WindowsBrowser} objects. * * @param browsersToCheck List * @return Map */ private Map getAvailableBrowsers(List tempBrowsersToCheck) { logger.debug("finding available browsers using registry"); logger.debug("browsers to check: " + tempBrowsersToCheck); Map browsersAvailable = new TreeMap(String.CASE_INSENSITIVE_ORDER); try { // create map of exe names to win browser objects Map exesToBrowserObjs = getExeNamesToBrowsers(tempBrowsersToCheck); // access and look in registry Regor regor = new Regor(); String subKeyName = "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths"; int key = regor.openKey(Regor.HKEY_LOCAL_MACHINE, subKeyName); if (key > -1) { List keys = regor.listKeys(key); Collections.sort(keys, String.CASE_INSENSITIVE_ORDER); Iterator keysIter = exesToBrowserObjs.keySet().iterator(); while (keysIter.hasNext()) { String exeKey = (String) keysIter.next(); int index = Collections.binarySearch(keys, exeKey, String.CASE_INSENSITIVE_ORDER); if (index >= 0) { WindowsBrowser winBrowser = getBrowserFromRegistryEntry( regor, key, (String) keys.get(index), exeKey, exesToBrowserObjs); if (winBrowser != null) { if (logger.isDebugEnabled()) { logger.debug( "Adding browser " + winBrowser.getBrowserDisplayName() + " to available list."); logger.debug(winBrowser.getPathToExe()); } // adding display and exe for backward compatibility and // ease of use if someone passes in the name of an exe browsersAvailable.put(winBrowser.getBrowserDisplayName(), winBrowser); browsersAvailable.put(winBrowser.getBrowserApplicationName(), winBrowser); tempBrowsersToCheck.remove(winBrowser); } } } } } catch (RegistryErrorException ex) { logger.error("problem accessing registry", ex); } return browsersAvailable; }
/** * Checks that the windows key is valid. * * @param logger AbstractLogger * @param windowsKey String */ public WindowsBrowserLaunching(AbstractLogger logger, String windowsKey) { if (windowsKey == null) { throw new IllegalArgumentException("windowsKey cannot be null"); } if (Arrays.binarySearch(WIN_KEYS, windowsKey) < 0) { throw new IllegalArgumentException(windowsKey + " is invalid"); } this.logger = logger; this.windowsKey = windowsKey; logger.info(windowsKey); }
/** * Opens a url using the default browser. * * @param urlString String * @throws UnsupportedOperatingSystemException * @throws BrowserLaunchingExecutionException * @throws BrowserLaunchingInitializingException */ public void openUrl(String urlString) throws UnsupportedOperatingSystemException, BrowserLaunchingExecutionException, BrowserLaunchingInitializingException { try { logger.info(urlString); String protocol = getProtocol(urlString); logger.info(protocol); // try the system prop first boolean successfullSystemPropLaunch = false; String browserName = System.getProperty(IBrowserLaunching.BROWSER_SYSTEM_PROPERTY, null); if (browserName != null) { Map browserMap = getBrowserMap(); WindowsBrowser winBrowser = (WindowsBrowser) browserMap.get(browserName); if (winBrowser != null) { logger.debug("using browser from system property"); successfullSystemPropLaunch = openUrlWithBrowser(winBrowser, protocol, urlString); } } if (!successfullSystemPropLaunch) { String[] args = getCommandArgs(protocol, urlString); if (logger.isDebugEnabled()) { logger.debug(getArrayAsString(args)); } Process process = Runtime.getRuntime().exec(args); // This avoids a memory leak on some versions of Java on Windows. // That's hinted at in <http://developer.java.sun.com/developer/qow/archive/68/>. process.waitFor(); process.exitValue(); } } catch (Exception e) { logger.error("fatal exception", e); throw new BrowserLaunchingExecutionException(e); } }
/** * Secondary method for browser discovery. * * <p>Uses IE to get the path to the Program Files directory; then gets a list of the sub dirs and * checks them against the remaining browsers. * * @param iePath String * @param browsersAvailable Map * @param tmpBrowsersToCheck List */ private Map processFilePathsForBrowsers(List tmpBrowsersToCheck) { logger.debug("finding available browsers in program files path"); logger.debug("browsers to check: " + tmpBrowsersToCheck); Map browsersAvailable = new HashMap(); File progFilesPath = getProgramFilesPath(); if (progFilesPath != null) { logger.debug("program files path: " + progFilesPath.getPath()); File[] subDirs = progFilesPath.listFiles(new DirFileFilter()); int subDirsCnt = subDirs != null ? subDirs.length : 0; // create and populate map of dir names to win browser objects Iterator iter = tmpBrowsersToCheck.iterator(); Map dirNameToBrowser = new HashMap(); while (iter.hasNext()) { WindowsBrowser wBrowser = (WindowsBrowser) iter.next(); dirNameToBrowser.put(wBrowser.getSubDirName(), wBrowser); } // iterate over subdirs and compare to map entries for (int idx = 0; idx < subDirsCnt && !tmpBrowsersToCheck.isEmpty(); idx++) { if (dirNameToBrowser.containsKey(subDirs[idx].getName())) { WindowsBrowser wBrowser = (WindowsBrowser) dirNameToBrowser.get(subDirs[idx].getName()); // need to search folder and sub-folders for exe to find // the full path String exeName = wBrowser.getBrowserApplicationName() + ".exe"; File fullPathToExe = findExeFilePath(subDirs[idx], exeName); if (fullPathToExe != null) { logger.debug( "Adding browser " + wBrowser.getBrowserDisplayName() + " to available list."); wBrowser.setPathToExe(fullPathToExe.getPath()); logger.debug(wBrowser.getPathToExe()); // adding display and exe for backward compatibility and // ease of use if someone passes in the name of an exe browsersAvailable.put(wBrowser.getBrowserDisplayName(), wBrowser); browsersAvailable.put(wBrowser.getBrowserApplicationName(), wBrowser); tmpBrowsersToCheck.remove(wBrowser); } } } } return browsersAvailable; }
/** * Returns true if the browser is available, ie mdfind command finds it. * * @param logger AbstractLogger * @return boolean */ public boolean isBrowserAvailable(StandardUnixBrowser browser, AbstractLogger logger) { boolean isAvailable = false; try { Process process = Runtime.getRuntime().exec(new String[] {"mdfind", browser.getBrowserApplicationName()}); InputStream errStream = process.getErrorStream(); InputStream inStream = process.getInputStream(); BufferedReader errIn = new BufferedReader(new InputStreamReader(errStream)); BufferedReader in = new BufferedReader(new InputStreamReader(inStream)); String temp; StringBuffer whichOutput = new StringBuffer(); while ((temp = in.readLine()) != null) { // Searching with spotlight (mdfind) will find more than just the app sometimes if (temp.indexOf(browser.getBrowserApplicationName()) > -1) { whichOutput.append(temp); } } StringBuffer whichErrOutput = new StringBuffer(); while ((temp = errIn.readLine()) != null) { whichErrOutput.append(temp); } in.close(); errIn.close(); if (whichOutput.length() > 0) { logger.debug(whichOutput.toString()); // very weak test but should be enough since the Open -a applicationname works very well isAvailable = true; } if (whichErrOutput.length() > 0) { logger.debug(whichErrOutput.toString()); } } catch (IOException ex) { logger.error("io error executing which command", ex); } return isAvailable; }