com.rmn.qa.servlet.BmpServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.rmn.qa.servlet.BmpServlet.java

Source

/*
 * Copyright (C) 2014 RetailMeNot, Inc.
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 */
package com.rmn.qa.servlet;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.openqa.grid.internal.Registry;
import org.openqa.grid.web.servlet.RegistryBasedServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.io.ByteStreams;
import com.rmn.qa.AutomationConstants;
import com.rmn.qa.servlet.BmpProxyRegistry.ProxyHolder;

import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.proxy.CaptureType;
import net.lightbody.bmp.proxy.auth.AuthType;

/**
 * Servlet to start instance of BrowserMobProxy for authentication
 */
public class BmpServlet extends RegistryBasedServlet {

    private static final long serialVersionUID = 8484071790930378855L;
    private static final Logger log = LoggerFactory.getLogger(BmpServlet.class);

    private static String coreVersion;
    private static String coreRevision;

    /**
     * Constructs a servlet with default functionality
     */
    public BmpServlet() {
        this(null);
    }

    /**
     * Constructs a servlet with the specified registry
     * 
     * @param registry
     */
    public BmpServlet(Registry registry) {
        super(registry);
        getVersion();
    }

    /**
     * Stops and cleans up the proxy.
     * 
     * Content should contain the uuid in a json content
     * 
     * expects a parameter passed in query string of "uuid"
     * 
     * @return Responds with a 202 Accepted if the proxy is removed or does not exist.
     * @return Responds with a 400 Bad Request if the uuid is not specified or there is no reason to create the proxy
     *         (see above).
     */
    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String uuid = request.getParameter("uuid");
        if (StringUtils.isBlank(uuid)) {
            log.error("uuid not  present");
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "uuid must be specified in json");
            return;
        }
        log.info("Stopping proxy with uuid " + uuid);
        BmpProxyRegistry.getInstance().stopProxy(uuid);
        response.setStatus(HttpServletResponse.SC_ACCEPTED);
    }

    /**
     * Starts a new BrowserMobProxy. Note that either recordHar must be set to true or some credentials are provided or
     * a proxy will not be created.
     *
     * Content should be a json object in the following form.
     * 
     * <pre>
    {
      "uuid": "my-uuid",//required
      "recordHar" : "true",
      "credentials": [{
        "domain" : "",
        "username" : "",
        "password" : "",
      }]
    }
     * </pre>
     * 
     * @return Responds with a 201 Created and the url ins the Location header if proxy is created.
     * 
     * @return Responds with a 400 Bad Request if the uuid is not specified or there is no reason to create the proxy
     *         (see above).
     * 
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // if (request.getContentType().equals("application/json"))
        try {
            JsonNode input = getNodeFromRequest(request);
            String uuid = getJsonString(input, "uuid");
            if (StringUtils.isBlank(uuid)) {
                log.error("uuid not  present");
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "uuid must be specified in json");
                return;
            }

            JsonNode harRecording = input.get("recordHar");
            boolean recorrdingHar = harRecording != null && harRecording.asBoolean(false);
            BrowserMobProxy proxy = null;
            if (recorrdingHar) {
                proxy = new BrowserMobProxyServer();
                Set<CaptureType> set = new HashSet<CaptureType>(CaptureType.getRequestCaptureTypes());
                set.addAll(CaptureType.getResponseCaptureTypes());
                set.removeAll(CaptureType.getBinaryContentCaptureTypes());
                proxy.setHarCaptureTypes(set);
            }
            JsonNode creds = input.get("credentials");
            if (creds != null) {
                if (proxy == null) {
                    proxy = new BrowserMobProxyServer();
                }
                if (creds.isArray()) {
                    ArrayNode array = (ArrayNode) creds;
                    Iterator<JsonNode> elements = array.elements();
                    while (elements.hasNext()) {
                        JsonNode cred = elements.next();
                        addCredentials(proxy, cred);
                    }
                } else {
                    addCredentials(proxy, creds);
                }
            }
            if (proxy == null) {
                log.error("Nothing for proxy to do");
                response.sendError(HttpServletResponse.SC_BAD_REQUEST,
                        "Har recording or credentials not specified. There is no reason to start a proxy.");
                return;
            } else {
                String localhostname;
                // Try and get the IP address from the system property
                String runTimeHostName = System.getProperty(AutomationConstants.IP_ADDRESS);
                try {
                    if (runTimeHostName == null) {
                        log.warn("Host name could not be determined from system property.");
                    }
                    localhostname = (runTimeHostName != null) ? runTimeHostName
                            : InetAddress.getLocalHost().getHostName();
                } catch (UnknownHostException e) {
                    log.error("Error parsing out host name", e);
                    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                            "Host name could not be determined: " + e);
                    return;
                }

                // build the response
                BmpProxyRegistry.getInstance().addProxy(uuid, proxy);
                proxy.start();
                response.setStatus(HttpServletResponse.SC_CREATED);
                response.setHeader("Location", localhostname + ":" + proxy.getPort());
            }
        } catch (Exception e) {
            log.error("Error starting proxy: " + e, e);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error starting proxy: " + e);
        }
    }

    /**
     * 
     * {@inheritDoc}
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        response.setStatus(200);

        StringBuilder builder = new StringBuilder();

        builder.append("<html>");
        builder.append("<head>");

        builder.append("<title>BrowserMobProxy instances</title>");

        builder.append("</head>");

        builder.append("<body>");
        builder.append("<H1>Grid Hub ");
        builder.append(coreVersion).append(coreRevision);
        builder.append("</H1>");
        Map<String, ProxyHolder> proxyMap = BmpProxyRegistry.getInstance().getProxyMap();
        DateFormat df = DateFormat.getDateTimeInstance();
        if (proxyMap.isEmpty()) {
            builder.append("No BrowserMobProxy instances currently running.");
        } else {
            for (Entry<String, ProxyHolder> entry : proxyMap.entrySet()) {
                StringBuilder localBuilder = new StringBuilder();
                ProxyHolder holder = entry.getValue();
                String uuid = entry.getKey();
                localBuilder.append("<fieldset>");
                localBuilder.append("<legend>BrowserMobProxy for test id ").append(uuid).append("</legend>");
                localBuilder.append("listening on ").append(holder.getProxy().getPort()).append("<br/>");
                localBuilder.append("started at ").append(df.format(new Date(holder.getCreated()))).append("<br/>");
                localBuilder.append("</fieldset>");
                builder.append(localBuilder.toString());
            }
        }
        try (InputStream in = new ByteArrayInputStream(builder.toString().getBytes("UTF-8"));) {
            ByteStreams.copy(in, response.getOutputStream());
        } finally {
            response.flushBuffer();
        }
    }

    private JsonNode getNodeFromRequest(HttpServletRequest request) throws IOException {
        String jsonString = null;
        ServletInputStream in = null;
        try {
            in = request.getInputStream();
            jsonString = IOUtils.toString(in, "utf-8");
        } finally {
            IOUtils.closeQuietly(in);
        }
        ObjectMapper mapper = new ObjectMapper();
        JsonNode input = mapper.readTree(jsonString);
        return input;
    }

    private void addCredentials(BrowserMobProxy proxy, JsonNode creds) {
        String domain = getJsonString(creds, "domain");
        String user = getJsonString(creds, "username");
        String pass = getJsonString(creds, "password");
        proxy.autoAuthorization(domain, user, pass, AuthType.BASIC);

    }

    private String getJsonString(JsonNode node, String key) {
        String ret = null;
        JsonNode child = node.get(key);
        if (child != null) {
            ret = child.asText();
        }
        return ret;
    }

    private void getVersion() {
        final Properties p = new Properties();

        InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("VERSION.txt");
        if (stream == null) {
            log.error("Couldn't determine version number");
            return;
        }
        try {
            p.load(stream);
        } catch (IOException e) {
            log.error("Cannot load version from VERSION.txt" + e.getMessage());
        }
        coreVersion = p.getProperty("selenium.core.version");
        coreRevision = p.getProperty("selenium.core.revision");
        if (coreVersion == null) {
            log.error("Cannot load selenium.core.version from VERSION.txt");
        }
    }

}