Java tutorial
package org.openqa.selenium.server.browserlaunchers; import org.apache.commons.logging.Log; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.Copy; import org.apache.tools.ant.taskdefs.Delete; import org.apache.tools.ant.types.FileSet; import org.openqa.jetty.log.LogFactory; import org.openqa.selenium.server.SeleniumServer; import org.openqa.selenium.server.ClassPathResource; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Various static utility functions used to launch browsers */ public class LauncherUtils { static Log log = LogFactory.getLog(LauncherUtils.class); /** * creates an empty temp directory for managing a browser profile */ protected static File createCustomProfileDir(String sessionId) { final File customProfileDir; customProfileDir = customProfileDir(sessionId); if (customProfileDir.exists()) { LauncherUtils.recursivelyDeleteDir(customProfileDir); } customProfileDir.mkdir(); return customProfileDir; } /** * Return the name of the custom profile directory for a specific seleniumm session * * @param sessionId Current selenium sesssion id. Cannot be null. * @return file path of the custom profile directory for this session. */ public static File customProfileDir(String sessionId) { final File tmpDir; final String customProfileDirParent; final File customProfileDir; tmpDir = new File(System.getProperty("java.io.tmpdir")); customProfileDirParent = ((tmpDir.exists() && tmpDir.isDirectory()) ? tmpDir.getAbsolutePath() : "."); customProfileDir = new File(customProfileDirParent + "/customProfileDir" + sessionId); return customProfileDir; } /** * Delete a directory and all subdirectories */ public static void recursivelyDeleteDir(File customProfileDir) { if (customProfileDir == null || !customProfileDir.exists()) { return; } Delete delete = new Delete(); delete.setProject(new Project()); delete.setDir(customProfileDir); delete.setFailOnError(true); delete.execute(); } /** * Try several times to recursively delete a directory */ public static void deleteTryTryAgain(File dir, int tries) { try { recursivelyDeleteDir(dir); } catch (BuildException e) { if (tries > 0) { AsyncExecute.sleepTight(2000); deleteTryTryAgain(dir, tries - 1); } else { throw e; } } } /** * Generate a proxy.pac file, configuring a dynamic proxy for URLs * containing "/selenium-server/" * @param avoidProxy TODO */ protected static File makeProxyPAC(File parentDir, int port, boolean avoidProxy) throws FileNotFoundException { return makeProxyPAC(parentDir, port, true, avoidProxy); } /** * Generate a proxy.pac file, configuring a dynamic proxy. <p/> If * proxySeleniumTrafficOnly is true, then the proxy applies only to URLs * containing "/selenium-server/". Otherwise the proxy applies to all URLs. * @param avoidProxy TODO */ protected static File makeProxyPAC(File parentDir, int port, boolean proxySeleniumTrafficOnly, boolean avoidProxy) throws FileNotFoundException { return makeProxyPAC(parentDir, port, proxySeleniumTrafficOnly, System.getProperty("http.proxyHost"), System.getProperty("http.proxyPort"), System.getProperty("http.nonProxyHosts"), avoidProxy); } public static File makeProxyPAC(File parentDir, int port, boolean proxySeleniumTrafficOnly, String configuredProxy, String proxyPort, String nonProxyHosts, boolean avoidProxy) throws FileNotFoundException { if (!avoidProxy) { proxySeleniumTrafficOnly = false; } File proxyPAC = new File(parentDir, "proxy.pac"); PrintStream out = new PrintStream(new FileOutputStream(proxyPAC)); String defaultProxy = "DIRECT"; if (configuredProxy != null) { defaultProxy = "PROXY " + configuredProxy; if (proxyPort != null) { defaultProxy += ":" + proxyPort; } } out.println("function FindProxyForURL(url, host) {"); if (proxySeleniumTrafficOnly) { out.println(" if(shExpMatch(url, '*/selenium-server/*')) {"); } out.println(" return 'PROXY localhost:" + Integer.toString(port) + "; " + defaultProxy + "';"); if (proxySeleniumTrafficOnly) { if (nonProxyHosts != null && nonProxyHosts.trim().length() > 0) { String[] hosts = nonProxyHosts.split("\\|"); for (String host : hosts) { out.println(" } else if (shExpMatch(host, '" + host + "')) {"); out.println(" return 'DIRECT';"); } } if (configuredProxy != null) { out.println(" } else {"); out.println(" return '" + defaultProxy + "';"); } out.println(" }"); } out.println("}"); out.close(); return proxyPAC; } /** * Strips the specified URL so it only includes a protocal, hostname and * port * * @throws MalformedURLException */ public static String stripStartURL(String url) { try { URL u = new URL(url); String path = u.getPath(); if (path != null && !"".equals(path) && !path.endsWith("/")) { log.warn("It looks like your baseUrl (" + url + ") is pointing to a file, not a directory (it doesn't end with a /). We're going to have to strip off the last part of the pathname."); } return u.getProtocol() + "://" + u.getAuthority(); } catch (MalformedURLException e) { throw new RuntimeException(e); } } protected static String getQueryString(String url) { final String query; try { query = new URL(url).getQuery(); return query == null ? "" : query; } catch (MalformedURLException e) { throw new RuntimeException(e); } } protected static String getDefaultHTMLSuiteUrl(String browserURL, String suiteUrl, boolean multiWindow, int serverPort) { String url = LauncherUtils.stripStartURL(browserURL); String resultsUrl; if (serverPort == 0) { resultsUrl = "../postResults"; } else { resultsUrl = "http://localhost:" + serverPort + "/selenium-server/postResults"; } return url + "/selenium-server/core/TestRunner.html?auto=true" + "&multiWindow=" + multiWindow + "&defaultLogLevel=info" + "&baseUrl=" + urlEncode(browserURL) + "&resultsUrl=" + resultsUrl + "&test=" + urlEncode(suiteUrl); } protected static String getDefaultRemoteSessionUrl(String startURL, String sessionId, boolean multiWindow, int serverPort, boolean browserSideLog) { String url = LauncherUtils.stripStartURL(startURL); url += "/selenium-server/core/RemoteRunner.html?" + "sessionId=" + sessionId + "&multiWindow=" + multiWindow + "&baseUrl=" + urlEncode(startURL) + "&debugMode=" + browserSideLog; if (serverPort != 0) { url += "&driverUrl=http://localhost:" + serverPort + "/selenium-server/driver/"; } return url; } /** Encodes the text as an URL using UTF-8. * * @param text the text too encode * @return the encoded URI string * @see URLEncoder#encode(java.lang.String, java.lang.String) */ public static String urlEncode(String text) { try { return URLEncoder.encode(text, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } protected static File extractHTAFile(File dir, int port, String resourceFile, String outFile) { InputStream input = getSeleniumResourceAsStream(resourceFile); BufferedReader br = new BufferedReader(new InputStreamReader(input)); File hta = new File(dir, outFile); try { FileWriter fw = new FileWriter(hta); String line = br.readLine(); fw.write(line); fw.write('\n'); fw.write("<base href=\"http://localhost:" + port + "/selenium-server/core/\">"); while ((line = br.readLine()) != null) { fw.write(line); fw.write('\n'); } fw.flush(); fw.close(); } catch (IOException e) { throw new RuntimeException(e); } return hta; } public static InputStream getSeleniumResourceAsStream(String resourceFile) { Class clazz = ClassPathResource.class; InputStream input = clazz.getResourceAsStream(resourceFile); if (input == null) { try { // This is hack for the OneJar version of Selenium-Server. // Examine the contents of the jar made by // https://svn.openqa.org/svn/selenium-rc/trunk/selenium-server-onejar/build.xml clazz = Class.forName("OneJar"); input = clazz.getResourceAsStream(resourceFile); } catch (ClassNotFoundException e) { } } return input; } public static boolean isScriptFile(File aFile) { final char firstTwoChars[] = new char[2]; final FileReader reader; int charsRead; try { reader = new FileReader(aFile); charsRead = reader.read(firstTwoChars); if (2 != charsRead) { return false; } return (firstTwoChars[0] == '#' && firstTwoChars[1] == '!'); } catch (IOException e) { throw new RuntimeException(e); } } protected static void copySingleFile(File sourceFile, File destFile) { copySingleFileWithOverwrite(sourceFile, destFile, false); } protected static void copySingleFileWithOverwrite(File sourceFile, File destFile, boolean overwrite) { Project p = new Project(); Copy c = new Copy(); c.setProject(p); c.setTofile(destFile); FileSet fs = new FileSet(); fs.setProject(p); fs.setFile(sourceFile); c.addFileset(fs); c.setOverwrite(overwrite); c.execute(); } protected static void copyDirectory(File source, File dest) { Project p = new Project(); Copy c = new Copy(); c.setProject(p); c.setTodir(dest); FileSet fs = new FileSet(); fs.setDir(source); c.addFileset(fs); c.execute(); } /** * Copies all files matching the suffix to the destination directory. * * If no files match, and the destination directory did not already * exist, the destination directory is still created, if possible. * * @param source the source directory * @param suffix the suffix for all files to be copied. * @param dest the destination directory */ protected static boolean copyDirectory(File source, String suffix, File dest) { boolean result = false; try { Project p = new Project(); Copy c = new Copy(); c.setProject(p); c.setTodir(dest); FileSet fs = new FileSet(); fs.setDir(source); if (null != suffix) { fs.setIncludes("*" + suffix); // add the wildcard. } c.addFileset(fs); c.execute(); // handle case where no files match; must create empty directory. if (!dest.exists()) { result = dest.mkdirs(); } else { result = true; } } catch (SecurityException se) { log.warn("Could not copy the specified directory files", se); result = false; } return result; } protected enum ProxySetting { NO_PROXY, PROXY_SELENIUM_TRAFFIC_ONLY, PROXY_EVERYTHING }; protected static void generatePacAndPrefJs(File customProfileDir, int port, ProxySetting proxySetting, String homePage, boolean changeMaxConnections, int timeoutInSeconds, boolean avoidProxy) throws FileNotFoundException { // We treat PROXY_SELENIUM_TRAFFIC_ONLY as a suggestion; if the user didn't explicitly // allow us to proxy selenium traffic only, then we'll proxy everything if (proxySetting == ProxySetting.PROXY_SELENIUM_TRAFFIC_ONLY && avoidProxy) { proxySetting = ProxySetting.PROXY_EVERYTHING; } File prefsJS = new File(customProfileDir, "prefs.js"); PrintStream out = new PrintStream(new FileOutputStream(prefsJS, true)); // Don't ask if we want to switch default browsers out.println("user_pref('browser.shell.checkDefaultBrowser', false);"); if (proxySetting != ProxySetting.NO_PROXY) { boolean proxySeleniumTrafficOnly = (proxySetting == ProxySetting.PROXY_SELENIUM_TRAFFIC_ONLY); // Configure us as the local proxy File proxyPAC = LauncherUtils.makeProxyPAC(customProfileDir, port, proxySeleniumTrafficOnly, avoidProxy); out.println("user_pref('network.proxy.type', 2);"); out.println("user_pref('network.proxy.autoconfig_url', '" + pathToBrowserURL(proxyPAC.getAbsolutePath()) + "');"); } // suppress authentication confirmations out.println("user_pref('network.http.phishy-userpass-length', 255);"); // Disable pop-up blocking out.println("user_pref('browser.allowpopups', true);"); out.println("user_pref('dom.disable_open_during_load', false);"); // Allow scripts to run as long as the server timeout out.println("user_pref('dom.max_script_run_time', " + timeoutInSeconds + ");"); out.println("user_pref('dom.max_chrome_script_run_time', " + timeoutInSeconds + ");"); // Open links in new windows (Firefox 2.0) out.println("user_pref('browser.link.open_external', 2);"); out.println("user_pref('browser.link.open_newwindow', 2);"); if (homePage != null) { out.println("user_pref('startup.homepage_override_url', '" + homePage + "');"); // for Firefox 2.0 out.println("user_pref('browser.startup.homepage', '" + homePage + "');"); out.println("user_pref('startup.homepage_welcome_url', '');"); // This handles known RC problems when the startup page is a blank page or when the previous session has been restored out.println("user_pref('browser.startup.page', 1);"); } // Disable security warnings out.println("user_pref('security.warn_submit_insecure', false);"); out.println("user_pref('security.warn_submit_insecure.show_once', false);"); out.println("user_pref('security.warn_entering_secure', false);"); out.println("user_pref('security.warn_entering_secure.show_once', false);"); out.println("user_pref('security.warn_entering_weak', false);"); out.println("user_pref('security.warn_entering_weak.show_once', false);"); out.println("user_pref('security.warn_leaving_secure', false);"); out.println("user_pref('security.warn_leaving_secure.show_once', false);"); out.println("user_pref('security.warn_viewing_mixed', false);"); out.println("user_pref('security.warn_viewing_mixed.show_once', false);"); // Disable cache out.println("user_pref('browser.cache.disk.enable', false);"); out.println("user_pref('browser.cache.memory.enable', true);"); // Disable "do you want to remember this password?" out.println("user_pref('signon.rememberSignons', false);"); // Disable re-asking for license agreement (Firefox 3) out.println("user_pref('browser.EULA.3.accepted', true);"); out.println("user_pref('browser.EULA.override', true);"); // Disable any of the random self-updating crap out.println("user_pref('app.update.auto', false);"); out.println("user_pref('app.update.enabled', false);"); out.println("user_pref('extensions.update.enabled', false);"); out.println("user_pref('browser.search.update', false);"); out.println("user_pref('browser.safebrowsing.enabled', false);"); if (changeMaxConnections) { out.println("user_pref('network.http.max-connections', 256);"); out.println("user_pref('network.http.max-connections-per-server', 256);"); out.println("user_pref('network.http.max-persistent-connections-per-proxy', 256);"); out.println("user_pref('network.http.max-persistent-connections-per-server', 256);"); } out.close(); } static final Pattern JAVA_STYLE_UNC_URL = Pattern.compile("^file:////([^/]+/.*)$"); /** * Generates an URL suitable for use in browsers, unlike Java's URLs, which * choke on UNC paths. <p/> * <P> * Java's URLs work in IE, but break in Mozilla. Mozilla's team snobbily * demanded that <I>all</I> file paths must have the empty authority * (file:///), even for UNC file paths. On Mozilla \\socrates\build is * therefore represented as file://///socrates/build. * </P> * See Mozilla bug <a * href="https://bugzilla.mozilla.org/show_bug.cgi?id=66194">66194</A>. * * @param path - * the file path to convert to a browser URL * @return a nice Mozilla-compatible file URL */ private static String pathToBrowserURL(String path) { if (path == null) return null; String url = (new File(path)).toURI().toString(); Matcher m = JAVA_STYLE_UNC_URL.matcher(url); if (m.find()) { url = "file://///"; url += m.group(1); } return url; } /** Run the specified pattern on each line of the data to extract a dictionary */ public static Map<String, String> parseDictionary(String data, Pattern pattern, boolean reverse) { Map<String, String> map = new HashMap<String, String>(); for (String line : data.split("\n")) { Matcher m = pattern.matcher(line); if (!m.find()) continue; String name, value; if (reverse) { name = m.group(2); value = m.group(1); } else { name = m.group(1); value = m.group(2); } map.put(name, value); } return map; } public static Map<String, String> parseDictionary(String data, Pattern pattern) { return parseDictionary(data, pattern, false); } }