Skip to content

Commit 5bf5a90

Browse files
committed
Add the /file endpoint to the new server
With a test, and everything. This change requires us to track a `TemporaryFileSystem` per `ActiveSession` bringing us ever closer to have an equivalence with `Session`.
1 parent afdf13b commit 5bf5a90

File tree

9 files changed

+256
-7
lines changed

9 files changed

+256
-7
lines changed

java/server/src/org/openqa/selenium/remote/server/ActiveSession.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.openqa.selenium.remote.server;
1919

20+
import org.openqa.selenium.io.TemporaryFilesystem;
2021
import org.openqa.selenium.remote.Dialect;
2122
import org.openqa.selenium.remote.SessionId;
2223

@@ -35,5 +36,7 @@ public interface ActiveSession extends CommandHandler {
3536
*/
3637
Map<String, Object> getCapabilities();
3738

39+
TemporaryFilesystem getFileSystem();
40+
3841
void stop();
3942
}

java/server/src/org/openqa/selenium/remote/server/ActiveSessions.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.common.cache.CacheBuilder;
2222
import com.google.common.cache.RemovalListener;
2323

24+
import org.openqa.selenium.io.TemporaryFilesystem;
2425
import org.openqa.selenium.remote.SessionId;
2526
import org.openqa.selenium.remote.server.log.LoggingManager;
2627
import org.openqa.selenium.remote.server.log.PerSessionLogHandler;
@@ -44,7 +45,13 @@ public class ActiveSessions {
4445
public ActiveSessions(long inactiveSessionTimeout, TimeUnit unit) {
4546
RemovalListener<SessionId, ActiveSession> listener = notification -> {
4647
ActiveSession session = notification.getValue();
47-
listeners.forEach(l -> l.onStop(session));
48+
listeners.forEach(l -> {
49+
try {
50+
l.onStop(session);
51+
} catch (Exception e) {
52+
LOG.log(Level.WARNING, "Caught exception closing session: " + session.getId(), e);
53+
}
54+
});
4855
session.stop();
4956
};
5057

@@ -68,6 +75,15 @@ public void onStop(ActiveSession session) {
6875
logHandler.removeSessionLogs(session.getId());
6976
}
7077
});
78+
79+
addListener(new ActiveSessionListener() {
80+
@Override
81+
public void onStop(ActiveSession session) {
82+
TemporaryFilesystem filesystem = session.getFileSystem();
83+
filesystem.deleteTemporaryFiles();
84+
filesystem.deleteBaseDir();
85+
}
86+
});
7187
}
7288

7389
public void put(ActiveSession session) {

java/server/src/org/openqa/selenium/remote/server/AllHandlers.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@
2828

2929
import org.openqa.selenium.remote.SessionId;
3030
import org.openqa.selenium.remote.http.HttpMethod;
31+
import org.openqa.selenium.remote.server.commandhandler.GetAllSessions;
3132
import org.openqa.selenium.remote.server.commandhandler.GetLogTypes;
3233
import org.openqa.selenium.remote.server.commandhandler.GetLogsOfType;
3334
import org.openqa.selenium.remote.server.commandhandler.NoHandler;
3435
import org.openqa.selenium.remote.server.commandhandler.NoSessionHandler;
3536
import org.openqa.selenium.remote.server.commandhandler.Status;
36-
import org.openqa.selenium.remote.server.commandhandler.GetAllSessions;
37+
import org.openqa.selenium.remote.server.commandhandler.UploadFile;
3738

3839
import java.lang.reflect.Constructor;
3940
import java.util.List;
@@ -67,7 +68,9 @@ public AllHandlers(ActiveSessions allSessions) {
6768
),
6869
HttpMethod.POST, ImmutableList.of(
6970
handler("/session", BeginSession.class),
70-
handler("/session/{sessionId}/log", GetLogsOfType.class)
71+
handler("/session/{sessionId}/file", UploadFile.class),
72+
handler("/session/{sessionId}/log", GetLogsOfType.class),
73+
handler("/session/{sessionId}/se/file", UploadFile.class)
7174
));
7275
}
7376

