1616// under the License.
1717package org .openqa .selenium .manager ;
1818
19- import static java .nio .file .StandardCopyOption .REPLACE_EXISTING ;
2019import static org .openqa .selenium .Platform .MAC ;
2120import static org .openqa .selenium .Platform .WINDOWS ;
2221
2322import java .io .IOException ;
2423import java .io .InputStream ;
25- import java .nio .file .FileVisitResult ;
2624import java .nio .file .Files ;
2725import java .nio .file .Path ;
2826import java .nio .file .Paths ;
29- import java .nio .file .SimpleFileVisitor ;
30- import java .nio .file .attribute .BasicFileAttributes ;
3127import java .time .Duration ;
3228import java .util .ArrayList ;
3329import java .util .Arrays ;
3632import java .util .logging .Level ;
3733import java .util .logging .Logger ;
3834import org .openqa .selenium .Beta ;
35+ import org .openqa .selenium .BuildInfo ;
3936import org .openqa .selenium .Capabilities ;
4037import org .openqa .selenium .MutableCapabilities ;
4138import org .openqa .selenium .Platform ;
@@ -63,20 +60,31 @@ public class SeleniumManager {
6360 private static final Logger LOG = Logger .getLogger (SeleniumManager .class .getName ());
6461
6562 private static final String SELENIUM_MANAGER = "selenium-manager" ;
63+ private static final String DEFAULT_CACHE_PATH = "~/.cache/selenium" ;
64+ private static final String BINARY_PATH_FORMAT = "/manager/%s/%s" ;
65+ private static final String HOME = "~" ;
66+ private static final String CACHE_PATH_ENV = "SE_CACHE_PATH" ;
67+ private static final String BETA_PREFIX = "0." ;
68+ private static final String EXE = ".exe" ;
6669
6770 private static volatile SeleniumManager manager ;
68-
6971 private final String managerPath = System .getenv ("SE_MANAGER_PATH" );
7072 private Path binary = managerPath == null ? null : Paths .get (managerPath );
73+ private String seleniumManagerVersion ;
74+ private boolean binaryInTemporalFolder = false ;
7175
7276 /** Wrapper for the Selenium Manager binary. */
7377 private SeleniumManager () {
78+ BuildInfo info = new BuildInfo ();
79+ String releaseLabel = info .getReleaseLabel ();
80+ int lastDot = releaseLabel .lastIndexOf ("." );
81+ seleniumManagerVersion = BETA_PREFIX + releaseLabel .substring (0 , lastDot );
7482 if (managerPath == null ) {
7583 Runtime .getRuntime ()
7684 .addShutdownHook (
7785 new Thread (
7886 () -> {
79- if (binary != null && Files .exists (binary )) {
87+ if (binaryInTemporalFolder && binary != null && Files .exists (binary )) {
8088 try {
8189 Files .delete (binary );
8290 } catch (IOException e ) {
@@ -161,23 +169,27 @@ private static Result runCommand(Path binary, List<String> arguments) {
161169 */
162170 private synchronized Path getBinary () {
163171 if (binary == null ) {
164- Platform current = Platform .getCurrent ();
165- String folder = "linux" ;
166- String extension = "" ;
167- if (current .is (WINDOWS )) {
168- extension = ".exe" ;
169- folder = "windows" ;
170- } else if (current .is (MAC )) {
171- folder = "macos" ;
172- }
173- String binaryPath = String .format ("%s/%s%s" , folder , SELENIUM_MANAGER , extension );
174- try (InputStream inputStream = this .getClass ().getResourceAsStream (binaryPath )) {
175- Path tmpPath = Files .createTempDirectory (SELENIUM_MANAGER + System .nanoTime ());
172+ try {
173+ Platform current = Platform .getCurrent ();
174+ String folder = "linux" ;
175+ String extension = "" ;
176+ if (current .is (WINDOWS )) {
177+ extension = EXE ;
178+ folder = "windows" ;
179+ } else if (current .is (MAC )) {
180+ folder = "macos" ;
181+ }
176182
177- deleteOnExit (tmpPath );
183+ binary = getBinaryInCache (SELENIUM_MANAGER + extension );
184+ if (!binary .toFile ().exists ()) {
185+ String binaryPathInJar = String .format ("%s/%s%s" , folder , SELENIUM_MANAGER , extension );
186+ try (InputStream inputStream = this .getClass ().getResourceAsStream (binaryPathInJar )) {
187+ binary .getParent ().toFile ().mkdirs ();
188+ Files .copy (inputStream , binary );
189+ }
190+ binary .toFile ().setExecutable (true );
191+ }
178192
179- binary = tmpPath .resolve (SELENIUM_MANAGER + extension );
180- Files .copy (inputStream , binary , REPLACE_EXISTING );
181193 } catch (Exception e ) {
182194 throw new WebDriverException ("Unable to obtain Selenium Manager Binary" , e );
183195 }
@@ -192,35 +204,6 @@ private synchronized Path getBinary() {
192204 return binary ;
193205 }
194206
195- private void deleteOnExit (Path tmpPath ) {
196- Runtime .getRuntime ()
197- .addShutdownHook (
198- new Thread (
199- () -> {
200- try {
201- Files .walkFileTree (
202- tmpPath ,
203- new SimpleFileVisitor <Path >() {
204- @ Override
205- public FileVisitResult postVisitDirectory (Path dir , IOException exc )
206- throws IOException {
207- Files .delete (dir );
208- return FileVisitResult .CONTINUE ;
209- }
210-
211- @ Override
212- public FileVisitResult visitFile (Path file , BasicFileAttributes attrs )
213- throws IOException {
214- Files .delete (file );
215- return FileVisitResult .CONTINUE ;
216- }
217- });
218- } catch (IOException e ) {
219- // Do nothing. We're just tidying up.
220- }
221- }));
222- }
223-
224207 /**
225208 * Returns the browser binary path when present in the vendor options
226209 *
@@ -319,4 +302,25 @@ private Level getLogLevel() {
319302 }
320303 return level ;
321304 }
305+
306+ private Path getBinaryInCache (String binaryName ) throws IOException {
307+ String cachePath = DEFAULT_CACHE_PATH .replace (HOME , System .getProperty ("user.home" ));
308+
309+ // Look for cache path as env
310+ String cachePathEnv = System .getenv (CACHE_PATH_ENV );
311+ if (cachePathEnv != null ) {
312+ cachePath = cachePathEnv ;
313+ }
314+
315+ // If cache path is not writable, SM will be extracted to a temporal folder
316+ Path cacheParent = Paths .get (cachePath );
317+ if (!Files .isWritable (cacheParent )) {
318+ cacheParent = Files .createTempDirectory (SELENIUM_MANAGER );
319+ binaryInTemporalFolder = true ;
320+ }
321+
322+ return Paths .get (
323+ cacheParent .toString (),
324+ String .format (BINARY_PATH_FORMAT , seleniumManagerVersion , binaryName ));
325+ }
322326}
0 commit comments