/*******************************************************************************
 * Copyright (c) 2011, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Raymond Augé <raymond.auge@liferay.com> - Bug 436698
 *******************************************************************************/
package org.eclipse.equinox.http.servlet.internal.registration;

import java.io.IOException;
import java.util.Arrays;
import java.util.regex.Pattern;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.equinox.http.servlet.internal.context.ContextController;
import org.eclipse.equinox.http.servlet.internal.context.ServiceHolder;
import org.eclipse.equinox.http.servlet.internal.servlet.FilterChainImpl;
import org.eclipse.equinox.http.servlet.internal.servlet.Match;
import org.eclipse.equinox.http.servlet.internal.util.Const;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.http.runtime.dto.FilterDTO;

//This class wraps the filter object registered in the HttpService.registerFilter call, to manage the context classloader when handleRequests are being asked.
public class FilterRegistration
	extends MatchableRegistration<Filter, FilterDTO>
	implements Comparable<FilterRegistration> {

	private final ServiceHolder<Filter> filterHolder;
	private final ClassLoader classLoader;
	private final int priority;
	private final ContextController contextController;
	private final boolean initDestoyWithContextController;
	private final Pattern[] compiledRegexs;
	private final boolean needDecode;

	public FilterRegistration(
		ServiceHolder<Filter> filterHolder, FilterDTO filterDTO, int priority,
		ContextController contextController) {

		super(filterHolder.get(), filterDTO);
		this.filterHolder = filterHolder;
		this.priority = priority;
		this.contextController = contextController;
		this.compiledRegexs = getCompiledRegex(filterDTO);
		if (filterHolder.getLegacyTCCL() != null) {
			// legacy filter registrations used the current TCCL at registration time
			classLoader = filterHolder.getLegacyTCCL();
		} else {
			classLoader = filterHolder.getBundle().adapt(BundleWiring.class).getClassLoader();
		}
		String legacyContextFilter = (String) filterHolder.getServiceReference().getProperty(Const.EQUINOX_LEGACY_CONTEXT_SELECT);
		if (legacyContextFilter != null) {
			// This is a legacy Filter registration.  
			// This filter tells us the real context controller,
			// backed by an HttpContext that should be used to init/destroy this Filter
			org.osgi.framework.Filter f = null;
			try {
				f = FrameworkUtil.createFilter(legacyContextFilter);
			}
			catch (InvalidSyntaxException e) {
				// nothing
			}
			initDestoyWithContextController = f == null || contextController.matches(f);
		} else {
			initDestoyWithContextController = true;
		}
		needDecode = MatchableRegistration.patternsRequireDecode(filterDTO.patterns);
	}

	@Override
	public int compareTo(FilterRegistration otherFilterRegistration) {
		int priorityDifference = priority - otherFilterRegistration.priority;
		if (priorityDifference != 0)
			return -priorityDifference;

		// Note that we use abs here because the DTO service ID may have been negated for legacy filters.
		// We always compare with the positive id values and we know the positive values are unique.
		long thisId = Math.abs(getD().serviceId);
		long otherId = Math.abs(otherFilterRegistration.getD().serviceId);
		return (thisId < otherId) ? -1 : ((thisId == otherId) ? 0 : 1);
	}

	@Override
	public void destroy() {
		if (!initDestoyWithContextController) {
			return;
		}
		ClassLoader original = Thread.currentThread().getContextClassLoader();
		try {
			Thread.currentThread().setContextClassLoader(classLoader);
			contextController.getHttpServiceRuntime().getRegisteredObjects().remove(this.getT());
			contextController.getFilterRegistrations().remove(this);
			contextController.ungetServletContextHelper(filterHolder.getBundle());
			super.destroy();
			getT().destroy();
		}
		finally {
			destroyContextAttributes();
			Thread.currentThread().setContextClassLoader(original);
			filterHolder.release();
		}
	}

	public boolean appliesTo(FilterChainImpl filterChainImpl) {
		return (Arrays.binarySearch(
			getD().dispatcher, filterChainImpl.getDispatcherType().name()) >= 0);
	}

	//Delegate the handling of the request to the actual filter
	public void doFilter(
			HttpServletRequest request, HttpServletResponse response,
			FilterChain chain)
		throws IOException, ServletException {

		ClassLoader original = Thread.currentThread().getContextClassLoader();
		try {
			Thread.currentThread().setContextClassLoader(classLoader);
			getT().doFilter(request, response, chain);
		}
		finally {
			Thread.currentThread().setContextClassLoader(original);
		}
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof FilterRegistration)) {
			return false;
		}

		FilterRegistration filterRegistration = (FilterRegistration)obj;

		return getT().equals(filterRegistration.getT());
	}

	@Override
	public int hashCode() {
		return Long.valueOf(getD().serviceId).hashCode();
	}

	//Delegate the init call to the actual filter
	public void init(FilterConfig filterConfig) throws ServletException {
		if (!initDestoyWithContextController) {
			return;
		}
		boolean initialized = false;
		ClassLoader original = Thread.currentThread().getContextClassLoader();
		try {
			Thread.currentThread().setContextClassLoader(classLoader);

			createContextAttributes();
			getT().init(filterConfig);
			initialized = true;
		}
		finally {
			if (!initialized) {
				destroyContextAttributes();
			}
			Thread.currentThread().setContextClassLoader(original);
		}
	}

	public String match(
		String name, String requestURI, String extension, Match match) {
		if ((name != null) && (getD().servletNames != null)) {
			for (String servletName : getD().servletNames) {
				if (servletName.equals(name)) {
					return name;
				}
			}
		}

		if (requestURI == null || requestURI.isEmpty()) {
			return null;
		}

		for (String pattern : getD().patterns) {
			if (doPatternMatch(pattern, requestURI, extension)) {
				return pattern;
			}
		}

		for (Pattern regex : compiledRegexs) {
			if (regex.matcher(requestURI).matches()) {
				return regex.toString();
			}
		}

		return null;
	}

	@Override
	public String match(
		String name, String servletPath, String pathInfo, String extension, Match match) {
		// TODO need to rework match for filters to remove this method
		throw new UnsupportedOperationException("Should not be calling this method on FilterRegistration"); //$NON-NLS-1$
	}

	private void createContextAttributes() {
		contextController.createContextAttributes();
	}

	private void destroyContextAttributes() {
		contextController.destroyContextAttributes();
	}

	protected boolean isPathWildcardMatch(String pattern, String path) {
		if (path == null) {
			return false;
		}
		// first try wild card matching if the pattern requests it
		if (pattern.endsWith("/*")) { //$NON-NLS-1$
			int pathPatternLength = pattern.length() - 2;
			if (path.regionMatches(0, pattern, 0, pathPatternLength)) {
				return path.length() <= pathPatternLength || path.charAt(pathPatternLength) == '/';
			}
			return false;
		}
		// now do exact matching
		return pattern.equals(path);
	}

	protected boolean doPatternMatch(String pattern, String path, String extension)
		throws IllegalArgumentException {

		if (pattern.indexOf(Const.SLASH_STAR_DOT) == 0) {
			pattern = pattern.substring(1);
		}
		int extensionMatchIndex = pattern.indexOf(Const.SLASH_STAR_DOT);
		String extensionWithPrefixMatch = null;
		if (extensionMatchIndex >= 0 && pattern.lastIndexOf('/') == extensionMatchIndex) {
			extensionWithPrefixMatch = pattern.substring(extensionMatchIndex + 3);
			pattern = pattern.substring(0, extensionMatchIndex + 2);
		}

		if (pattern.isEmpty() && Const.SLASH.equals(path)) {
			return true;
		}
		else if (!pattern.isEmpty()) {
			// first try prefix path matching; taking into account wild cards if necessary
			if (pattern.charAt(0) == '/') {
				if (isPathWildcardMatch(pattern, path)) {
					if (extensionWithPrefixMatch != null) {
						return extensionWithPrefixMatch.equals(extension);
					}
					return true;
				}
				return false;
			}

			// next try extension matching if requested
			if (pattern.charAt(0) == '*') {
				return pattern.substring(2).equals(extension);
			}
		}

		return false;
	}

	private Pattern[] getCompiledRegex(FilterDTO filterDTO) {
		if (filterDTO.regexs == null) {
			return new Pattern[0];
		}

		Pattern[] patterns = new Pattern[filterDTO.regexs.length];

		for (int i = 0; i < filterDTO.regexs.length; i++) {
			patterns[i] = Pattern.compile(filterDTO.regexs[i]);
		}

		return patterns;
	}

	@Override
	public boolean needDecode() {
		return needDecode;
	}

}