@@ -123,6 +126,7 @@ private <H extends CommandHandler> Function<String, CommandHandler> handler(
123126
ActiveSession session = allSessions.get(id);
124127
if (session != null) {
125128
args.add(session);
129+
args.add(session.getFileSystem());
126130
}
127131
}
128132
match.getParameters().entrySet().stream()

java/server/src/org/openqa/selenium/remote/server/InMemorySession.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static java.nio.charset.StandardCharsets.UTF_8;
2222

2323
import com.google.common.base.Preconditions;
24+
import com.google.common.base.StandardSystemProperty;
2425
import com.google.common.collect.ImmutableMap;
2526
import com.google.common.collect.ImmutableSet;
2627
import com.google.gson.Gson;
@@ -38,6 +39,7 @@
3839
import org.openqa.selenium.remote.http.HttpResponse;
3940

4041
import java.io.BufferedReader;
42+
import java.io.File;
4143
import java.io.IOException;
4244
import java.io.InputStream;
4345
import java.io.InputStreamReader;
@@ -60,6 +62,7 @@ class InMemorySession implements ActiveSession {
6062
private final Map<String, Object> capabilities;
6163
private final SessionId id;
6264
private final Dialect downstream;
65+
private final TemporaryFilesystem filesystem;
6366
private final JsonHttpCommandHandler handler;
6467

6568
private InMemorySession(WebDriver driver, Capabilities capabilities, Dialect downstream)
@@ -80,6 +83,9 @@ private InMemorySession(WebDriver driver, Capabilities capabilities, Dialect dow
8083
this.id = new SessionId(UUID.randomUUID().toString());
8184
this.downstream = Preconditions.checkNotNull(downstream);
8285

86+
File tempRoot = new File(StandardSystemProperty.JAVA_IO_TMPDIR.value(), id.toString());
87+
this.filesystem = TemporaryFilesystem.getTmpFsBasedOn(tempRoot);
88+
8389
this.handler = new JsonHttpCommandHandler(
8490
new PretendDriverSessions(),
8591
LOG);
@@ -110,6 +116,11 @@ public Map<String, Object> getCapabilities() {
110116
return capabilities;
111117
}
112118

119+
@Override
120+
public TemporaryFilesystem getFileSystem() {
121+
return filesystem;
122+
}
123+
113124
@Override
114125
public void stop() {
115126
driver.quit();

java/server/src/org/openqa/selenium/remote/server/ServicedSession.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@
2020

2121
import static java.util.concurrent.TimeUnit.SECONDS;
2222

23+
import com.google.common.base.StandardSystemProperty;
24+
2325
import org.openqa.selenium.SessionNotCreatedException;
26+
import org.openqa.selenium.io.TemporaryFilesystem;
2427
import org.openqa.selenium.net.PortProber;
25-
import org.openqa.selenium.remote.Command;
2628
import org.openqa.selenium.remote.CommandCodec;
2729
import org.openqa.selenium.remote.Dialect;
28-
import org.openqa.selenium.remote.DriverCommand;
2930
import org.openqa.selenium.remote.ProtocolHandshake;
3031
import org.openqa.selenium.remote.Response;
3132
import org.openqa.selenium.remote.ResponseCodec;
@@ -41,6 +42,7 @@
4142
import org.openqa.selenium.remote.internal.ApacheHttpClient;
4243
import org.openqa.selenium.remote.service.DriverService;
4344

45+
import java.io.File;
4446
import java.io.IOException;
4547
import java.io.InputStream;
4648
import java.lang.reflect.Method;
@@ -55,10 +57,11 @@ class ServicedSession implements ActiveSession {
5557

5658
private final DriverService service;
5759
private final SessionId id;
58-
private Dialect downstream;
59-
private Dialect upstream;
60+
private final Dialect downstream;
61+
private final Dialect upstream;
6062
private final SessionCodec codec;
6163
private final Map<String, Object> capabilities;
64+
private final TemporaryFilesystem filesystem;
6265

6366
public ServicedSession(
6467
DriverService service,
@@ -73,6 +76,9 @@ public ServicedSession(
7376
this.codec = codec;
7477
this.id = id;
7578
this.capabilities = capabilities;
79+
80+
File tempRoot = new File(StandardSystemProperty.JAVA_IO_TMPDIR.value(), id.toString());
81+
this.filesystem = TemporaryFilesystem.getTmpFsBasedOn(tempRoot);
7682
}
7783

7884

@@ -101,6 +107,11 @@ public Map<String, Object> getCapabilities() {
101107
return capabilities;
102108
}
103109

110+
@Override
111+
public TemporaryFilesystem getFileSystem() {
112+
return filesystem;
113+
}
114+
104115
@Override
105116
public void stop() {
106117
// Try and kill the running session. Both W3C and OSS use the same quit endpoint
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.remote.server.commandhandler;
19+
20+
import com.google.gson.Gson;
21+
22+
import org.openqa.selenium.WebDriverException;
23+
import org.openqa.selenium.io.Zip;
24+
import org.openqa.selenium.remote.ErrorCodes;
25+
import org.openqa.selenium.remote.Response;
26+
import org.openqa.selenium.remote.http.HttpRequest;
27+
import org.openqa.selenium.remote.http.HttpResponse;
28+
import org.openqa.selenium.remote.server.ActiveSession;
29+
import org.openqa.selenium.remote.server.CommandHandler;
30+
31+
import java.io.File;
32+
import java.io.IOException;
33+
import java.util.Map;
34+
import java.util.Objects;
35+
36+
public class UploadFile implements CommandHandler {
37+
38+
private final Gson gson;
39+
private final ActiveSession session;
40+
41+
public UploadFile(Gson gson, ActiveSession session) {
42+
this.gson = Objects.requireNonNull(gson);
43+
this.session = Objects.requireNonNull(session);
44+
}
45+
46+
@Override
47+
public void execute(HttpRequest req, HttpResponse resp) throws IOException {
48+
Map<?, ?> args = gson.fromJson(req.getContentString(), Map.class);
49+
String file = (String) args.get("file");
50+
51+
File tempDir = session.getFileSystem().createTempDir("upload", "file");
52+
53+
Zip.unzip(file, tempDir);
54+
// Select the first file
55+
File[] allFiles = tempDir.listFiles();
56+
57+
Response response = new Response(session.getId());
58+
if (allFiles == null || allFiles.length != 1) {
59+
response.setStatus(ErrorCodes.UNHANDLED_ERROR);
60+
response.setValue(new WebDriverException(
61+
"Expected there to be only 1 file. There were: " +
62+
(allFiles == null ? 0 : allFiles.length)));
63+
} else {
64+
response.setStatus(ErrorCodes.SUCCESS);
65+
response.setValue(allFiles[0].getAbsolutePath());
66+
}
67+
68+
session.getDownstreamDialect().getResponseCodec().encode(() -> resp, response);
69+
}
70+
}

java/server/test/org/openqa/selenium/remote/server/BUCK

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ java_test(name = 'small-tests',
1515
java_library(name = 'tests',
1616
srcs = glob([
1717
'*.java',
18+
'commandhandler/*.java',
1819
'handler/**/*.java',
1920
'rest/*.java',
2021
'xdrpc/*.java',

java/server/test/org/openqa/selenium/remote/server/RemoteServerTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
SyntheticNewSessionPayloadTest.class,
4646
TeeReaderTest.class,
4747
UploadFileTest.class,
48+
org.openqa.selenium.remote.server.commandhandler.UploadFileTest.class,
4849
ConfigureTimeoutTest.class,
4950
UrlTemplateTest.class,
5051
UtilsTest.class

0 commit comments

Comments
 (0)