public void afterTest(@Observes After event) {
    TestResult result = testResult.get();
    if (strategy.get().isTakingAction(event, result)) {
      ScreenshotType screenshotType = getScreenshotType();
      ScreenshotMetaData metaData = getMetaData(event);
      metaData.setTestResult(result);

      beforeScreenshotTaken.fire(new BeforeScreenshotTaken(screenshotType, metaData));

      takeScreenshot.fire(
          new TakeScreenshot(
              screenshotType,
              metaData,
              result.getStatus() == TestResult.Status.FAILED ? When.FAILED : When.AFTER));

      afterScreenshotTaken.fire(new AfterScreenshotTaken(screenshotType, metaData));
    }
  }
 @Override
 public boolean isTakingAction(Event event, TestResult result) {
   if (event instanceof After) {
     if (configuration.getTakeAfterTest()) {
       return true;
     }
     if (result.getStatus() == Status.FAILED && configuration.getTakeWhenTestFailed()) {
       return true;
     }
   }
   return false;
 }
  public void callback(@Observes EventContext<Test> eventContext) throws Exception {
    // first let the test run
    eventContext.proceed();
    // then verify that the test performed within the specified time
    verifyPerformance(eventContext.getEvent());
    // then compare with previous results

    PerformanceSuiteResult suiteResult = suiteResultInst.get();

    if (suiteResult != null) {
      try {
        comparePerformanceSuiteResults(
            suiteResult, eventContext.getEvent().getTestMethod().getName());
      } catch (PerformanceException pe) {
        TestResult result = testResultInst.get();
        if (result != null) {
          result.setThrowable(pe);
        }
      }
    }
  }
  /**
   * Verify that the test ended within specified time
   *
   * @param event, the test
   * @throws PerformanceException if the test did not end within the specified time
   */
  private void verifyPerformance(Test event) throws PerformanceException {
    TestResult result = testResultInst.get();
    if (result != null) {
      // check if we have set a threshold
      Performance performance = null;
      Annotation[] annotations = event.getTestMethod().getDeclaredAnnotations();
      for (Annotation a : annotations)
        if (a.annotationType().getName().equals(Performance.class.getCanonicalName()))
          performance = (Performance) a;

      double maxTime = -1;
      if (performance != null) {
        // System.out.println("For test: "+event.toString()+", it took:
        // "+(result.getEnd()-result.getStart()));
        if (performance.time() > 0 && performance.time() < (result.getEnd() - result.getStart())) {
          result.setStatus(TestResult.Status.FAILED);
          result.setThrowable(
              new PerformanceException(
                  "The test didnt finish within the specified time: "
                      + performance.time()
                      + "ms, it took "
                      + (result.getEnd() - result.getStart())
                      + "ms."));
        }

        maxTime = performance.time();
      }

      // fetch suiteResult, get the correct classResult and append the test to that
      // classResult.
      PerformanceSuiteResult suiteResult = suiteResultInst.get();
      if (suiteResult != null) {
        suiteResult
            .getResult(event.getTestClass().getName())
            .addMethodResult(
                new PerformanceMethodResult(
                    maxTime, result.getEnd() - result.getStart(), event.getTestMethod()));
      }
    }
  }
  public void on(
      @Observes AfterTestLifecycleEvent event,
      TestResult testResult,
      GovernorRegistry governorRegistry,
      JiraGovernorConfiguration jiraGovernorConfiguration,
      JiraGovernorClient jiraGovernorClient) {
    int count = 0;
    try {
      Integer c = lifecycleCountRegister.get(event.getTestMethod());
      count = (c != null ? c.intValue() : 0);
      if (count
          == 0) { // skip first event - see
                  // https://github.com/arquillian/arquillian-governor/pull/16#issuecomment-166590210
        return;
      }
      final ExecutionDecision decision =
          TestMethodExecutionRegister.resolve(event.getTestMethod(), provides());

      // if we passed some test method annotated with Jira, we may eventually close it

      if (jiraGovernorConfiguration.getClosePassed()) {
        // we decided we run this test method even it has annotation on it
        if (testResult.getStatus() == Status.PASSED
            && decision.getDecision() == Decision.EXECUTE
            && (JiraGovernorStrategy.FORCING_EXECUTION_REASON_STRING)
                .equals(decision.getReason())) {

          for (Map.Entry<Method, List<Annotation>> entry : governorRegistry.get().entrySet()) {
            if (entry.getKey().toString().equals(event.getTestMethod().toString())) {
              for (Annotation annotation : entry.getValue()) {
                if (annotation.annotationType() == provides()) {
                  String id = ((Jira) annotation).value();
                  jiraGovernorClient.close(id);
                  return;
                }
              }
            }
          }
        }
      }
    } finally {
      lifecycleCountRegister.put(event.getTestMethod(), ++count);
    }
  }
  @Override
  public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
      throws IOException, ServletException {
    if (req instanceof HttpServletRequest && resp instanceof HttpServletResponse) {
      HttpServletRequest httpReq = ((HttpServletRequest) req);
      HttpServletResponse httpResp = ((HttpServletResponse) resp);

      String requestEnrichment = httpReq.getHeader(ENRICHMENT_REQUEST);

      if (requestEnrichment != null && !"null".equals(requestEnrichment)) {

        final AtomicReference<NonWritingServletOutputStream> stream =
            new AtomicReference<NonWritingServletOutputStream>();
        final AtomicReference<NonWritingPrintWriter> writer =
            new AtomicReference<NonWritingPrintWriter>();

        HttpServletResponseWrapper responseWrapper =
            new HttpServletResponseWrapper((HttpServletResponse) resp) {
              @Override
              public ServletOutputStream getOutputStream() throws IOException {
                stream.set(new NonWritingServletOutputStream());
                return stream.get();
              }

              @Override
              public PrintWriter getWriter() throws IOException {
                writer.set(NonWritingPrintWriter.newInstance());
                return writer.get();
              }
            };

        String responseEnrichment = "null";

        try {
          RequestPayload requestPayload =
              SerializationUtils.deserializeFromBase64(requestEnrichment);
          ServerAssertion serverAssertion = requestPayload.getAssertion();

          ManagerBuilder builder =
              ManagerBuilder.from().extension(Class.forName(DEFAULT_EXTENSION_CLASS));
          Manager manager = builder.create();
          manager.start();
          manager.bind(ApplicationScoped.class, Manager.class, manager);
          manager.inject(this);

          req.setAttribute(
              WarpCommons.LIFECYCLE_MANAGER_STORE_REQUEST_ATTRIBUTE, lifecycleManagerStore);

          manager.fire(new BeforeSuite());
          manager.fire(new BeforeRequest(req));
          lifecycleManagerStore.get().bind(ServletRequest.class, req);

          assertionRegistry.get().registerAssertion(serverAssertion);

          lifecycleManager.get().fireLifecycleEvent(new BeforeServletEvent());

          try {
            chain.doFilter(req, responseWrapper);

            lifecycleManager.get().fireLifecycleEvent(new AfterServletEvent());

            // request successfully finished
            TestResult firstFailedResult = testResultStore.get().getFirstFailed();
            if (firstFailedResult == null) {
              ResponsePayload responsePayload = new ResponsePayload(serverAssertion);
              responseEnrichment = SerializationUtils.serializeToBase64(responsePayload);
              httpResp.setHeader(ENRICHMENT_RESPONSE, responseEnrichment);
            } else {
              Throwable throwable = firstFailedResult.getThrowable();
              if (throwable instanceof InvocationTargetException) {
                throwable = throwable.getCause();
              }
              ResponsePayload responsePayload = new ResponsePayload(throwable);
              enrichResponse(httpResp, responsePayload);
            }
          } catch (Exception e) {
            log.log(Level.SEVERE, "The error occured during request execution", e);
            throw e;
          } finally {
            assertionRegistry.get().unregisterAssertion(serverAssertion);

            lifecycleManagerStore.get().unbind(ServletRequest.class, req);
            manager.fire(new AfterRequest(req));
            manager.fire(new AfterSuite());
          }

        } catch (Throwable e) {
          // exception occured during request execution
          ResponsePayload responsePayload = new ResponsePayload(e);
          responseEnrichment = SerializationUtils.serializeToBase64(responsePayload);
          httpResp.setHeader(ENRICHMENT_RESPONSE, responseEnrichment);
          httpResp.sendError(500);
        }

        if (writer.get() != null) {
          writer.get().finallyWriteAndClose(resp.getOutputStream());
        }
        if (stream.get() != null) {
          stream.get().finallyWriteAndClose(resp.getOutputStream());
        }

        return;
      }
    }

    chain.doFilter(req, resp);
  }