/*
 * Copyright (C) 2009-2010, Google Inc. and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.http.server.glue;

import java.io.IOException;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Encapsulates the entire serving stack for a single URL.
 * <p>
 * Subclasses provide the implementation of {@link #match(HttpServletRequest)},
 * which is called by {@link MetaServlet} in registration order to determine the
 * pipeline that will be used to handle a request.
 * <p>
 * The very bottom of each pipeline is a single {@link HttpServlet} that will
 * handle producing the response for this pipeline's URL. {@link Filter}s may
 * also be registered and applied around the servlet's processing, to manage
 * request attributes, set standard response headers, or completely override the
 * response generation.
 */
abstract class UrlPipeline {
	/** Filters to apply around {@link #servlet}; may be empty but never null. */
	private final Filter[] filters;

	/** Instance that must generate the response; never null. */
	private final HttpServlet servlet;

	UrlPipeline(Filter[] filters, HttpServlet servlet) {
		this.filters = filters;
		this.servlet = servlet;
	}

	/**
	 * Initialize all contained filters and servlets.
	 *
	 * @param context
	 *            the servlet container context our {@link MetaServlet} is
	 *            running within.
	 * @param inited
	 *            <i>(input/output)</i> the set of filters and servlets which
	 *            have already been initialized within the container context. If
	 *            those same instances appear in this pipeline they are not
	 *            initialized a second time. Filters and servlets that are first
	 *            initialized by this pipeline will be added to this set.
	 * @throws ServletException
	 *             a filter or servlet is unable to initialize.
	 */
	void init(ServletContext context, Set<Object> inited)
			throws ServletException {
		for (Filter ref : filters)
			initFilter(ref, context, inited);
		initServlet(servlet, context, inited);
	}

	private static void initFilter(final Filter ref,
			final ServletContext context, final Set<Object> inited)
			throws ServletException {
		if (!inited.contains(ref)) {
			ref.init(new NoParameterFilterConfig(ref.getClass().getName(),
					context));
			inited.add(ref);
		}
	}

	private static void initServlet(final HttpServlet ref,
			final ServletContext context, final Set<Object> inited)
			throws ServletException {
		if (!inited.contains(ref)) {
			ref.init(new ServletConfig() {
				@Override
				public String getInitParameter(String name) {
					return null;
				}

				@Override
				public Enumeration<String> getInitParameterNames() {
					return new Enumeration<>() {

						@Override
						public boolean hasMoreElements() {
							return false;
						}

						@Override
						public String nextElement() {
							throw new NoSuchElementException();
						}
					};
				}

				@Override
				public ServletContext getServletContext() {
					return context;
				}

				@Override
				public String getServletName() {
					return ref.getClass().getName();
				}
			});
			inited.add(ref);
		}
	}

	/**
	 * Destroy all contained filters and servlets.
	 *
	 * @param destroyed
	 *            <i>(input/output)</i> the set of filters and servlets which
	 *            have already been destroyed within the container context. If
	 *            those same instances appear in this pipeline they are not
	 *            destroyed a second time. Filters and servlets that are first
	 *            destroyed by this pipeline will be added to this set.
	 */
	void destroy(Set<Object> destroyed) {
		for (Filter ref : filters)
			destroyFilter(ref, destroyed);
		destroyServlet(servlet, destroyed);
	}

	private static void destroyFilter(Filter ref, Set<Object> destroyed) {
		if (!destroyed.contains(ref)) {
			ref.destroy();
			destroyed.add(ref);
		}
	}

	private static void destroyServlet(HttpServlet ref, Set<Object> destroyed) {
		if (!destroyed.contains(ref)) {
			ref.destroy();
			destroyed.add(ref);
		}
	}

	/**
	 * Determine if this pipeline handles the request's URL.
	 * <p>
	 * This method should match on the request's {@code getPathInfo()} method,
	 * as {@link MetaServlet} passes the request along as-is to each pipeline's
	 * match method.
	 *
	 * @param req
	 *            current HTTP request being considered by {@link MetaServlet}.
	 * @return {@code true} if this pipeline is configured to handle the
	 *         request; {@code false} otherwise.
	 */
	abstract boolean match(HttpServletRequest req);

	/**
	 * Execute the filters and the servlet on the request.
	 * <p>
	 * Invoked by {@link MetaServlet} once {@link #match(HttpServletRequest)}
	 * has determined this pipeline is the correct pipeline to handle the
	 * current request.
	 *
	 * @param req
	 *            current HTTP request.
	 * @param rsp
	 *            current HTTP response.
	 * @throws ServletException
	 *             request cannot be completed.
	 * @throws IOException
	 *             IO error prevents the request from being completed.
	 */
	void service(HttpServletRequest req, HttpServletResponse rsp)
			throws ServletException, IOException {
		if (0 < filters.length)
			new Chain(filters, servlet).doFilter(req, rsp);
		else
			servlet.service(req, rsp);
	}

	private static class Chain implements FilterChain {
		private final Filter[] filters;

		private final HttpServlet servlet;

		private int filterIdx;

		Chain(Filter[] filters, HttpServlet servlet) {
			this.filters = filters;
			this.servlet = servlet;
		}

		@Override
		public void doFilter(ServletRequest req, ServletResponse rsp)
				throws IOException, ServletException {
			if (filterIdx < filters.length)
				filters[filterIdx++].doFilter(req, rsp, this);
			else
				servlet.service(req, rsp);
		}
	}
}
