org.openqa.selenium.grid.node.local.SessionSlot Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of selenium-grid Show documentation
Show all versions of selenium-grid Show documentation
Selenium automates browsers. That's it! What you do with that power is entirely up to you.
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.openqa.selenium.grid.node.local;
import java.io.UncheckedIOException;
import java.util.ServiceLoader;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.StreamSupport;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.ImmutableCapabilities;
import org.openqa.selenium.NoSuchSessionException;
import org.openqa.selenium.RetrySessionRequestException;
import org.openqa.selenium.SessionNotCreatedException;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebDriverInfo;
import org.openqa.selenium.events.EventBus;
import org.openqa.selenium.grid.data.CreateSessionRequest;
import org.openqa.selenium.grid.data.SessionClosedEvent;
import org.openqa.selenium.grid.node.ActiveSession;
import org.openqa.selenium.grid.node.SessionFactory;
import org.openqa.selenium.grid.node.relay.RelaySessionFactory;
import org.openqa.selenium.internal.Either;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.remote.SessionId;
import org.openqa.selenium.remote.http.HttpHandler;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;
public class SessionSlot
implements HttpHandler,
Function>,
Predicate {
private static final Logger LOG = Logger.getLogger(SessionSlot.class.getName());
private final EventBus bus;
private final UUID id;
private final Capabilities stereotype;
private final SessionFactory factory;
private final AtomicBoolean reserved = new AtomicBoolean(false);
private final boolean supportingCdp;
private final boolean supportingBiDi;
private ActiveSession currentSession;
public SessionSlot(EventBus bus, Capabilities stereotype, SessionFactory factory) {
this.bus = Require.nonNull("Event bus", bus);
this.id = UUID.randomUUID();
this.stereotype = ImmutableCapabilities.copyOf(Require.nonNull("Stereotype", stereotype));
this.factory = Require.nonNull("Session factory", factory);
this.supportingCdp = isSlotSupportingCdp(this.stereotype);
this.supportingBiDi = isSlotSupportingBiDi(this.stereotype);
}
public UUID getId() {
return id;
}
public Capabilities getStereotype() {
return stereotype;
}
public void reserve() {
if (reserved.getAndSet(true)) {
throw new IllegalStateException("Attempt to reserve a slot that is already reserved");
}
}
public void release() {
reserved.set(false);
}
public boolean isAvailable() {
return !reserved.get();
}
public ActiveSession getSession() {
if (isAvailable()) {
throw new NoSuchSessionException("Session is not running");
}
return currentSession;
}
public void stop() {
if (isAvailable()) {
return;
}
SessionId id = currentSession.getId();
try {
currentSession.stop();
} catch (Exception e) {
LOG.log(Level.WARNING, "Unable to cleanly close session", e);
}
currentSession = null;
release();
bus.fire(new SessionClosedEvent(id));
LOG.info(String.format("Stopping session %s", id));
}
@Override
public HttpResponse execute(HttpRequest req) throws UncheckedIOException {
if (currentSession == null) {
throw new NoSuchSessionException("No session currently running: " + req.getUri());
}
return currentSession.execute(req);
}
@Override
public boolean test(Capabilities capabilities) {
return factory.test(capabilities);
}
@Override
public Either apply(CreateSessionRequest sessionRequest) {
if (currentSession != null) {
return Either.left(new RetrySessionRequestException("Slot is busy. Try another slot."));
}
if (!test(sessionRequest.getDesiredCapabilities())) {
return Either.left(
new SessionNotCreatedException(
"New session request capabilities do not " + "match the stereotype."));
}
try {
Either possibleSession = factory.apply(sessionRequest);
if (possibleSession.isRight()) {
ActiveSession session = possibleSession.right();
currentSession = session;
return Either.right(session);
} else {
return Either.left(possibleSession.left());
}
} catch (Exception e) {
LOG.log(Level.WARNING, "Unable to create session", e);
return Either.left(new SessionNotCreatedException(e.getMessage()));
}
}
public boolean isSupportingCdp() {
return supportingCdp;
}
public boolean isSupportingBiDi() {
return supportingBiDi;
}
private boolean isSlotSupportingCdp(Capabilities stereotype) {
return StreamSupport.stream(ServiceLoader.load(WebDriverInfo.class).spliterator(), false)
.filter(webDriverInfo -> webDriverInfo.isSupporting(stereotype))
.anyMatch(WebDriverInfo::isSupportingCdp);
}
private boolean isSlotSupportingBiDi(Capabilities stereotype) {
return StreamSupport.stream(ServiceLoader.load(WebDriverInfo.class).spliterator(), false)
.filter(webDriverInfo -> webDriverInfo.isSupporting(stereotype))
.anyMatch(WebDriverInfo::isSupportingBiDi);
}
public boolean hasRelayFactory() {
return factory instanceof RelaySessionFactory;
}
public boolean isRelayServiceUp() {
return hasRelayFactory() && ((RelaySessionFactory) factory).isServiceUp();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy