Skip to content

Commit a01fb62

Browse files
asmundakjleyba
authored andcommitted
Replace HashBiMap with thread-safe and lighter-weight ConcurrentHashMap (#3151)
HashBiMap is not thread safe. And its ability to map back from value to key is used in a single place and can be easily replaced.
1 parent a4402d6 commit a01fb62

1 file changed

Lines changed: 14 additions & 14 deletions

File tree

java/client/src/org/openqa/selenium/remote/http/AbstractHttpCommandCodec.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,7 @@
109109
import com.google.common.base.Objects;
110110
import com.google.common.base.Splitter;
111111
import com.google.common.base.Strings;
112-
import com.google.common.collect.BiMap;
113-
import com.google.common.collect.FluentIterable;
114-
import com.google.common.collect.HashBiMap;
112+
115113
import com.google.common.collect.ImmutableList;
116114
import com.google.common.collect.Maps;
117115

@@ -123,6 +121,7 @@
123121
import org.openqa.selenium.remote.JsonToBeanConverter;
124122
import org.openqa.selenium.remote.SessionId;
125123

124+
import java.util.concurrent.ConcurrentHashMap;
126125
import java.util.HashMap;
127126
import java.util.List;
128127
import java.util.Map;
@@ -136,7 +135,7 @@ public abstract class AbstractHttpCommandCodec implements CommandCodec<HttpReque
136135
private static final Splitter PATH_SPLITTER = Splitter.on('/').omitEmptyStrings();
137136
private static final String SESSION_ID_PARAM = "sessionId";
138137

139-
private final BiMap<String, CommandSpec> nameToSpec = HashBiMap.create();
138+
private final ConcurrentHashMap<String, CommandSpec> nameToSpec = new ConcurrentHashMap();
140139
private final Map<String, String> aliases = new HashMap<>();
141140
private final BeanToJsonConverter beanToJsonConverter = new BeanToJsonConverter();
142141
private final JsonToBeanConverter jsonToBeanConverter = new JsonToBeanConverter();
@@ -281,18 +280,20 @@ public Command decode(final HttpRequest encodedCommand) {
281280
final String path = Strings.isNullOrEmpty(encodedCommand.getUri())
282281
? "/" : encodedCommand.getUri();
283282
final ImmutableList<String> parts = ImmutableList.copyOf(PATH_SPLITTER.split(path));
284-
List<CommandSpec> matchingSpecs = FluentIterable.from(nameToSpec.inverse().keySet())
285-
.filter(spec -> {
286-
return spec.isFor(encodedCommand.getMethod(), parts);
287-
})
288-
.toSortedList((a, b) -> a.pathSegments.size() - b.pathSegments.size());
289-
290-
if (matchingSpecs.isEmpty()) {
283+
int minPathLength = Integer.MAX_VALUE;
284+
CommandSpec spec = null;
285+
String name = null;
286+
for (Map.Entry<String, CommandSpec> nameValue : nameToSpec.entrySet()) {
287+
if ((nameValue.getValue().pathSegments.size() < minPathLength)
288+
&& nameValue.getValue().isFor(encodedCommand.getMethod(), parts)) {
289+
name = nameValue.getKey();
290+
spec = nameValue.getValue();
291+
}
292+
}
293+
if (name == null) {
291294
throw new UnsupportedCommandException(
292295
encodedCommand.getMethod() + " " + encodedCommand.getUri());
293296
}
294-
CommandSpec spec = matchingSpecs.get(0);
295-
296297
Map<String, Object> parameters = Maps.newHashMap();
297298
spec.parsePathParameters(parts, parameters);
298299

@@ -303,7 +304,6 @@ public Command decode(final HttpRequest encodedCommand) {
303304
parameters.putAll(tmp);
304305
}
305306

306-
String name = nameToSpec.inverse().get(spec);
307307
SessionId sessionId = null;
308308
if (parameters.containsKey(SESSION_ID_PARAM)) {
309309
String id = (String) parameters.remove(SESSION_ID_PARAM);

0 commit comments

Comments
 (0)