/*
 * Copyright 2018, OpenCensus Authors
 *
 * 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 io.opencensus.contrib.http.servlet;

import static com.google.common.base.Preconditions.checkNotNull;

import io.opencensus.common.ExperimentalApi;
import io.opencensus.common.Scope;
import io.opencensus.contrib.http.HttpRequestContext;
import io.opencensus.contrib.http.HttpServerHandler;
import io.opencensus.trace.Tracing;
import java.io.Closeable;
import javax.annotation.Nullable;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * This class implements {@link AsyncListener} to handle span completion for async request handling.
 */
@ExperimentalApi
public final class OcHttpServletListener implements Closeable, AsyncListener {
  private final HttpRequestContext context;
  private final HttpServerHandler<HttpServletRequest, HttpServletResponse, HttpServletRequest>
      handler;
  @Nullable private Scope scope = null;

  OcHttpServletListener(
      HttpServerHandler<HttpServletRequest, HttpServletResponse, HttpServletRequest> handler,
      HttpRequestContext context) {
    checkNotNull(context, "context");
    checkNotNull(handler, "handler");
    this.context = context;
    this.handler = handler;
  }

  @Override
  public void close() {}

  @Override
  public void onComplete(AsyncEvent event) {
    ServletResponse response = event.getSuppliedResponse();
    if (response instanceof HttpServletResponse) {
      OcHttpServletUtil.recordMessageSentEvent(handler, context, (HttpServletResponse) response);
    }
    if (scope != null) {
      scope.close();
    }
    handler.handleEnd(
        context,
        (HttpServletRequest) event.getSuppliedRequest(),
        (HttpServletResponse) event.getSuppliedResponse(),
        null);
    this.close();
  }

  @Override
  public void onError(AsyncEvent event) {
    if (scope != null) {
      scope.close();
    }
    handler.handleEnd(
        context,
        (HttpServletRequest) event.getSuppliedRequest(),
        (HttpServletResponse) event.getSuppliedResponse(),
        event.getThrowable());
  }

  @Override
  @SuppressWarnings(
      "MustBeClosedChecker") // Close will happen in onTimeout or onError or onComplete method
  public void onStartAsync(AsyncEvent event) {
    AsyncContext eventAsyncContext = event.getAsyncContext();
    if (eventAsyncContext != null) {
      this.scope = Tracing.getTracer().withSpan(handler.getSpanFromContext(context));
      eventAsyncContext.addListener(this, event.getSuppliedRequest(), event.getSuppliedResponse());
    }
  }

  @Override
  public void onTimeout(AsyncEvent event) {
    if (scope != null) {
      scope.close();
    }
    handler.handleEnd(
        context,
        (HttpServletRequest) event.getSuppliedRequest(),
        (HttpServletResponse) event.getSuppliedResponse(),
        null);
  }
}

@@ -757,43 +757,8 @@
 pi;%0A
-import io.opencensus.common.Scope;%0A
 impo
@@ -871,91 +871,21 @@
 ort 
-io.opencensus.trace.Tracing;%0Aimport java.io.Closeable;%0Aimport javax.annotation.Null
+java.io.Close
 able
@@ -1484,48 +1484,8 @@
 ler;
-%0A  @Nullable private Scope scope = null;
 %0A%0A  
@@ -2088,60 +2088,8 @@
   %7D%0A
-    if (scope != null) %7B%0A      scope.close();%0A    %7D%0A
     
@@ -2336,60 +2336,8 @@
 ) %7B%0A
-    if (scope != null) %7B%0A      scope.close();%0A    %7D%0A
     
@@ -2802,94 +2802,8 @@
 ) %7B%0A
-      this.scope = Tracing.getTracer().withSpan(handler.getSpanFromContext(context));%0A
     
@@ -2969,60 +2969,8 @@
 ) %7B%0A
-    if (scope != null) %7B%0A      scope.close();%0A    %7D%0A
     

rollback scope creation for async request. (#1709)