/**
   * Caso o response ja esteja fechado ou o metodo startAsync() ja tenha sido chamado, uma nova
   * invocacao resultara em uma IllegalStateException.
   */
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    PrintWriter writer = resp.getWriter();

    writer.println("Antes de iniciar a tarefa assincrona");

    /*
     * Para iniciar uma requisicao assincrona, basta chamar o metodo
     * startAsync de ServletRequest. O metodo startAsync é sobrecarregado
     * para receber um ServletRequest e um ServletResponse, desta forma é
     * possivel passar wrappers para ele. Caso o metodo startAsync seja
     * chamado, os objetos ServletRequest e Response originais serao
     * utilizados.
     */
    AsyncContext asyncContext = req.startAsync();

    MyAsyncTask asyncTask = new MyAsyncTask(asyncContext, writer);

    /*
     * O tempo padrao de time out depende do container, geralmente está
     * entre 5 e 10 segundos. Para desabilitar o time out basta informar um
     * valor negativo ou 0. Esse metodo pode ser chamado antes ou depois do
     * metodo start().
     */
    asyncContext.setTimeout(-1);

    /*
     * A Interface AsyncContext possui metodos para configurar a tarefa
     * assincrona e inicializar a mesma. O metodo estart recebe um runnable
     * que sera responsavel por realizar o processamento da tarefa
     * assincrona. Quando esse metodo é chamado, o processamento é realizado
     * por outra Thread do pool de Threads do servidor.
     */
    asyncContext.start(asyncTask);

    /*
     * Depois do start() da tarefa assincrona, o fluxo continua normalmente,
     * e quando o metodo service() é encerrado, a resposta nao é commitada
     * enquanto o metodo complete() de AsyncContext não for chamado. Desta
     * forma, o container processa a tarefa assincrona um background em
     * outra Thread.
     */
    writer.println("Depois de iniciar a tarefa assincrona");

    /*
     * Retorna o AsyncContext inicializado para esse request. Caso o metodo
     * startAsync() ainda nao tenha sido chamado, uma IllegalStateException
     * ocorrera.
     */
    req.getAsyncContext();
  }
 @Override
 public Object getAsyncResult(long timeout) {
   // MockHttpServletRequest type doesn't have async methods
   HttpServletRequest request = this.mockRequest;
   if ((timeout != 0) && request.isAsyncStarted()) {
     if (timeout == -1) {
       timeout = request.getAsyncContext().getTimeout();
     }
     if (!awaitAsyncResult(timeout)) {
       throw new IllegalStateException(
           "Gave up waiting on async result from handler [" + this.handler + "] to complete");
     }
   }
   return this.asyncResult;
 }
    @Override
    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp)
        throws ServletException, IOException {

      result = new StringBuilder();
      result.append('1');
      result.append(req.isAsyncStarted());
      req.startAsync();
      result.append('2');
      result.append(req.isAsyncStarted());

      req.getAsyncContext()
          .start(
              new Runnable() {
                @Override
                public void run() {
                  Thread t =
                      new Thread(
                          new Runnable() {
                            @Override
                            public void run() {
                              try {
                                result.append('3');
                                result.append(req.isAsyncStarted());
                                Thread.sleep(1000);
                                result.append('4');
                                result.append(req.isAsyncStarted());
                                resp.setContentType("text/plain");
                                resp.getWriter().print("OK");
                                req.getAsyncContext().complete();
                                result.append('5');
                                result.append(req.isAsyncStarted());
                                done = true;
                              } catch (InterruptedException e) {
                                result.append(e);
                              } catch (IOException e) {
                                result.append(e);
                              }
                            }
                          });
                  t.start();
                }
              });
      // Pointless method call so there is somewhere to put a break point
      // when debugging
      req.getMethod();
    }
 @Override
 protected void service(HttpServletRequest req, HttpServletResponse resp)
     throws ServletException, IOException {
   if (req.isAsyncStarted()) {
     req.getAsyncContext().complete();
   } else if (req.isAsyncSupported()) {
     AsyncContext actx = req.startAsync();
     actx.addListener(this);
     resp.setContentType("text/plain");
     clients.add(actx);
     if (clientcount.incrementAndGet() == 1) {
       ticker.addTickListener(this);
     }
   } else {
     new Exception("Async Not Supported").printStackTrace();
     resp.sendError(400, "Async is not supported.");
   }
 }
 @Override
 public AsyncContext getAsyncContext() {
   return request.getAsyncContext();
 }
  /** Processes the HTTP request, */
  protected void processRequest(
      HttpServletRequest request, HttpServletResponse response, String request_type)
      throws ServletException, IOException {

    try {

      // Is this a dispatch?
      Object consume_status_key = request.getAttribute(AsyncServletProcessUtil.CONSUME_STATUS_KEY);

      // Make a process client,
      PlatformContext ctx = PlatformContextFactory.getPlatformContext();

      ProcessInputMessage result;
      ProcessResult result_ob;

      // Is this the continuation init?
      if (consume_status_key == null) {

        Cookie pid_cookie = null;
        // The process id cookie,
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
          for (Cookie c : cookies) {
            String cname = c.getName();
            if (cname.equals("pid")) {
              pid_cookie = c;
            }
          }
        }

        if (pid_cookie == null) {
          // Give a friendlier error message here?
          response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Session cookie not found");
          return;
        }

        // Get the cookie's value,
        String process_id_str = pid_cookie.getValue();

        AppServiceProcessClient process_client = ctx.getAppServiceProcessClient();
        ProcessId process_id = ProcessId.fromString(process_id_str);

        String ip_addr = request.getRemoteAddr();

        // Check if the process is valid,
        ProcessMessage msg_to_send = ByteArrayProcessMessage.encodeArgs("?", null, null, ip_addr);

        // Invoke the function on the process id,
        result_ob = process_client.invokeFunction(process_id, msg_to_send, true);
        request.setAttribute(getClass().getName(), result_ob);

        result = result_ob.getResult(AsyncServletProcessUtil.createNotifier(request));
        if (result == null) {
          // Set timeout to 30 seconds,
          request.getAsyncContext().setTimeout(30 * 1000);
          return;
        }

      }
      // Not initial,
      else {
        result_ob = (ProcessResult) request.getAttribute(getClass().getName());
        result = result_ob.getResult();
      }

      // This would be a timeout,
      if (result == null) {
        response.sendError(
            HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Timed out waiting for response");
        return;
      }
      if (result.getType() == ProcessInputMessage.Type.RETURN_EXCEPTION) {
        throw new ServletException(result.getError());
      }

      // Ok, we now have our result from the process,
      Object[] args = ByteArrayProcessMessage.decodeArgsList(result.getMessage(), 0);
      String resp = (String) args[0];
      if (!resp.equals("OK")) {
        throw new RuntimeException("Invalid response from process: " + resp);
      }

      // The user of the process,
      String username = (String) args[1];

      // Ok, everything looks good to go,

      String location;
      String html_body;

      // Context info,
      String context_path = request.getContextPath();
      if (context_path == null) context_path = "";
      if (context_path.equals("/")) context_path = "";
      String servlet_path = request.getServletPath();
      String path_info = request.getPathInfo();
      if (path_info == null) path_info = "/";

      // Create the response,

      DDBResourceAccess mckoi_access = ctx.getDDBResourceAccess();

      // Parse the link,

      StringBuilder request_link = new StringBuilder();
      request_link.append(context_path);
      request_link.append(servlet_path);
      request_link.append(path_info);

      // Sub-part,
      int delim = path_info.lastIndexOf("/");
      String path_p = path_info.substring(0, delim);
      if (path_p.startsWith("/")) {
        path_p = path_p.substring(1);
      }

      // 'path_p' now contains the path we are looking at,

      // If no path_p,
      if (path_p.equals("")) {

        String link_prepend = context_path + servlet_path + "/";

        location = "Path List";
        html_body = pathListSummary(mckoi_access, link_prepend);

      } else {

        ODBTransaction t = mckoi_access.createODBTransaction(path_p);

        // Extract the location,
        delim = request_link.lastIndexOf("/");
        location = request_link.substring(delim + 1);

        String link_prepend = request_link.substring(0, delim + 1);

        // Get the 'pos' and 'size' vars if they exist,
        String pos = request.getParameter("pos");
        String size = request.getParameter("size");
        if (pos != null) {
          location = location + "?pos=" + pos + "&size=" + size;
        }

        if (location.equals("")) {

          location = "Path: " + path_p;
          html_body = ODBPathSummary(t, path_p, link_prepend);

        } else {

          // Get the formatter,
          ODBHTMLFormatter formatter = new ODBHTMLFormatter(t, link_prepend);

          // Format it,
          html_body = formatter.format(location);
        }
      }

      response.setContentType("text/html;charset=UTF-8");
      PrintWriter out = response.getWriter();

      try {

        out.println("<html>");
        out.println("<head>");
        out.println("<title>DBBrowser - " + HTMLWriter.toHTMLEntity(location) + "</title>");

        out.println("<style type=\"text/css\">");
        out.println(" table { border: 1px solid #000000; border-collapse: collapse; }");
        out.println(
            " td { border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 0px 6px 0px 6px; }");
        out.println(" th { background: #000000; color: #FFFFFF; }");
        out.println(" table.oblist { font-family:monospace; }");
        out.println(" table.data { border: none; border-collapse: collapse; }");
        out.println(
            " table.data td { border-left: none; border-right: none; padding: 2px 12px 2px 12px; }");
        out.println("</style>");

        out.println("</head>");
        out.println("<body>");
        out.println(html_body);
        out.println("</body>");
        out.println("</html>");

      } finally {
        out.close();
      }

    } catch (Throwable e) {
      // Output the error message,

      response.setContentType("text/html;charset=UTF-8");
      PrintWriter out = response.getWriter();

      try {

        out.println("<html>");
        out.println("<head>");
        out.println("<title>DBBrowser - error when producing page.</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>" + HTMLWriter.toHTMLEntity(e.getMessage()) + "</h1>");
        out.print("<pre>");
        StringWriter str_out = new StringWriter();
        PrintWriter pout = new PrintWriter(str_out);
        e.printStackTrace(pout);
        pout.flush();
        out.print(HTMLWriter.toHTMLEntity(str_out.toString()));
        out.println("</pre>");
        out.println("</body>");
        out.println("</html>");

      } finally {
        out.close();
      }
    }
  }