1 package com.atlassian.webdriver;
2
3 import com.atlassian.browsers.BrowserConfig;
4 import com.atlassian.webdriver.browsers.AutoInstallConfiguration;
5 import com.atlassian.webdriver.utils.WebDriverUtil;
6 import com.google.common.base.Preconditions;
7 import com.google.common.base.Supplier;
8 import org.openqa.selenium.WebDriver;
9 import org.openqa.selenium.WebDriverException;
10 import org.openqa.selenium.ie.InternetExplorerDriver;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13
14 import java.lang.ref.WeakReference;
15 import java.util.Map;
16 import java.util.concurrent.ConcurrentHashMap;
17
18 import static com.atlassian.webdriver.utils.WebDriverUtil.getUnderlyingDriver;
19
20
21
22
23
24
25
26
27
28
29
30
31
32 public class LifecycleAwareWebDriverGrid
33 {
34 private static final Logger log = LoggerFactory.getLogger(LifecycleAwareWebDriverGrid.class);
35 private final static Map<String,AtlassianWebDriver> drivers = new ConcurrentHashMap<String, AtlassianWebDriver>();
36 private volatile static AtlassianWebDriver currentDriver;
37
38 private static final Map<String,WeakReference<Thread>> SHUTDOWN_HOOKS = new ConcurrentHashMap<String, WeakReference<Thread>>();
39
40 private LifecycleAwareWebDriverGrid() {}
41
42
43
44
45
46
47
48
49 public static AtlassianWebDriver getDriver()
50 {
51 String browserProperty = WebDriverFactory.getBrowserProperty();
52 if (browserIsConfigured(browserProperty))
53 {
54 AtlassianWebDriver driver = drivers.get(browserProperty);
55 currentDriver = driver;
56 return driver;
57 }
58
59 BrowserConfig browserConfig = AutoInstallConfiguration.setupBrowser();
60 AtlassianWebDriver driver = WebDriverFactory.getDriver(browserConfig);
61 drivers.put(browserProperty, driver);
62 currentDriver = driver;
63
64 addShutdownHook(browserProperty, driver);
65 return driver;
66 }
67
68 public static AtlassianWebDriver getCurrentDriver()
69 {
70 Preconditions.checkState(currentDriver != null, "The current driver has not been initialised");
71 return currentDriver;
72 }
73
74 public static Supplier<AtlassianWebDriver> currentDriverSupplier()
75 {
76 return new Supplier<AtlassianWebDriver>()
77 {
78 @Override
79 public AtlassianWebDriver get()
80 {
81 return getCurrentDriver();
82 }
83 };
84 }
85
86
87
88
89
90
91 public static void shutdown()
92 {
93 for (Map.Entry<String,AtlassianWebDriver> driver: drivers.entrySet())
94 {
95 quit(driver.getValue());
96 removeHook(driver);
97 }
98 drivers.clear();
99 SHUTDOWN_HOOKS.clear();
100 currentDriver = null;
101 }
102
103 private static void removeHook(Map.Entry<String, AtlassianWebDriver> driver)
104 {
105 WeakReference<Thread> hookRef = SHUTDOWN_HOOKS.get(driver.getKey());
106 final Thread hook = hookRef != null ? hookRef.get() : null;
107 if (hook != null)
108 {
109 Runtime.getRuntime().removeShutdownHook(hook);
110 }
111 }
112
113 private static void quit(AtlassianWebDriver webDriver)
114 {
115 try
116 {
117 webDriver.quit();
118 }
119 catch (WebDriverException e)
120 {
121 onQuitError(webDriver, e);
122 }
123 }
124
125
126 private static boolean browserIsConfigured(String browserProperty)
127 {
128 return drivers.containsKey(browserProperty);
129 }
130
131 private static void addShutdownHook(final String browserProperty, final WebDriver driver) {
132 final Thread quitter = new Thread()
133 {
134 @Override
135 public void run()
136 {
137 log.debug("Running shut down hook for {}", driver);
138 try
139 {
140 drivers.remove(browserProperty);
141 if (driver.equals(currentDriver))
142 {
143 currentDriver = null;
144 }
145 log.info("Quitting {}", getUnderlyingDriver(driver));
146 driver.quit();
147 log.debug("Finished shutdown hook {}", this);
148 }
149 catch (WebDriverException e)
150 {
151 onQuitError(driver, e);
152 }
153 }
154 };
155 SHUTDOWN_HOOKS.put(browserProperty, new WeakReference<Thread>(quitter));
156 Runtime.getRuntime().addShutdownHook(quitter);
157 }
158
159
160 private static void onQuitError(WebDriver webDriver, WebDriverException e)
161 {
162
163
164 log.warn("Exception when trying to quit driver {}: {}", webDriver, e.getMessage());
165 log.debug("Exception when trying to quit driver - details", e);
166 }
167
168 }