/*
 * Copyright (c) 2009 The openGion 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 org.opengion.hayabusa.filter;

import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpFilter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.annotation.WebFilter;

import jakarta.servlet.http.HttpServletResponseWrapper;

import java.io.IOException;

/**
 * CacheControlFilter は、Filter インターフェースを継承した アクセス制御クラスです。
 * web.xml で filter 設定することにより、Webアプリケーションへのアクセスを制御できます。
 * ※ @WebFilter アノテーションだけでは、上手く動かなかった。
 *
 * 本来は、org.apache.catalina.filters.ExpiresFilter を使用する所だが、単純に
 * キャッシュさせる設定だけ入れたかっただけなので、こちらにした。
 *
 * Cache-Control ヘッダーに対して、private,max-age=31536000,immutable を設定します。
 * 対象は、.css , .js , .gif , .png  です。
 * 大文字、小文字の区別有で、ﾘｸｴｽﾄURIの後ろ一致で判定しています。
 *
 * 【WEB-INF/web.xml】
 *     &lt;filter&gt;
 *         &lt;filter-name&gt;CacheControlFilter&lt;/filter-name&gt;
 *         &lt;filter-class&gt;org.opengion.hayabusa.filter.CacheControlFilter&lt;/filter-class&gt;
 *         &lt;init-param&gt;
 *             &lt;param-name&gt;debug&lt;/param-name&gt;
 *             &lt;param-value&gt;true&lt;/param-value&gt;
 *         &lt;/init-param&gt;
 *     &lt;/filter&gt;
 *
 *     &lt;filter-mapping&gt;
 *         &lt;filter-name&gt;CacheControlFilter&lt;/filter-name&gt;
 *         &lt;url-pattern&gt;/*;/url-pattern&gt;
 *     &lt;/filter-mapping&gt;
 *
 * @og.group フィルター処理
 * @og.rev 8.3.0.0 (2022/08/01) 新規追加
 *
 * @version  8.2
 * @author   Kazuhiko Hasegawa
 * @since    JDK17.0,
 */
@WebFilter(filterName="CacheControlFilter", urlPatterns="/*")
public final class CacheControlFilter extends HttpFilter {			// HttpFilter は、Servlet 4.0
	private static final long serialVersionUID = 830020220801L ;

	private boolean  isDebug	;

	/**
	 * Filter インターフェースの init メソッド (何もしません)。
	 *
	 * 実行時のURLを標準出力に出力します。
	 *
	 * @og.rev 8.3.0.0 (2022/08/01) 新規追加
	 *
	 * @param	filterConfig	FilterConfigオブジェクト
	 */
	@Override	// Filter
	public void init(final FilterConfig filterConfig) {
		isDebug = Boolean.parseBoolean( filterConfig.getInitParameter("debug") );
	}

	/**
	 * フィルター処理本体のメソッドです。
	 *
	 * @og.rev 8.3.0.0 (2022/08/01) 新規追加
	 *
	 * @param	req		ServletRequestオブジェクト
	 * @param	res		ServletResponseオブジェクト
	 * @param	chain		FilterChainオブジェクト
	 * @throws IOException 入出力エラーが発生した場合、throw されます。
	 * @throws ServletException サーブレット関係のエラーが発生した場合、throw されます。
	 */
	@Override	// HttpFilter
	public void doFilter( final ServletRequest req,
							final ServletResponse res,
							final FilterChain chain )
								throws IOException, ServletException {
		if( req instanceof HttpServletRequest && res instanceof HttpServletResponse ) {
			final HttpServletRequest request = (HttpServletRequest) req;
			final HttpServletResponse response = (HttpServletResponse) res;

			final int type = checkType( request ) ;
			if( type > 0 ) {
	//			final CCFResponseWrapper wrapResponse = new CCFResponseWrapper( hsRes,type );
	//			chain.doFilter(req, wrapResponse);
				chain.doFilter(req, res);
				response.setHeader( "Cache-Control", "private,max-age=31536000,immutable" );
				if( type == 1 ) {
					response.setCharacterEncoding( "UTF-8" );
				}
			}
		}
		chain.doFilter(req, res);
	}

	/**
	 * フィルターを実行するかどうか、判定します。
	 *
	 * @og.rev 8.3.0.0 (2022/08/01) 新規追加
	 *
	 * @param request ServletRequestオブジェクト
	 *
	 * @return	-1:対象外 1:ﾃｷｽﾄ 2:ﾊﾞｲﾅﾘ
	 */
	private int checkType( final HttpServletRequest request ) {
		final String url = request.getRequestURI();

		int rtnType = -1;
		if( url.endsWith( ".css" ) || url.endsWith( ".js" ) ) { rtnType = 1; }
		else if( url.endsWith( ".gif" ) || url.endsWith( ".png" )  ) { rtnType = 2; }

		if( isDebug && rtnType > 0 ) { System.out.println( "CacheControlFilter=" + url ); }

		return rtnType ;
	}

	/**
	 * ResponseWrapper の継承クラス
	 *
	 * とりあえず、Wrapper 無しでもﾍｯﾀﾞｰの設定が出来たので、今は未使用とします。
	 *
	 * @og.rev 8.3.0.0 (2022/08/01) 新規追加
	 */
	final static class CCFResponseWrapper extends HttpServletResponseWrapper {
		/** オリジナルのレスポンス */
		protected HttpServletResponse origResponse	;

		/**
		 * コンストラクター
		 *
		 * @param	response	HttpServletResponseオブジェクト
		 * @param	type		-1:対象外 1:ﾃｷｽﾄ 2:ﾊﾞｲﾅﾘ
		 */
		public CCFResponseWrapper(final HttpServletResponse response , final int type) {
			super(response);
			origResponse = response;
			origResponse.setHeader( "Cache-Control", "private,max-age=31536000,immutable" );
			if( type == 1 ) {
				origResponse.setCharacterEncoding( "UTF-8" );
			}
	//		origResponse.setHeader( "Expires", null );
	//		origResponse.setHeader( "Pragma" , null );
		}
	}
}
