Package com.google.jstestdriver.server.handlers

Source Code of com.google.jstestdriver.server.handlers.BrowserQueryResponseHandler

/*
* Copyright 2008 Google Inc.
*
* Licensed 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 com.google.jstestdriver.server.handlers;

import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.google.inject.Inject;
import com.google.jstestdriver.CapturedBrowsers;
import com.google.jstestdriver.Command;
import com.google.jstestdriver.FileInfo;
import com.google.jstestdriver.FileResult;
import com.google.jstestdriver.FileSource;
import com.google.jstestdriver.JsonCommand;
import com.google.jstestdriver.LoadedFiles;
import com.google.jstestdriver.Response;
import com.google.jstestdriver.Response.ResponseType;
import com.google.jstestdriver.SlaveBrowser;
import com.google.jstestdriver.protocol.BrowserLog;
import com.google.jstestdriver.protocol.BrowserStreamAcknowledged;
import com.google.jstestdriver.requesthandlers.RequestHandler;

import org.mortbay.jetty.MimeTypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;

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


/**
* @author jeremiele@google.com (Jeremie Lenfant-Engelmann)
*/
class BrowserQueryResponseHandler implements RequestHandler {
  private static final Logger logger =
      LoggerFactory.getLogger(BrowserQueryResponseHandler.class);

  private final Gson gson = new Gson();

  private final HttpServletRequest request;
  private final HttpServletResponse response;
  private final CapturedBrowsers browsers;
  // TODO(corysmith): factor out a streaming session class.
  private final ConcurrentMap<SlaveBrowser, List<String>> streamedResponses;

  @Inject
  public BrowserQueryResponseHandler(
      HttpServletRequest request,
      HttpServletResponse response,
      CapturedBrowsers browsers,
      ConcurrentMap<SlaveBrowser, List<String>> streamedResponses) {
    this.request = request;
    this.response = response;
    this.browsers = browsers;
    this.streamedResponses = streamedResponses;
  }

  @Override
  public void handleIt() throws IOException {
    logger.trace("Browser Query Post:\n\tpath:{}\n\tresponse:{}\n\tdone:{}\n\tresponseId:{}",
        new Object[] {
          request.getPathInfo().substring(1),
          request.getParameter("response"),
          request.getParameter("done"),
          request.getParameter("responseId")
        });

    response.setContentType(MimeTypes.TEXT_JSON_UTF_8);
    service(request.getPathInfo().substring(1),
            request.getParameter("response"),
            request.getParameter("done"),
            request.getParameter("responseId"),
            response.getWriter());
  }

  public void service(String id,
                      String response,
                      String done,
                      String responseId,
                      PrintWriter writer) {
    SlaveBrowser browser = browsers.getBrowser(id);

    if (browser != null) {
      boolean isLast = Boolean.parseBoolean(done);
      try {
        serviceBrowser(response, isLast, responseId, writer, browser);
      } catch (JsonParseException e) {
        writer.print(gson.toJson(new JsonCommand(JsonCommand.CommandType.STOP, null)));
        writer.flush();
        throw new RuntimeException("Unable to parse: " + response, e);
      }
    } else {
      // TODO(corysmith): handle this better.
      logger.error("Unknown browser {} with response {}.\n Known {}", new Object[]{id, response, browsers.getSlaveBrowsers()});
      writer.print(gson.toJson(new JsonCommand(JsonCommand.CommandType.STOP, Lists.newArrayList("Stopping due to missing browser."))));
      try {
        Thread.sleep(1000); // pause to make sure the browser doesn't spin.
      } catch (InterruptedException e) {
       
      }
    }
    writer.flush();
  }

