16
16
// under the License.
17
17
package org .openqa .selenium .manager ;
18
18
19
- import static java .nio .file .StandardCopyOption .REPLACE_EXISTING ;
20
19
import static org .openqa .selenium .Platform .MAC ;
21
20
import static org .openqa .selenium .Platform .WINDOWS ;
22
21
23
22
import java .io .IOException ;
24
23
import java .io .InputStream ;
25
- import java .nio .file .FileVisitResult ;
26
24
import java .nio .file .Files ;
27
25
import java .nio .file .Path ;
28
26
import java .nio .file .Paths ;
29
- import java .nio .file .SimpleFileVisitor ;
30
- import java .nio .file .attribute .BasicFileAttributes ;
31
27
import java .time .Duration ;
32
28
import java .util .ArrayList ;
33
29
import java .util .Arrays ;
36
32
import java .util .logging .Level ;
37
33
import java .util .logging .Logger ;
38
34
import org .openqa .selenium .Beta ;
35
+ import org .openqa .selenium .BuildInfo ;
39
36
import org .openqa .selenium .Capabilities ;
40
37
import org .openqa .selenium .MutableCapabilities ;
41
38
import org .openqa .selenium .Platform ;
@@ -63,20 +60,31 @@ public class SeleniumManager {
63
60
private static final Logger LOG = Logger .getLogger (SeleniumManager .class .getName ());
64
61
65
62
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" ;
66
69
67
70
private static volatile SeleniumManager manager ;
68
-
69
71
private final String managerPath = System .getenv ("SE_MANAGER_PATH" );
70
72
private Path binary = managerPath == null ? null : Paths .get (managerPath );
73
+ private String seleniumManagerVersion ;
74
+ private boolean binaryInTemporalFolder = false ;
71
75
72
76
/** Wrapper for the Selenium Manager binary. */
73
77
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 );
74
82
if (managerPath == null ) {
75
83
Runtime .getRuntime ()
76
84
.addShutdownHook (
77
85
new Thread (
78
86
() -> {
79
- if (binary != null && Files .exists (binary )) {
87
+ if (binaryInTemporalFolder && binary != null && Files .exists (binary )) {
80
88
try {
81
89
Files .delete (binary );
82
90
} catch (IOException e ) {
@@ -161,23 +169,27 @@ private static Result runCommand(Path binary, List<String> arguments) {
161
169
*/
162
170
private synchronized Path getBinary () {
163
171
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
+ }
176
182
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
+ }
178
192
179
- binary = tmpPath .resolve (SELENIUM_MANAGER + extension );
180
- Files .copy (inputStream , binary , REPLACE_EXISTING );
181
193
} catch (Exception e ) {
182
194
throw new WebDriverException ("Unable to obtain Selenium Manager Binary" , e );
183
195
}
@@ -192,35 +204,6 @@ private synchronized Path getBinary() {
192
204
return binary ;
193
205
}
194
206
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
-
224
207
/**
225
208
* Returns the browser binary path when present in the vendor options
226
209
*
@@ -319,4 +302,25 @@ private Level getLogLevel() {
319
302
}
320
303
return level ;
321
304
}
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
+ }
322
326
}
0 commit comments