/*
 * 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.taglib;

import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.fukurou.util.ToString;						// 6.1.1.0 (2015/01/17)

import static org.opengion.fukurou.util.StringUtil.nval ;

import javax.servlet.http.HttpServletResponse ;
import java.io.IOException;

/**
 * レスポンスヘッダー情報をセットするタグです。
 *
 * レスポンスヘッダーには、キャッシュコントロールやリフレッシュ(ページ自動転送)などを行う
 * ヘッダー情報をセットすることで、HTML の振る舞いを制御することができます。
 *
 * @og.formSample
 * ●形式：&lt;og:responseHeader cacheKey="[･･･]" /&gt;
 * ●body：なし
 *
 * ●Tag定義：
 *   &lt;og:responseHeader
 *       cacheControl       【TAG】レスポンスヘッダ に、Cache-Control の値を設定します(初期値:"max-age=0")
 *       contentType        【TAG】レスポンスヘッダ に、content-Type の値を設定します
 *       refresh            【TAG】レスポンスヘッダ に、refresh の値を設定します
 *       refreshURL         【TAG】レスポンスヘッダ に、refresh の値を設定するときに、指定のURLをロードします
 *       redirect           【TAG】指定されたURLへ一時的なリダイレクトレスポンスを送信します
 *       status             【TAG】ステータスコードを設定します
 *       location           【TAG】レスポンスヘッダ に、location の値を設定します
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   /&gt;
 *
 * ●使用例
 *
 * @og.rev 3.1.3.0 (2003/04/10) ResponseHeaderTag を 新規作成しました。
 * @og.group 画面制御
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class ResponseHeaderTag extends CommonTagSupport {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "6.4.2.0 (2016/01/29)" ;
	private static final long serialVersionUID = 642020160129L ;

	private String	 pragma			;
	private String	 cacheControl	= "max-age=0";
	private String	 contentType	;
	private int 	 refresh		= -1;
	private String	 refreshURL		;
	private String	 redirect		;
	private int 	 status			= -1;
	private String	 location		;

	/**
	 * デフォルトコンストラクター
	 *
	 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
	 */
	public ResponseHeaderTag() {
		super();		// これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
	}

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 3.1.9.0 (2003/05/16) refresh 属性を設定した場合は、ページの残りを処理しないように変更。
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();		// 4.0.0 (2005/02/28)
		int rtn = EVAL_PAGE;		// ページの残りを評価する。

		final HttpServletResponse response = (HttpServletResponse)pageContext.getResponse();

		if( pragma != null ) {
			response.setHeader( "Pragma",pragma );
		}

		if( cacheControl != null ) {
			response.setHeader( "Cache-Control",cacheControl );
		}

		if( contentType != null ) {
			response.setContentType( contentType );
		}

		if( refresh >= 0 ) {
			// 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
//			if( refreshURL != null ) {
			if( refreshURL == null ) {
				response.setIntHeader( "Refresh",refresh );
			}
			else {
				final StringBuilder ref = new StringBuilder( BUFFER_MIDDLE )
					.append( refresh )
					.append( "; URL=" )
					.append( response.encodeRedirectURL( refreshURL ) );
				response.setHeader( "Refresh",ref.toString() );
			}
//			else {
//				response.setIntHeader( "Refresh",refresh );
//			}
			rtn = SKIP_PAGE;		// ページの残りの処理を行わない。
		}

		if( redirect != null ) {
			try {
				response.sendRedirect( response.encodeRedirectURL( redirect ) );
			}
			catch( final IOException ex ) {
				final String errMsg = "sendRedirect に失敗しました。" + CR
							+ " URL=" + redirect + CR
							+ ex.getMessage();					// 5.1.8.0 (2010/07/01) errMsg 修正
				throw new HybsSystemException( errMsg,ex );		// 3.5.5.4 (2004/04/15) 引数の並び順変更
			}
		}

		if( status >= 0 ) {
			response.setStatus( status );
		}

		if( location != null ) {
			response.setHeader( "Location",location );
		}

		return rtn ;
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 */
	@Override
	protected void release2() {
		super.release2();
		pragma       = null;
		cacheControl = "max-age=0";
		contentType  = null;
		refresh      = -1;
		refreshURL   = null;
		redirect     = null;
		status       = -1;
		location     = null;
	}

	/**
	 * 【TAG】レスポンスヘッダ に、Cache-Control の値を設定します(初期値:"max-age=0")。
	 *
	 * @og.tag
	 * このヘッダは、クライアントに対してドキュメントをキャッシュする場合の
	 * 条件を伝えます。初期値は、max-age=0 に設定しています。
	 * 指定する値は、以下のどれかです。
	 *
	 * public        : ドキュメントをキャッシュして良い
	 * private       : ドキュメントが共有されないプライベートの中なら、キャッシュして良い。
	 * no-cache      : ドキュメントをキャッシュしてはいけない。
	 * no-store      : ドキュメントのキャッシュや、ディスク上の一時ファイルも禁止する。
	 * must-revalidate
	 *               : クライアントは、ドキュメントをプロキシではなく、本来の
	 *                 サーバーに確認する必要がある。
	 * proxy-revalidate
	 *               : must-revalidate と同じであるが、共有キャッシュに対してのみ
	 *                 適用される。
	 * max-age=xxx   : ドキュメントが、xxx秒後に陳腐化する。Expires より優先される。
	 * s-max-age=xxx : 共有キャッシュは、ドキュメントが、xxx秒後に陳腐化する。
	 *
	 * @og.rev 3.1.5.1 (2003/04/24) 初期値を、"max-age=0" に変更。
	 * @param	cc Cache-Control
	 */
	public void setCacheControl( final String cc ) {
		cacheControl = nval( getRequestParameter( cc ),cacheControl );
		if( "no-cache".equals( cacheControl ) ) {
			pragma = "no-cache";
		}
	}

	/**
	 * 【TAG】レスポンスヘッダ に、content-Type の値を設定します。
	 *
	 * @og.tag
	 * このヘッダは、これから返すドキュメントのMIMEタイプを与えます。
	 * MIMEタイプの詳しい規格は、RFC1521 と、RFC1522 です。
	 * <a href="http://www.isi.edu/in-notes/iana/assignments/media-types/media-types" >最新リスト</a>
	 * <a href="http://www.ltsw.se/knbase/internet/mime.htp">未登録タイプ(x-タイプ)</a>
	 *
	 * @param	ct content-Type
	 */
	public void setContentType( final String ct ) {
		contentType = nval( getRequestParameter( ct ),contentType );
	}

	/**
	 * 【TAG】レスポンスヘッダ に、refresh の値を設定します。
	 *
	 * @og.tag
	 * レスポンスヘッダのrefresh の値は、更新されたページをブラウザが
	 * 今から何秒後にリクエストすればよいかということを伝えます。
	 * つまり、指定した秒数後に、再リクエストさせる事が可能になります。
	 *
	 * @param	ref 画面更新(秒)
	 */
	public void setRefresh( final String ref ) {
		refresh = nval( getRequestParameter( ref ),refresh );
	}

	/**
	 * 【TAG】レスポンスヘッダ に、refresh の値を設定するときに、指定のURLをロードします。
	 *
	 * @og.tag
	 * このヘッダは、refresh と共に使用され、リクエストする場合のURLを指定します。
	 *
	 * @og.rev 3.1.4.0 (2003/04/18) 属性名変更。(refreshUrl ⇒ refreshURL)
	 *
	 * @param	refurl 再リクエストさせるURL
	 */
	public void setRefreshURL( final String refurl ) {
		refreshURL = nval( getRequestParameter( refurl ),refreshURL );
	}

	/**
	 * 【TAG】指定されたURLへ一時的なリダイレクトレスポンスを送信します。
	 *
	 * @og.tag
	 * 指定されたリダイレクト先のURLを用いて、 クライアントに一時的な
	 * リダイレクトレスポンスを送信します。
	 * URLとしては相対URLを指定することができます。
	 *
	 * @og.rev 3.6.0.0 (2004/09/17) \\\\hn51d4 などのネットワーク名への対応
	 *
	 * @param	rd リダイレクするURL
	 */
	public void setRedirect( final String rd ) {
		redirect = nval( getRequestParameter( rd ),redirect );
		if( redirect != null && redirect.startsWith( "\\\\" ) ) {
			redirect = "file://" + redirect;
		}
	}

	/**
	 * 【TAG】ステータスコードを設定します。
	 *
	 * @og.tag
	 * ステータスコードを設定します。
	 * 100 ～ 199  １００番台はおしらせ的な情報です。
	 * 200 ～ 299  ２００番台はリクエストが成功したことを表します。
	 * 300 ～ 399  ３００番台はファイルが移動したことを表します。
	 * 400 ～ 499  ４００番台はクライアント側のエラーを表します。
	 * 500 ～ 599  ５００番台はサーバー側のエラーを表します。
	 *
	 * @param	st ステータスコード
	 */
	public void setStatus( final String st ) {
		status = nval( getRequestParameter( st ),status );
	}

	/**
	 * 【TAG】レスポンスヘッダ に、location の値を設定します。
	 *
	 * @og.tag
	 * このヘッダは、ドキュメントのアドレスを通知します。
	 * ３００番台のステータスコードには、このヘッダが必ず付随する必要があります。
	 *
	 * @param	lo ドキュメントのアドレス(ロケーション)
	 */
	public void setLocation( final String lo ) {
		location = nval( getRequestParameter( lo ),location );
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 * @og.rtnNotNull
	 */
	@Override
	public String toString() {
		return ToString.title( this.getClass().getName() )
				.println( "VERSION"		,VERSION		)
				.println( "pragma"		,pragma			)
				.println( "cacheControl",cacheControl	)
				.println( "contentType"	,contentType	)
				.println( "refresh"		,refresh		)
				.println( "refreshURL"	,refreshURL		)
				.println( "redirect"	,redirect		)
				.println( "status"		,status			)
				.println( "location"	,location		)
				.println( "Other..."	,getAttributes().getAttribute() )
				.fixForm().toString() ;
	}
}