  private void serviceBrowser(String response, Boolean done, String responseId, PrintWriter writer,
      SlaveBrowser browser) throws JsonParseException {
    addResponseId(responseId, browser);
    browser.heartBeat();
    Command command = null;
    if (isResponseValid(response)) {
      Response res = gson.fromJson(response, Response.class);
      logger.trace("response type: " +  res.getResponseType());
      // TODO (corysmith): Replace this with polymorphism,
      // using the response type to create disposable actions.
      switch (res.getResponseType()) {
        case BROWSER_READY:
          handleFileLoadResult(browser, res);
          // TODO(corysmith): Move the loading of files to a browser into the
          // server
          browser.addResponse(
              new Response(ResponseType.FILE_LOAD_RESULT.toString(), res.getResponse(), browser
                  .getBrowserInfo(), "", res.getExecutionTime()), false);
          browser.ready();
          break;
        case FILE_LOAD_RESULT:
          handleFileLoadResult(browser, res);
          browser.addResponse(res, done);
          break;
        case NOOP:
          break;
        case LOG:
          BrowserLog log = gson.fromJson(res.getResponse(), res.getGsonType());
          if (log.getLevel() == 1000) {
            logger.info("Error in browser: " + res.toString());
          } else {
            logger.info("Message from the browser: " + res.toString());
          }
          browser.addResponse(res, done);
          break;
        // reset the browsers fileset.
        case RESET_RESULT:
          browser.resetFileSet();
          logger.debug("Clearing fileset for {}", browser);
          handleFileLoadResult(browser, res);
          // queue the load results for the next command to be run.
          browser.addResponse(
              new Response(ResponseType.FILE_LOAD_RESULT.toString(), res.getResponse(), browser
                  .getBrowserInfo(), "", res.getExecutionTime()), false);
          browser.addResponse(res, done);
          break;
        case UNKNOWN:
          logger.error("Recieved Unknown: " + response);
          browser.addResponse(res, done);
          break;
        case BROWSER_PANIC:
          logger.debug("Browser panic for {}", res.toString());
        default:
          browser.addResponse(res, done);
          break;
      }
      logger.trace("Received:\n done: {} \n res:\n {}\n", new Object[] {done, res});
    }
    if (isResponseIdValid(responseId) && !done && !isResponseValid(response)) {
      logger.trace("Streaming query for ids {} from {}", streamedResponses.get(browser), browser);
    }
    // TODO(corysmith): What do we do?
    if (!isResponseValid(response) && done && browser.isCommandRunning()) {
      logger.error("Streaming ending, but no response sent for {} while running {}",
          browser,
          browser.getCommandRunning());
    }
    // TODO(corysmith): Refactoring the streaming into a separate layer.
    if (!done) { // we are still streaming, so we respond with the streaming
                 // acknowledge.
      // this is independent of receiving an actual response.
      final String jsonResponse = gson.toJson(new BrowserStreamAcknowledged(streamedResponses.get(browser)));
      logger.trace("sending jsonResponse {}", jsonResponse);
      writer.print(jsonResponse);
      writer.flush();
      return;
    } else {
      streamedResponses.get(browser).clear();
    }
    if(command == null) {
     command = browser.dequeueCommand();
     browser.heartBeat();
    }

    logger.trace("sending command {}", command == null ? "null" : command.getCommand());
    writer.print(command.getCommand());
  }

  /**
   * @param browser
   * @param res
   */
  private void handleFileLoadResult(SlaveBrowser browser, Response res) {
    LoadedFiles loadedFiles = gson.fromJson(res.getResponse(), res.getGsonType());
    Collection<FileResult> allLoadedFiles = loadedFiles.getLoadedFiles();
    logger.info("loaded {} files", allLoadedFiles.size());
    browser.addFileResults(allLoadedFiles);
  }

  private boolean isResponseValid(String response) {
    return response != null && !"null".equals(response) && !"undefined".equals(response) && response.length() > 0;
  }

  private void addResponseId(String responseId, SlaveBrowser browser) {
    if (!streamedResponses.containsKey(browser)) {
      streamedResponses.put(browser, new CopyOnWriteArrayList<String>());
    }
    if (!isResponseIdValid(responseId)) {
      return;
    }
    streamedResponses.get(browser).add(responseId);
  }

  private boolean isResponseIdValid(String responseId) {
    return !(responseId == null || "".equals(responseId));
  }
}
TOP

Related Classes of com.google.jstestdriver.server.handlers.BrowserQueryResponseHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.