    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.filter;
    017
    018import jakarta.servlet.ServletRequest;
    019import jakarta.servlet.ServletResponse;
    020import jakarta.servlet.http.HttpServletRequest;
    021import jakarta.servlet.http.HttpServletResponse;
    022import jakarta.servlet.ServletException;
    023import jakarta.servlet.http.HttpFilter;
    024import jakarta.servlet.FilterChain;
    025import jakarta.servlet.FilterConfig;
    026import jakarta.servlet.annotation.WebFilter;
    027
    028import jakarta.servlet.http.HttpServletResponseWrapper;
    029
    030import java.io.IOException;
    031
    032/**
    033 * CacheControlFilter は、Filter インターフェースを継承した アクセス制御クラスです。
    034 * web.xml で filter 設定することにより、Webアプリケーションへのアクセスを制御できます。
    035 * ※ @WebFilter アノテーションだけでは、上手く動かなかった。
    036 *
    037 * 本来は、org.apache.catalina.filters.ExpiresFilter を使用する所だが、単純に
    038 * キャッシュさせる設定だけ入れたかっただけなので、こちらにした。
    039 *
    040 * Cache-Control ヘッダーに対して、private,max-age=31536000,immutable を設定します。
    041 * 対象は、.css , .js , .gif , .png  です。
    042 * 大文字、小文字の区別有で、ﾘｸｴｽﾄURIの後ろ一致で判定しています。
    043 *
    044 * 【WEB-INF/web.xml】
    045 *     &lt;filter&gt;
    046 *         &lt;filter-name&gt;CacheControlFilter&lt;/filter-name&gt;
    047 *         &lt;filter-class&gt;org.opengion.hayabusa.filter.CacheControlFilter&lt;/filter-class&gt;
    048 *         &lt;init-param&gt;
    049 *             &lt;param-name&gt;debug&lt;/param-name&gt;
    050 *             &lt;param-value&gt;true&lt;/param-value&gt;
    051 *         &lt;/init-param&gt;
    052 *     &lt;/filter&gt;
    053 *
    054 *     &lt;filter-mapping&gt;
    055 *         &lt;filter-name&gt;CacheControlFilter&lt;/filter-name&gt;
    056 *         &lt;url-pattern&gt;/*;/url-pattern&gt;
    057 *     &lt;/filter-mapping&gt;
    058 *
    059 * @og.group フィルター処理
    060 * @og.rev 8.3.0.0 (2022/08/01) 新規追加
    061 *
    062 * @version  8.2
    063 * @author   Kazuhiko Hasegawa
    064 * @since    JDK17.0,
    065 */
    066@WebFilter(filterName="CacheControlFilter", urlPatterns="/*")
    067public final class CacheControlFilter extends HttpFilter {                      // HttpFilter は、Servlet 4.0
    068        private static final long serialVersionUID = 830020220801L ;
    069
    070        private boolean  isDebug        ;
    071
    072        /**
    073         * Filter インターフェースの init メソッド (何もしません)。
    074         *
    075         * 実行時のURLを標準出力に出力します。
    076         *
    077         * @og.rev 8.3.0.0 (2022/08/01) 新規追加
    078         *
    079         * @param       filterConfig    FilterConfigオブジェクト
    080         */
    081        @Override       // Filter
    082        public void init(final FilterConfig filterConfig) {
    083                isDebug = Boolean.parseBoolean( filterConfig.getInitParameter("debug") );
    084        }
    085
    086        /**
    087         * フィルター処理本体のメソッドです。
    088         *
    089         * @og.rev 8.3.0.0 (2022/08/01) 新規追加
    090         *
    091         * @param       req             ServletRequestオブジェクト
    092         * @param       res             ServletResponseオブジェクト
    093         * @param       chain           FilterChainオブジェクト
    094         * @throws IOException 入出力エラーが発生した場合、throw されます。
    095         * @throws ServletException サーブレット関係のエラーが発生した場合、throw されます。
    096         */
    097        @Override       // HttpFilter
    098        public void doFilter( final ServletRequest req,
    099                                                        final ServletResponse res,
    100                                                        final FilterChain chain )
    101                                                                throws IOException, ServletException {
    102                if( req instanceof HttpServletRequest && res instanceof HttpServletResponse ) {
    103                        final HttpServletRequest request = (HttpServletRequest) req;
    104                        final HttpServletResponse response = (HttpServletResponse) res;
    105
    106                        final int type = checkType( request ) ;
    107                        if( type > 0 ) {
    108        //                      final CCFResponseWrapper wrapResponse = new CCFResponseWrapper( hsRes,type );
    109        //                      chain.doFilter(req, wrapResponse);
    110                                chain.doFilter(req, res);
    111                                response.setHeader( "Cache-Control", "private,max-age=31536000,immutable" );
    112                                if( type == 1 ) {
    113                                        response.setCharacterEncoding( "UTF-8" );
    114                                }
    115                        }
    116                }
    117                chain.doFilter(req, res);
    118        }
    119
    120        /**
    121         * フィルターを実行するかどうか、判定します。
    122         *
    123         * @og.rev 8.3.0.0 (2022/08/01) 新規追加
    124         *
    125         * @param request ServletRequestオブジェクト
    126         *
    127         * @return      -1:対象外 1:ﾃｷｽﾄ 2:ﾊﾞｲﾅﾘ
    128         */
    129        private int checkType( final HttpServletRequest request ) {
    130                final String url = request.getRequestURI();
    131
    132                int rtnType = -1;
    133                if( url.endsWith( ".css" ) || url.endsWith( ".js" ) ) { rtnType = 1; }
    134                else if( url.endsWith( ".gif" ) || url.endsWith( ".png" )  ) { rtnType = 2; }
    135
    136                if( isDebug && rtnType > 0 ) { System.out.println( "CacheControlFilter=" + url ); }
    137
    138                return rtnType ;
    139        }
    140
    141        /**
    142         * ResponseWrapper の継承クラス
    143         *
    144         * とりあえず、Wrapper 無しでもﾍｯﾀﾞｰの設定が出来たので、今は未使用とします。
    145         *
    146         * @og.rev 8.3.0.0 (2022/08/01) 新規追加
    147         */
    148        final static class CCFResponseWrapper extends HttpServletResponseWrapper {
    149                /** オリジナルのレスポンス */
    150                protected HttpServletResponse origResponse      ;
    151
    152                /**
    153                 * コンストラクター
    154                 *
    155                 * @param       response        HttpServletResponseオブジェクト
    156                 * @param       type            -1:対象外 1:ﾃｷｽﾄ 2:ﾊﾞｲﾅﾘ
    157                 */
    158                public CCFResponseWrapper(final HttpServletResponse response , final int type) {
    159                        super(response);
    160                        origResponse = response;
    161                        origResponse.setHeader( "Cache-Control", "private,max-age=31536000,immutable" );
    162                        if( type == 1 ) {
    163                                origResponse.setCharacterEncoding( "UTF-8" );
    164                        }
    165        //              origResponse.setHeader( "Expires", null );
    166        //              origResponse.setHeader( "Pragma" , null );
    167                }
    168        }
    169}