// Copyright (C) 2012 The Android Open Source Project
//
// 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.gerrit.httpd;

import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.plugins.Plugin;
import com.google.gerrit.server.plugins.StopPluginListener;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.internal.UniqueAnnotations;
import com.google.inject.servlet.ServletModule;

import java.io.IOException;
import java.util.Iterator;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/** Filters all HTTP requests passing through the server. */
public abstract class AllRequestFilter implements Filter {
  public static ServletModule module() {
    return new ServletModule() {
      @Override
      protected void configureServlets() {
        DynamicSet.setOf(binder(), AllRequestFilter.class);
        filter("/*").through(FilterProxy.class);

        bind(StopPluginListener.class)
          .annotatedWith(UniqueAnnotations.create())
          .to(FilterProxy.class);
      }
    };
  }

  @Singleton
  static class FilterProxy implements Filter, StopPluginListener {
    private final DynamicSet<AllRequestFilter> filters;

    private DynamicSet<AllRequestFilter> initializedFilters;
    private FilterConfig filterConfig;

    @Inject
    FilterProxy(DynamicSet<AllRequestFilter> filters) {
      this.filters = filters;
      this.initializedFilters = new DynamicSet<>();
      this.filterConfig = null;
    }

    /**
     * Initializes a filter if needed
     *
     * @param filter The filter that should get initialized
     * @return {@code true} iff filter is now initialized
     * @throws ServletException if filter itself fails to init
     */
    private synchronized boolean initFilterIfNeeded(AllRequestFilter filter)
        throws ServletException {
      boolean ret = true;
      if (filters.contains(filter)) {
        // Regardless of whether or not the caller checked filter's
        // containment in initializedFilters, we better re-check as we're now
        // synchronized.
        if (!initializedFilters.contains(filter)) {
          filter.init(filterConfig);
          initializedFilters.add(filter);
        }
      } else {
        ret = false;
      }
      return ret;
    }

    private synchronized void cleanUpInitializedFilters() {
      Iterable<AllRequestFilter> filtersToCleanUp  = initializedFilters;
      initializedFilters = new DynamicSet<>();
      for (AllRequestFilter filter : filtersToCleanUp) {
        if (filters.contains(filter)) {
          initializedFilters.add(filter);
        } else {
          filter.destroy();
        }
      }
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res,
        final FilterChain last) throws IOException, ServletException {
      final Iterator<AllRequestFilter> itr = filters.iterator();
      new FilterChain() {
        @Override
        public void doFilter(ServletRequest req, ServletResponse res)
            throws IOException, ServletException {
          while (itr.hasNext()) {
            AllRequestFilter filter = itr.next();
            // To avoid {@code synchronized} on the the whole filtering (and
            // thereby killing concurrency), we start the below disjunction
            // with an unsynchronized check for containment. This
            // unsynchronized check is always correct if no filters got
            // initialized/cleaned concurrently behind our back.
            // The case of concurrently initialized filters is saved by the
            // call to initFilterIfNeeded. So that's fine too.
            // The case of concurrently cleaned filters between the {@code if}
            // condition and the call to {@code doFilter} is not saved by
            // anything. If a filter is getting removed concurrently while
            // another thread is in those two lines, doFilter might (but need
            // not) fail.
            //
            // Since this failure only occurs if a filter is deleted
            // (e.g.: a plugin reloaded) exactly when a thread is in those
            // two lines, and it only breaks a single request, we're ok with
            // it, given that this is really both really improbable and also
            // the "proper" fix for it would basically kill concurrency of
            // webrequests.
            if (initializedFilters.contains(filter)
                || initFilterIfNeeded(filter)) {
              filter.doFilter(req, res, this);
              return;
            }
          }
          last.doFilter(req, res);
        }
      }.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
      // Plugins that provide AllRequestFilters might get loaded later at
      // runtime, long after this init method had been called. To allow to
      // correctly init such plugins' AllRequestFilters, we keep the
      // FilterConfig around, and reuse it to lazy init the AllRequestFilters.
      filterConfig = config;

      for (AllRequestFilter f: filters) {
        initFilterIfNeeded(f);
      }
    }

    @Override
    public synchronized void destroy() {
      Iterable<AllRequestFilter> filtersToDestroy  = initializedFilters;
      initializedFilters = new DynamicSet<>();
      for (AllRequestFilter filter: filtersToDestroy) {
        filter.destroy();
      }
    }

    @Override
    public void onStopPlugin(Plugin plugin) {
      // In order to allow properly garbage collection, we need to scrub
      // initializedFilters clean of filters stemming from plugins as they
      // get unloaded.
      cleanUpInitializedFilters();
    }
  }

  @Override
  public void init(FilterConfig config) throws ServletException {
  }

  @Override
  public void destroy() {
  }
}
