JSP/Servlet, そしてJavaのお勉強メモ その13

Servletでクラスファイルを更新したらTomcatを再起動しなきゃいけないもんだと思ってたけど, 違った.

                                                                                                                      • -

@IT:Java TIPS -- クラスファイルの更新時にTomcatを再起動しない方法
http://www.atmarkit.co.jp/fjava/javatips/002container002.html

                                                                                                                      • -

この↑ページに書いてあるように, おおもとの設定ファイルを編集して, reloadable=trueとすればいいみたい.
やってみたら確かに再起動しなくてもいけた.
ただし, 何回かページを更新をしてやんないと反映されないけど.


1行をPタグでくくるようにした.
OL, UL, DL, TABLEのいずれかのタグがあるとPタグでくくるのを停止する.
また, 空行を入れるとそれを反映するように, BRタグを入れるようにした.

package test.textarea;

import java.util.*;

public class TranslateInputData
{
    private String input;       // 入力文字列
    private StringBuffer output; // 出力文字列

    // == 0 : Pタグを出力
    // >= 1 : Pタグを出力しない
    private int PTAG_OFF;

    // 今読み込んでるタグが開始タグか終端タグかどうかを示す変数
    // == 1 : 開始タグ
    // == 2 : 終端タグ
    private int SLASH;

    private static Hashtable<String, Integer> map = new Hashtable<String, Integer>();

    // コンストラクタ
    public TranslateInputData(){}

    public TranslateInputData( String input )
    {
        this.input  = input + '\n'; // 念のため, 文末に改行をつけておく.
        this.output = new StringBuffer();
        this.PTAG_OFF = 0;
        this.SLASH    = 1;
    }

    public String getTranslatedText()
    {
        return output.toString();
    }

    // ULタグについて詳細なチェックを行う
    private int getResultOfULCheck( int start, int chk )
    {
        int check =  getResultOfDefaultCheck( start, chk );

        if( check > 0 ){
            if( SLASH == 2 && PTAG_OFF > 0 ){
                PTAG_OFF--;
            } else if( SLASH == 1 ){
                PTAG_OFF++;
            }
        }
        return check;
    }

    // OLタグについて詳細なチェックを行う
    private int getResultOfOLCheck( int start, int chk )
    {
        int check =  getResultOfDefaultCheck( start, chk );

        if( check > 0 ){
            if( SLASH == 2 && PTAG_OFF > 0 ){
                PTAG_OFF--;
            } else if( SLASH == 1 ){
                PTAG_OFF++;
            }
        }
        return check;
    }

    // DLタグについて詳細なチェックを行う
    private int getResultOfDLCheck( int start, int chk )
    {
        int check =  getResultOfDefaultCheck( start, chk );

        if( check > 0 ){
            if( SLASH == 2 && PTAG_OFF > 0 ){
                PTAG_OFF--;
            } else if( SLASH == 1 ){
                PTAG_OFF++;
            }
        }
        return check;
    }

    // TABLEタグについて詳細なチェックを行う
    private int getResultOfTABLECheck( int start, int chk )
    {
        int check =  getResultOfDefaultCheck( start, chk );

        if( check > 0 ){
            if( SLASH == 2 && PTAG_OFF > 0 ){
                PTAG_OFF--;
            } else if( SLASH == 1 ){
                PTAG_OFF++;
            }
        }
        return check;
    }

    private int getResultOfDefaultCheck( int start, int chk )
    {
        int check = chk;
        char c;

        // 行末までに終端タグがあるかどうかを調べる
        if( check > 0 ){
            // ここで'c'が指すものは, ' ', '>'のどちらかのハズ(コメントを除いて).
            c = input.charAt( start+check );
            for( ; c!='>'; check++ ){
                if( c == '\n' ){ return 0; }
                // ここで"c"が指すものは, ' ', '>'のどちらかのハズ(コメントを除いて).
                c = input.charAt( start+check );
            }
        }

        return check;
    }

    private int getResultOfTagCheck( int tag, int start, int check )
    {
        int chk;

        switch( tag ){
        case 31:
            chk = getResultOfULCheck( start, check );
            break;
        case 32:
            chk = getResultOfOLCheck( start, check );
            break;
        case 34:
            chk = getResultOfDLCheck( start, check );
            break;
        case 38:
            chk = getResultOfTABLECheck( start, check );
            break;
        default:
            chk = getResultOfDefaultCheck( start, check );
            break;
        }
        return chk;
    }

    // タグであれば0以上の値が, そうでなければ, 0が返戻される.
    private int getTagLength( int start )
    {
        int     check =  0;     // 検証した文字数
        int       tag = -1;     // タグならば, 0以上の値をとる

        char c;   // 一時保存用

        // 最大の長さのタグ, BLOCKQUOTEが10のため, 10個先まで検証.
        for( int i=1; i<11; i++ ){

            // 次の文字が改行, また, 空白だったならば, 終了.
            c = input.charAt( start+i-1 );
            if( c == '\n' || c == ' ' ){ return 0; }

            try{
                // <BLOCKQUOTE .... だったならば, BLOCKQUOTEの部分と一致するかどうか.
                tag = map.get( input.substring( start, start+i ).toUpperCase() );
            } catch( NullPointerException e ){
                // Hashtableに登録されていなかった.
                tag = -1;
            }

            // タグの文字列の次の文字は, 空白か, '>'でなければならない.
            if( tag > 0 ){
                c = input.charAt( start+i );
                if( c == ' ' || c == '>' ){
                    check = i;
                    break;
                }
                tag = -1;
            } else if ( tag == 0 ){
                // コメントだったならば,
                check = i;
                break;
            }
        }

        // 各タグそれぞれにおける詳細なチェックを行う.
        // tag変数からタグ長を取れるようにすれば, checkは無くてもいいかもしれない.
        // でも, それを実装するより, checkを直に渡した方が楽.
        check = getResultOfTagCheck( tag, start, check );

        return check;
    }

