All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.rationaleemotions.proxy.GhostProxy Maven / Gradle / Ivy

The newest version!
package com.rationaleemotions.proxy;

import com.google.common.collect.MapMaker;
import com.rationaleemotions.config.ConfigReader;
import com.rationaleemotions.internal.ProxiedTestSlot;
import com.rationaleemotions.server.SpawnedServer;
import java.util.HashMap;
import org.openqa.grid.common.RegistrationRequest;
import org.openqa.grid.common.SeleniumProtocol;
import org.openqa.grid.common.exception.GridException;
import org.openqa.grid.internal.GridRegistry;
import org.openqa.grid.internal.TestSession;
import org.openqa.grid.internal.TestSlot;
import org.openqa.grid.selenium.proxy.DefaultRemoteProxy;
import org.openqa.grid.web.servlet.handler.RequestType;
import org.openqa.grid.web.servlet.handler.SeleniumBasedRequest;
import org.openqa.selenium.remote.CapabilityType;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

import static org.openqa.grid.web.servlet.handler.RequestType.START_SESSION;

/**
 * Represents a simple {@link DefaultRemoteProxy} implementation that relies on spinning off a server
 * and then routing the session traffic to the spawned server.
 */
public class GhostProxy extends DefaultRemoteProxy {
    private final AtomicInteger counter = new AtomicInteger(0);


    private interface Marker {
    }

    private static final Logger LOG = Logger.getLogger(Marker.class.getEnclosingClass().getName());
    private Map servers = new MapMaker().initialCapacity(500).makeMap();

    public GhostProxy(RegistrationRequest request, GridRegistry registry) {
        super(request, registry);
        LOG.info("Maximum sessions supported: " + ConfigReader.getInstance().getMaxSession());
    }

    @Override
    public TestSlot createTestSlot(SeleniumProtocol protocol, Map capabilities) {
        return new ProxiedTestSlot(this, protocol, capabilities);
    }

    @Override
    public TestSession getNewSession(Map requestedCapability) {
    	
    	 LOG.fine(String.format("Trying to create a new session on node %s", this));

        if (!hasCapability(requestedCapability)) {
        	LOG.fine("Node " + this + " has no matching capability");
          return null;
        }

        if (counter.get() > ConfigReader.getInstance().getMaxSession()) {
            LOG.info("Waiting for remote nodes to be available");
            return null;
        }

        // any slot left for the given app ?
        for (TestSlot testslot : getTestSlots()) {
            TestSession session = testslot.getNewSession(requestedCapability);
            if (session != null) {
                return session;
            }
        }
        return null;
    }
    
    @Override
    public void beforeRelease(TestSession session) {
        // release the resources remotely if the remote started a browser.
        if (session.getExternalKey() == null) {
          return;
        }
        boolean ok = session.sendDeleteSessionRequest();
        if (ok && processTestSession(session)) {
        	stopServerForTestSession(session);
		}
        if (!ok) {
          LOG.warning("Error releasing the resources on timeout for session " + session);
        }
      }

    @Override
    public void beforeCommand(TestSession session, HttpServletRequest request, HttpServletResponse response) {
        RequestType type = identifyRequestType(request);
        if (type == START_SESSION) {
                if (processTestSession(session)) {
                    startServerForTestSession(session);
                } else {
                	LOG.info("Missing target mapping. Available mappings are: " + ConfigReader.getInstance().getMapping());
                }
        }
        super.beforeCommand(session, request, response);
    }

    @Override
    public void afterSession(TestSession session) {
        	if (processTestSession(session)) {
        	    stopServerForTestSession(session);
        	}
      }

    @Override
    public Map getProxyStatus() {
        return new HashMap<>();
    }

    private RequestType identifyRequestType(HttpServletRequest request) {
        return SeleniumBasedRequest.createFromRequest(request, getRegistry()).extractRequestType();
    }

    private boolean processTestSession(TestSession session) {
        Map requestedCapabilities = session.getRequestedCapabilities();
        String browser = (String) requestedCapabilities.get(CapabilityType.BROWSER_NAME);
        return ConfigReader.getInstance().getMapping().containsKey(browser);
    }

    private void startServerForTestSession(TestSession session) {
        try {
            SpawnedServer server = SpawnedServer.spawnInstance(session);
            String key = "http://" + server.getHost() + ":" + server.getPort();
            URL url = new URL(key);
            servers.put(key, server);
            ((ProxiedTestSlot) session.getSlot()).setRemoteURL(url);
            if (LOG.isLoggable(Level.INFO)) {
                LOG.info(String.format("Forwarding session to: %s", session.getSlot().getRemoteURL()));
                LOG.info(String.format("Counter value after incrementing: %d", counter.incrementAndGet()));
            }
        } catch (Exception e) {
            throw new GridException(e.getMessage(), e);
        }
    }

    private void stopServerForTestSession(TestSession session) {
        URL url = session.getSlot().getRemoteURL();
        String key = String.format("%s://%s:%d", url.getProtocol(), url.getHost(), url.getPort());
        SpawnedServer localServer = servers.get(key);
        if (localServer != null) {
            localServer.shutdown();
            servers.remove(key);
            LOG.info(String.format("Counter value after decrementing: %d", counter.decrementAndGet()));
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy