package project.filter.develop.struts;

import java.io.IOException;
import java.security.PrivilegedAction;
import java.util.Objects;

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

import org.apache.commons.chain2.CatalogFactory;
import org.apache.commons.chain2.Context;
import org.apache.commons.chain2.impl.CatalogFactoryBase;

import online.filter.develop.S2HotDeployClassLoader;

/**
 * HotDeployフィルタ
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public class S2HotDeployChainConfigFilter implements Filter, HbS2HotDeploy {

	/** 対象パッケージ */
	private String[] inc = null;
	/** 対象外パッケージ */
	private String[] exc = null;

	/**
	 * @see javax.servlet.Filter#destroy()
	 */
	@Override
	public void destroy() {
		return;
	}

	/**
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	@Override
	public void init(final FilterConfig filterConfig) throws ServletException {
		String val = filterConfig.getInitParameter("include");
		if (!Objects.toString(val, "").isEmpty()) {
			this.inc = val.split(",");
		}
		val = filterConfig.getInitParameter("exclude");
		if (!Objects.toString(val, "").isEmpty()) {
			this.exc = val.split(",");
		}

		setClassPath(filterConfig.getServletContext());
	}

	/**
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
	 * javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	@Override
	public void doFilter(final ServletRequest request, final ServletResponse response,
			final FilterChain chain) throws IOException, ServletException {
		doChain(request, response, chain,
			cl -> {
				try {
					final CatalogFactory<String, Object, Context<String, Object>> cf =
									CatalogFactoryBase.getInstance();
					Thread.currentThread().setContextClassLoader(cl);
					setCatalog(cf);
					chain.doFilter(request, response);
				} finally {
					CatalogFactoryBase.clear();
				}
			}
		);
	}

	/**
	 * @see online.filter.develop.S2HotDeploy#getClassLoaderSupplier(java.lang.ClassLoader)
	 */
	@Override
	public PrivilegedAction<ClassLoader> getClassLoaderSupplier(final ClassLoader org) {
		return () -> new S2HotDeployClassLoader(org, this.inc, this.exc);
	}

	/**
	 * 初期設定
	 *
	 * @param cf カタログファクトリ
	 */
	private void setCatalog(final CatalogFactory<String, Object, Context<String, Object>> cf) {
		final CatalogFactory<String, Object, Context<String, Object>> factory =
						CatalogFactoryBase.getInstance();
		cf.getNames().forEach(name -> factory.addCatalog(name, cf.getCatalog(name)));
	}
}