    // 入力文字列をしかるべき形式に変換し, StrinbBuffer型変数に代入するメソッド.
    public void translate()
    {
        int     count = 0;              // 入力文字列において読み込んだ文字数
        int    length = input.length(); // 入力文字列の長さ
        int taglength = 0;              // タグの長さ

        boolean DOCTOPLF  = false;

        char c;                 // 現在読み込んでいる文字

        // まずは文頭の処理
        if( length > 1 ){
            if( input.charAt( 1 ) == '\n' || input.charAt( 1 ) == '\r' ){
                // 次の文字が改行ならば, <br>.
                output.append( "<br>\n" );
                PTAG_OFF++;
                DOCTOPLF = true;
            } else {
                // 1行をpタグでくくる.
                output.append( "<p>" );
            }
        }

        for( count=0; count<length; ++count ){
            c = input.charAt(count);
            switch(c){
            case  '&':
                output.append( "&amp;" );
                break;
            case  '>':
                output.append( "&gt;" );
                break;
            case  '<':
                // 終端タグかどうかをチェックする.
                if( input.charAt( count+1 ) == '/' ){ SLASH = 2; }
                // SLASHは最低でも1.
                // '<', '</'の次の文字を指すようにするため.
                taglength = getTagLength( count+SLASH );
                if( taglength > 0 ){
                    // 第2引数で+1としているのは,
                    // substringが書き込む文字列の最終文字の次を指定しなければならないため.
                    output.append( input.substring( count, count+SLASH+taglength+1 ) );
                    // 読み込んだ文字数を更新
                    count += SLASH+taglength;
                } else {
                    output.append( "&lt;" );
                }
                taglength = 0;  // 初期状態に戻しておく
                SLASH     = 1;  // 必ずSLASH=1に戻す
                break;
            case  ' ':
                output.append( "&nbsp;");
                break;
            case '\"':
                output.append( "&quot;" );
                break;
            case '\'':
                output.append( "&#39;" );
                break;
            case '\t':
                // タグは空白4つ
                output.append( "&nbsp;&nbsp;&nbsp;&nbsp;" );
                break;
            case '\r':
                // こいつは無視する. 大丈夫かなぁ?
                break;
            case '\n':
                if(  count+1 < length ){
                    // なんか文字コードEUCに指定しているのに, 改行は\r\nみたい.
                    // 上手い改行の検出方法ってないかなあ.
                    if( input.charAt( count+1 ) == '\n' || input.charAt( count+1 ) == '\r' ){
                        output.append( "<br>\n" );
                    } else if( PTAG_OFF == 0 ){
                        output.append( "</p>\n<p>" );
                    } else if( DOCTOPLF == false ){
                        output.append( "\n" );
                    } else if( DOCTOPLF == true ){
                        output.append( "<p>" );
                        DOCTOPLF = false;
                        PTAG_OFF--;
                    }
                } else if( count+1 == length ){
                    // 最後の1文字のための処理
                    if( PTAG_OFF == 0 ){
                        output.append( "</p>\n" );
                    } else {
                        output.append( "\n" );
                    }
                }
                break;
            default:
                output.append(c);
                break;
            }
        }
    }

    // オブジェクト作成時, 自動で実行される.
    static {
        fillMap();
    }

    private static void setTag(String k, Integer v)
    {
        map.put( k, v );
    }

    // 値が無い場合はNullPointerExceptionを返す
    private static void fillMap()
    {
        setTag(        "!--",  0 );
        setTag(         "H1",  1 );
        setTag(         "H2",  2 );
        setTag(         "H3",  3 );
        setTag(         "H4",  4 );
        setTag(         "H5",  5 );
        setTag(         "H6",  6 );
        setTag(       "FONT",  7 );
        setTag(   "BASEFONT",  8 );
        setTag(        "BIG",  9 );
        setTag(      "SMALL", 10 );
        setTag(          "B", 11 );
        setTag(          "I", 12 );
        setTag(          "U", 13 );
        setTag(          "S", 14 );
        setTag(         "TT", 15 );
        setTag(        "SUP", 16 );
        setTag(        "SUB", 17 );
        setTag(      "BLINK", 18 );
        setTag(          "P", 19 );
        setTag(         "BR", 20 );
        setTag(         "HR", 21 );
        setTag(     "CENTER", 22 );
        setTag(        "DIV", 23 );
        setTag( "BLOCKQUOTE", 24 );
        setTag(        "PRE", 25 );
        setTag(        "XMP", 26 );
        setTag(       "NOBR", 27 );
        setTag(        "WBR", 28 );
        setTag(   "MULTICOL", 29 );
        setTag(     "SPACER", 30 );
        setTag(         "UL", 31 );
        setTag(         "OL", 32 );
        setTag(         "LI", 33 );
        setTag(         "DL", 34 );
        setTag(         "DT", 35 );
        setTag(         "DD", 36 );
        setTag(          "A", 37 );
        setTag(      "TABLE", 38 );
        setTag(         "TR", 39 );
        setTag(         "TD", 40 );
        setTag(         "TH", 41 );
        setTag(    "CAPTION", 42 );
        setTag(        "IMG", 43 );
        setTag(        "MAP", 44 );
        setTag(       "AREA", 45 );
    }
}

そろそろソース全部のっけるのが大変になってきた.
なんかオブジェクト指向っぽくない気がする.


Wiki作ろうとか考えてたけど, いきなりはたいへんだろうから, とりあえずは掲示板を作ってみようかな.
ちょうど図書館でそんな本借りてきてるし.