package org.maachang.comet.httpd.engine.errors ;

import org.maachang.comet.MaachangDef;
import org.maachang.comet.httpd.HttpdErrorDef;
import org.maachang.util.FileUtil;
import org.maachang.util.StringUtil;

/**
 * HTTPDエラーページ管理オブジェクト.
 * 
 * @version 2007/08/29
 * @author masahito suzuki
 * @since MaachangComet 1.00
 */
public class HttpdErrorPageManager {
    
    /**
     * デフォルトエラーページテンプレートファイル.
     */
    private static final String DEFAULT_TEMPLATE =
        "org/maachang/comet/httpd/engine/errors/default.error" ;
    
    /**
     * エラーページ名.
     */
    private static final String ERROR_PAGE = "error.html" ;
    
    /**
     * エラーページ用ディレクトリ.
     */
    private String errorPageDirectory = null ;
    
    /**
     * デフォルトエラーページテンプレート.
     */
    private String defaultTemplate = null ;
    
    /**
     * コンストラクタ.
     */
    private HttpdErrorPageManager() {
        
    }
    
    /**
     * コンストラクタ.
     * <BR><BR>
     * 条件を指定してオブジェクトを生成します.
     * <BR>
     * @param directory 対象のカレントディレクトリを設定します.
     * @exception Exception 例外.
     */
    public HttpdErrorPageManager( String directory )
        throws Exception {
        if( directory == null || ( directory = directory.trim() ).length() <= 0 ) {
            throw new IllegalArgumentException( "カレントディレクトリは不正です" ) ;
        }
        directory = StringUtil.changeString( directory,"\\","/" ) ;
        if( directory.startsWith( "/" ) == false ) {
            directory = "/" + directory ;
        }
        if( directory.endsWith( "/" ) == false ) {
            directory += "/" ;
        }
        this.errorPageDirectory = directory + MaachangDef.DIRECTORY_ERROR_PAGE ;
        this.defaultTemplate = FileUtil.getScriptByResource( DEFAULT_TEMPLATE,null ) ;
    }
    
    /**
     * デストラクタ.
     */
    protected void finalize() throws Exception {
        errorPageDirectory = null ;
        defaultTemplate = null ;
    }
    
    /**
     * エラー情報を取得.
     * <BR><BR>
     * エラー情報を取得します.
     * <BR>
     * @param url 対象のURLを設定します.
     * @param code 対象のエラーコードを設定します.
     * @param message 対象のエラーメッセージを設定します.
     * @param detail 対象のエラー詳細を設定します.
     * @return String エラー情報が格納された内容が返されます.
     * @exception Exception 例外.
     */
    public String getErrorPage( String url,int code,String message,String detail )
        throws Exception {
        if( url == null || url.length() <= 0 ) {
            throw new IllegalArgumentException( "引数は不正です" ) ;
        }
        if( message == null || message.length() <= 0 ) {
            message = HttpdErrorDef.convertErrorMessage( code ) ;
        }
        String path = url.substring( 1,url.length() ) ;
        if( path.endsWith( "/" ) == false ) {
            int p = path.lastIndexOf( "/" ) ;
            if( p != -1 ) {
                path = path.substring( 0,p+1 ) ;
            }
        }
        String template = defaultTemplate ;
        String useErrorPage = getErrorTemplate( code,url ) ;
        if( useErrorPage != null ) {
            template = useErrorPage ;
        }
        useErrorPage = null ;
        return HttpdErrorPageTemplate.createErrorPage(
            template,String.valueOf( code ),message,detail,url ) ;
    }
    
    /**
     * エラー情報を取得.
     * <BR><BR>
     * エラー情報を取得します.
     * <BR>
     * @param url 対象のURLを設定します.
     * @param code 対象のエラーコードを設定します.
     * @param message 対象のエラーメッセージを設定します.
     * @param detail 対象のエラー詳細を設定します.
     * @return String エラー情報が格納された内容が返されます.
     */
    public String getDefaultErrorPage( String url,int code,String message,String detail ) {
        try {
            return HttpdErrorPageTemplate.createErrorPage(
                defaultTemplate,String.valueOf( code ),message,detail,url ) ;
        } catch( Exception e ) {
        }
        return null ;
    }
    
    /**
     * エラーページを取得.
     */
    private String getErrorTemplate( int state,String url )
        throws Exception {
        String path = url ;
        int p = path.indexOf( "/" ) ;
        if( p >= 0 ) {
            path = path.substring( p+1 ) ;
        }
        else {
            path = "" ;
        }
        // どちらかのエラーページを存在する場合は、取得する.
        String codePage = new StringBuilder().append( state ).append( ".html" ).toString() ;
        String errorPage = new StringBuilder().append( ERROR_PAGE ).append( ".html" ).toString() ;
        // エラーページが存在するかチェック.
        for( ;; ) {
            String target = new StringBuilder().append( errorPageDirectory ).
                append( path ).toString() ;
            if( target.endsWith( "/" ) == false ) {
                target += "/" ;
            }
            if( FileUtil.isFileExists( target+codePage ) == true ) {
                return FileUtil.getFileByString( target+codePage,"UTF8" ) ;
            }
            if( FileUtil.isFileExists( target+ERROR_PAGE ) == true ) {
                return FileUtil.getFileByString( target+errorPage,"UTF8" ) ;
            }
            if( path.length() <= 0 ) {
                return null ;
            }
            p = path.lastIndexOf( "/" ) ;
            if( p != -1 ) {
                path = path.substring( 0,p ) ;
                if( ( p = path.lastIndexOf( "/" ) ) != -1 ) {
                    path = path.substring( 0,p ) ;
                }
                else {
                    path = "" ;
                }
            }
            else {
                path = "" ;
            }
        }
    }
    
}
