package com.aimmac23.hub.proxy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openqa.grid.common.RegistrationRequest;
import org.openqa.selenium.remote.DesiredCapabilities;
/**
* Some default configurations may try to register nodes that can run more than one browser in parallel. This is
* a supported feature by Selenium, but doesn't work when trying to take a video of a running test (which will
* only really record the topmost window).
*
* This class re-writes incoming registration requests to remove any instances of parallelism.
*
* Selenium 3 introduced a small number of incompatible changes, so this class tries to support Selenium 2 as well
* by using reflection to do its work.
*
* @author Alasdair Macmillan
*
*/
public final class RegistrationRequestCorrector {
private static final String MAX_SESSION_WARNING = "Reducing 'maxSession' value to 1: Video node does not support concurrent sessions";
private static final Logger log = Logger.getLogger(RegistrationRequestCorrector.class.getName());
public static RegistrationRequest correctRegistrationRequest(RegistrationRequest request) {
try {
new V3ConfigurationCorrector().fixupConfig(request);
}
catch(Exception e) {
// not working? its probably running against Selenium v2, so try that next
try {
new V2ConfigurationCorrector().fixupConfig(request);
}
catch(Exception e2) {
// if both code paths have failed, then the Selenium project has introduced incompatible code changes, so get the user to report
// the original problem (discarding legacy exceptions)
log.log(Level.SEVERE, "Couldn't correct Selenium registration request - this code may need recompiling to support new code changes. "
+ "Please file a bug against the selenium-video-node project, and attach this stacktrace.", e);
// this may later prove to be slightly unexpected behaviour, but continue with the original registration request,
// and hope that the config is OK.
}
}
return request;
}
public interface ConfigurationCorrector {
public void fixupConfig(RegistrationRequest request) throws Exception;
}
private static class V3ConfigurationCorrector implements ConfigurationCorrector {
@SuppressWarnings("unchecked")
@Override
public void fixupConfig(RegistrationRequest request) throws Exception {
Method getConfigurationMethod = request.getClass().getMethod("getConfiguration");
Object configuration = getConfigurationMethod.invoke(request);
Field maxSessionField = configuration.getClass().getField("maxSession");
Integer maxSessions = (Integer) maxSessionField.get(configuration);
if(maxSessions != null && maxSessions != 1) {
log.warning(MAX_SESSION_WARNING);
maxSessionField.set(configuration, Integer.valueOf(1));
}
correctCapabilities((Collection<DesiredCapabilities>) configuration.getClass().getField("capabilities").get(configuration));
}
}
private static class V2ConfigurationCorrector implements ConfigurationCorrector {
@SuppressWarnings("unchecked")
@Override
public void fixupConfig(RegistrationRequest request) throws Exception {
Method getConfigurationMethod = request.getClass().getMethod("getConfigAsInt", String.class, int.class);
int maxSessions = (Integer) getConfigurationMethod.invoke(request, "maxSession", Integer.valueOf(1));
if(maxSessions != 1) {
log.warning(MAX_SESSION_WARNING);
Map<String, Object> configuration = (Map<String, Object>) request.getClass().getMethod("getConfiguration").invoke(request);
configuration.put("maxSession", Integer.valueOf(1));
}
correctCapabilities((Collection<DesiredCapabilities>) request.getClass().getMethod("getCapabilities").invoke(request));
}
}
private static void correctCapabilities(Collection<DesiredCapabilities> capabilities) {
for(DesiredCapabilities caps : capabilities) {
Object maxInstances = caps.getCapability(RegistrationRequest.MAX_INSTANCES);
caps.setCapability(RegistrationRequest.MAX_INSTANCES, "1");
if(maxInstances != null && !"1".equals(maxInstances)) {
log.warning("Reducing " + RegistrationRequest.MAX_INSTANCES + " for browser " + caps.getBrowserName() +
" to 1: Video node does not support concurrent sessions");
}
}
}
}