2007年12月28日金曜日

基になる RCW から分割された COM オブジェクトを使うことはできません.

 と言う、非常に分かりにくいメッセージに出くわす事がたまにありますが、未だにこの辺の仕組みが理解出来ていません orz

 このメッセージ、ExcelやWordなんかのCOMオブジェクトを使っていて、書き方を間違えると発生するものですが、以下の様な書き方をしなければ、なかなかお目にかかれません.
 いや、お目にかかりたくは無いんですけどねw

#region " USING "
using System;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
#endregion


namespace Com
{
    /// <summary>
    /// CExcel の概要の説明です。
    /// </summary>
    public class CExcel
    {
        /// <summary>
        /// 引数無しコンストラクタ
        /// </summary>
        public CExcel()
        {
        }

        /// <summary>
        /// デストラクタ
        /// </summary>
        ~CExcel()
        {
        }

        /// <summary>
        /// エラーを発生させてみるテスト.
        /// </summary>
        public void test()
        {
            // Local variable.
            ApplicationClass objExcel = new ApplicationClass();
            Worksheet objWorksheet = new Worksheet();

            // Workbook 追加.
            objExcel.Workbooks.Add(Type.Missing);

            // 1ページ目の Worksheet を取得(非常識な取得の仕方ですが)
            objWorksheet = (Worksheet)objExcel.Workbooks.get_Item(1)
                .Worksheets.get_Item(1);

            // Worksheet の名前を表示してみる.
            MessageBox.Show(objWorksheet.Name); // Sheet1

            /**
             * 本来必要は無いが、Worksheet を COM オブジェクトとしてを解放し
             * てみる.
             * 更に解放した Worksheet の Delete メソッドを呼び出してみる.
             * この時点では何故かエラーが出ない.
             * そして、Worksheet の名前を参照しようとすると
             *
             *  基になる RCW から分割された COM オブジェクトを使うことはできません
             *
             * と言う、非常に分かりにくいエラーメッセージが発生 orz
             * しかも、COM オブジェクト解放のみを実行した場合は、
             *
             *  オブジェクト参照がオブジェクト インスタンスに設定されていません。
             *
             * と言う見慣れた「ああ、インスタンス化してねーじゃん」と言うメッ
             * セージになり、Delete メソッドだけ実行した場合は、
             *
             *  HRESULT からの例外です : 0x800401A8。
             *
             * と言うエラーが参照段階で発生します.
             */
            this.releaseComObject(objWorksheet);
            objWorksheet.Delete();
            MessageBox.Show(objWorksheet.Name); // ここで例のエラーが発生.

            // Excel 終了.
            objExcel.Quit();

            /**
             * ここの COM オブジェクトリリースは必要.
             * 解放しない場合、プログラムが終了するまで Excel プロセスが継続.
             */
            this.releaseComObject(objExcel);
        }

        /// <summary>
        /// すべてのCOMオブジェクトが解放されるまで、繰り返し ReleaseComObject を
        /// 実行します。
        /// </summary>
        /// <param name="objInput">COMオブジェクト</param>
        public void releaseComObject(Object objInput)
        {
            while (System.Runtime.InteropServices.Marshal.
                ReleaseComObject(objInput) > 0);
            objInput = null;
        }

    } // CExcel
} // namespace
 ※見た通り、全く意味の無い適当な書き方です.
 ※参照追加でExcelのObjectLibraryを追加しないと動きません(念のため).

 参考に「相互運用機能アセンブリを使った複雑な COM オブジェクトの処理 - Office のメニュー ボタンが機能停止した場合の対策」と言うページも見たのですが、未だにピンと来ません.
 …私のレベルでは理解不能な話の様です orz

 嗚呼低次元低次元...

2007年12月25日火曜日

ActiveDirectoryのグループポリシー適用状況を確認.

C:\> gpresult


 gpupdate → gpresult でポリシーが適用されているか一目で分かる訳ですね.
 いや~これは便利なコマンドです.

 と言う、正に「そんな事も知らなかったのかよw」的なメモ orz


 さ、今日はクリスマスだし、更なる自虐的思想に陥る前にさっさと帰ろう.

電源設定.

 何を今更!?なメモ.

 ActiveDirectory環境でXPの電源設定周りを統一的に設定(要するにグループポリシーでゴニョゴニョ)出来ないものか、と言う話があったので調べてみましたが、どうやらXPでは無理(Vistaでは可能)な様で orz

 こんな方法でXPでも実現可能な様ですが、正直面倒この上ないので見なかった事にしたい気分ですw

 ついでに電源設定周りのレジストリ格納場所も探してる最中に見受けられたのでメモ.

 HKEY_CURRENT_USER\Control Panel\PowerCfg
 HKEY_USERS\[ユーザー]\Control Panel\PowerCfg

 と言うか、Powercfgと言うコマンド(ツール)がある事自体知りませんでしたから orz

2007年12月20日木曜日

唖然とする某システム.

 最近、某所にて某システムを触る機会がありました.
 …某某ばかりじゃ分からないけど orz
 その某システムが凄い訳です.

 PHPで書かれているんですが、まず、エラー画面にエラーハンドラで受け取ったエラー内容を「ほぼそのまま」表示します.
 ○○○.phpの○○行目で、○○関数の引数が○○だからエラーが出ましたよ、と(実際のメッセージは異なります).
 そりゃもう親切丁寧に教えてくれる訳ですよ orz

 更にエラーが発生した際、場合によってはクエリを画面に出力してくれます.
 まぁ!なんて親切なんでしょう♪ … orz
 ※これは多分意図した訳ではなく、デバッグ気分で echo ったであろうコードを削除し忘れているかと思われます

 とまぁ、致命的と思われる事はこの辺にしておき、一番衝撃的な事(いや、上のも十分衝撃的なんですが、自分でもやってしまいそうと言う意味での衝撃的)が、Ajax周りの挙動.
 私は余りそんな組み方をしませんが、

 1. 複数の選択欄(SELECT)がある
 2. 選択欄Aを選択するとAjaxが走り、サーバーへ選択欄Bのリストを取りに行く
 3. サーバーから取得したリストを選択欄Bへセットする
 (選択欄Dまで繰り返し...省略...)

 と言う「まぁ、やるっちゃーやるな」と言う処理なんですが(私は選択する度にトラフィックが発生するのが嫌で、余程膨大な選択種が無い限り最初に全部読み込みます)、今回出くわした環境がアナログ回線だったが為に、下の様な挙動を連発する訳です.

 選択欄Aで選択→選択欄Bが空欄のまま→ボーっと待つ→数秒後選択欄Bにリストがセットされる
 選択欄Aで内容1を選択→選択欄Aで内容2を選択しなおす→数秒後選択欄Bには選択欄Aの内容1に連動するリストがセット

 正直使う気が失せますね、これじゃ……
 良くAjaxでデータを読み込む時に、ローディング画像を表示しつつDIVなどで画面を保護する作りにしますが、選択欄を連動させるくらいでそんな保護しませんしねぇ.
 逆にいちいち選択内容変更する度に(選択欄を連動させる為だけに)ローディング画面になったら、Ajaxな意味が無くなるくらい煩わしくなりますし.

 まぁ、平成19年も師走を迎えた昨今、そんなWindows95を思い出す速度環境下なんて余り無いでしょうから、そんなに気にする必要も無いのかもしれませんけどw

 とは言いつつ、今回出くわした様な作りにはしない様に心掛けようと心底思った今日この頃.

/**
 * 追記.
 */
 この投稿書いてから、Gmailが高速化する手段として「メッセージをあらかじめ読み込んでおくため、メールを開くときにGoogleサーバにアクセスしなくてもよくなり、メールの表示が速くなる」(『@IT』より一部抜粋)方法を選んだ事を思い出しました.
 Ajaxも使い方次第では旧来よりユーザビリティを低下させるかもね、と.
 ※Gmailの場合、正確には「Ajaxなバックグラウンド処理で事前に読み込む」と言う方式らしい

2007年12月13日木曜日

MTOS: Movable Type オープンソース・プロジェクト.

 久々の投稿.
 仕事が忙しかった訳では無く、単に家で仕事をしていただけです.

 … orz

 そんなどうでもいい近況報告はおいておき、Movable Typeのオープンソース化プロジェクトが始まった様です.
 まぁ、前からソース確認出来てたみたいですけど、lightmaterialは余り興味が無く、一度も見た事がありませんでした.
 しかし「折角オープンソース化したんだしな」と、この機会にチラッと中身を覗いておこうと思い早速ダウンロード.

 さて、どこから見るかな~
 お!この「mtdb_base.php」って言うファイルは結構サイズがあるし、読み応えがありそうだ!
 どれどれ…


 ……ぎゃーーーー!!!
 き、き、き、汚ねぇよ!!! orz

 なんじゃこりゃ…
 いや、そりゃ読める範疇なんだけどもね.
 それにしたって、コメント全然無いし、トリッキー(初心者が見て理解不能な書き方. lightmaterialは一番嫌いです)だし、インデントがファイルによってタブ文字だったりスペースだったりするし、SQL文がコード中に直書き されてるし……

 有名所の会社でも、あんなコード書いてる所があるんだなぁ…と思い知った今日この頃.
 他の会社もあんなモンなんでしょうかね?
 ま、まさかね……w

/**
 * 追記
 */
 そう言えば、以前サクラエディタと言うソフトのソースを見た時も「色んな人が書いてるから読みにくいなぁ」と思ったものですが、私としてはMovable Typeの方がよっぽど読みにくいです(C++とPHP比較するのもアレですが).
 そんな感じです、はい.

2007年11月13日火曜日

Google デベロッパー ホーム.

後で読む.

http://www.google.co.jp/developer/prg/

2007年11月10日土曜日

WM_MOUSEWHEELメッセージ.

 「WM_MOUSEWHEEL」って、VisualStudio.Net2003(古っ)じゃ標準では使えないのか?
 普通にやると

error C2065: 'WM_MOUSEWHEEL' : 定義されていない識別子です。

 とVCコンパイラに怒られます.
 はて?
 windows.h→winuser.hの流れで読み込んで(宣言して)るはずなんだが??

 う~ん……
 久々に触ったC++(お遊びレベル)でグダグダ悩んでも仕方なし.
 さっさとgoogle先生に聞く事に.

 Windowsゲームプログラミング(と言う本の紹介ページ)

 このページの中段に

一部の開発環境を除いて、識別子 WM_MOUSEWHEEL が宣言されていないという問題が発生します。WM_MOUSEWHEEL は winuser.h ヘッダで宣言されていますが、#define _WIN32_WINNT 0x0400 が宣言されていないと認識されません。

 との一文が.
 へぇ.
 そうなのね.
 と言う事で、適切なヘッダファイル(当然「windows.h」を読み込む前)に

#ifndef _WIN32_WINNT 0x0400
#define _WIN32_WINNT 0x0400
#endif

 と追記.

 そしておもむろにビルドごー!
 おお、普通に動くではないか!!
 VS2003.Netのヤツめ、手こずらせやがるぜ!!!

 …と言うか、いい加減さっさと最新バージョン買えって話ですね orz
 「今年何年だと思ってるのさ?2007年も残り僅かだよ?w」と笑われますね orz
 金が無い.
 ああ金が無い金が無い.
 ※家で仕事(VB/ASP)するケースもあるから、Express Editionじゃ問題だし.

2007年11月2日金曜日

Google Japan Blog: 大規模日本語 n-gram データの公開

Google Japan Blog: 大規模日本語 n-gram データの公開

 n-gramは取り敢えず置いておき(貧乏人には厳しい…)、MeCabが非常に楽しそうだったので、その存在を忘れない様に走り書きメモ.
 Java用のバインディング(要するにMeCabをプログラム言語から使える用にしたもの、またはその橋渡し)もある様なので、Javaの勉強がてら触りたい.

 …そんな事妄想する前に、Javaでまともなコード書ける様にする方が先か orz

 と言うか、googleの公式blogがあるということ自体、初めて知った今日この頃.

/**
 * 2007-11-02 追記.
 */
 なんか、googleのblogに「リンクを作成」と言う項目があったから、試しにやってみました.
 こんな風に投稿される訳ですか.
 ふーん…二度と使わないと思いますがw
 本来の目的がメモなんで、リンク辿られるのもアレですし.

2007年10月27日土曜日

全角半角大文字小文字.

 今日は休日出勤.
 土曜・日曜と休みがあるだけ有り難いと(自らに)思い(込ませ)ながら仕事中.

 まったくどうでもいい話だけれども、他の社員が編集している文書ファイルを見てると、英語表記が半角だったり全角だったり大文字だったり小文字だったり(ある場所ではWindowsと書き、別の場所ではwindowsとかwindows[全角]とか…)します.
 あれってどうにかならないもんですかね?

 そういうファイルを開く度に、気になって気になって仕方がありません.
 いや、気になるというか「イライラ」します orz

 「そんな細かい事気にしてたら禿げるって!…あ…もうハゲ初期段階に突入してるか…」と思われるかもしれませんが、見た目も気になるのは勿論、データの再利用とかファイルに対して何らかの処理を行う時に面倒です.
 そんな風に書いてるから、データ処理のコードにUppercaseとかLowercaseとかはたまた半角全角変換と言う実に非効率でコスト高(実際の金額の問題は無視して、処理負荷の意味で)なコードを書く羽目になるんですよ.
 まったくもう!さっさと直しなさい!!

 …なーんて言えるのは社内だけの話で、お客さんに対しては言える訳も無く、当たり前に実装するんですけど.

 前に別のシステムで登録していたデータを移行する際、「姓と名のデータを分けて移行して」と言われたものの、どこぞの業者が作ったプログラムは『姓と名を分けずに一つの入力欄だけ設置』していた上に『姓と名の区切り文字のチェックも無し』と言う信じられない構造になっていて、データの中身を確認すると、案の定「姓と名の区切り文字が半角空白」「姓と名の区切り文字が全角空白」「姓と名の区切り文字が無い(絶望)」状態が混在.
 更にフリガナも姓と名が区切り無く保存されている上に、半角全角の区別(チェック)もなく登録されている始末.
 正にカオスなデータですw
 件数もかなりの数だったので、流石にこれは分割してDB格納するのは諦めてもらいました.
 半角全角の問題は、当然統一する様に直しましたけど.

 こんな変換作業(コード書き含む)なんて、本当に無駄な労力です.
 入力段階で(強制的に)統一しろって話ですよね.
 まぁ、プログラムはいいとして…Excelが存在し続ける限り、この変換問題は延々と続く悪寒がしますけど.
 人間諦めが肝心か…さて、さっさと帰りますか.

2007年10月23日火曜日

Windows版PHPのLDAP関数.

 一言メモ.

 以前書いたLDAP関数に関しての投稿は、Linux上で動作しているPHPで試していた訳ですが、マニュアルにある通り、Linux版ではOpenLDAPのクライアントがインストールされている必要があります.
 で、私はてっきりWindows版もOpenLDAPのクライアントが入ってないと駄目なんだろうと思っていたんですが、実は無くても全然問題ないんですね.
 これは楽だ!!

 …って、心底今更な話か orz

 マニュアルを見ると、LDAP関数の要件
LDAP サポートを有効にして PHP をコンパイルするには、 » OpenLDAP あるいは » Bind9.net から LDAP クライアント ライブラリを入手し、コンパイルしておく必要があります。

 と書いてあるから、完全に勘違いしてました.

2007年10月18日木曜日

ajaxWindows - AjaxがOSに成るのは何時の日か.

 Ajaxが今までに無いほどの繁栄を見せている昨今.
 タイトルにあるajaxWindowsの様な「AjaxなOS」がAjaxの行き着く究極なのでしょう.

 んが、正直使えたモンじゃありません orz



 確かに見た目は素晴らしいですが、動作が実用に耐えられるとは思えません.
 私がユーザー登録した9月の段階は「まぁ、ベータだから…(アルファではなかったはず)」と思っていたのですが、とても「どこでもOS」と言えるレベルではなさそうです.
 これは回線速度云々ではなく、現時点でのJavaScript自体の動作速度、言い換えればブラウザのJavaScript処理速度、ひいてはJavaScript自体の構造がOSなどのレスポンス重視の用途には「今の所」向いて居ないと言う事かもしれません.

 ajaxWindows以外にも「http://xcerion.com/」(3月にユーザー登録しましたが、まだ出来ない模様)なんかもありますが、今回のajaxWindowsを触って「あ~…根本的にAjaxでOS的な事を実用レベルで実装するのはまだまだ先の話だな」と実感した次第です.

 と言うか、Ajaxアプリ専用のブラウザとか作ったら、もう少し快適になりそうな気がしないでもないんですけどw
 まぁ、それじゃ本末転倒か.
 素直にiPod Touch触ってた方が余程先進的だと個人的には思いました.

2007年10月14日日曜日

電話番号の正規表現.

 今まで下らないと思って見てこなかったアルマゲドン.
 …不覚にも泣いてしまった orz
 あんな茶番劇に…自分で自分が情けない.

 と言うどーでもいい話に続いて、更にどーでもいい話をw
 電話番号の正規表現.
 検索かけると色々と出てきますが、心底意外にもその殆んどが怪しげな正規表現で「え〜…それじゃ抜け落ちるじゃん」と言う様な物でした.
 何で??
 みんな使う機会が多いと思うんだけどなぁ.

 勿論中には

 二度目の公開!電話番号の正規表現

 と言う様な素晴らしい正規表現も見付かりました.
 んが、そんなゴッツイ正規表現を求めるつもりは無い私の様な適当人間は、↓こんなんで十分だと思います.

public class Formatter {
    /**
     * Constructor.
     */
    public Formatter() {
    }

    /**
     * Constructor: 初期値として値を引数にとります.
     *
     * @param strValue
     */
    public Formatter(String strValue) {
        this.setValue(strValue);
    }

    /**
     * Property.
     */
    private String value;

    /**
     * Accessor: valueを取得します.
     *
     * @return String
     */
    public String getValue() {
        return (this.value != null) ? this.value : "";
    }

    /**
     * Accessor: valueをセットします.
     *
     * @param strValue
     */
    public void setValue(String strValue) {
        this.value = strValue;
    }

    /* --------------------------------------------------------------------- */

    /**
     * 電話番号として正しいフォーマットか確認します.<br>
     * 「-」(ハイフン)付きのフォーマットである必要があります.
     *
     * @return boolean
     */
    public boolean validatePhoneNumber() {
        // -> Local variable.
        String strPattern = "(?!^(090|080|070))(?=^\\d{2,5}?-\\d{1,4}?-\\d{4}$)[\\d-]{12}|" +
            "(?=^(090|080|070)-\\d{4}-\\d{4}$)[\\d-]{13}|" +
            "(?=^0120-\\d{2,3}-\\d{3,4})[\\d-]{12}|" +
            "^0800-\\d{3}-\\d{4}";

        //-> Check and return value.
        return this.checkMatch(this.getValue(), strPattern);
    }

    /**
     * 電話番号として正しいフォーマットか確認します.<br>
     * 「-」(ハイフン)無しのフォーマットである必要があります.
     *
     * @return boolean
     */
    public boolean validatePhoneNumberWithOutSeparator() {
        // -> Local variable.
        String strPattern = "(?!^(090|080|070))^[\\d]{10}|" +
            "^(090|080|070)[\\d]{8}";

        //-> Check and return value.
        return this.checkMatch(this.getValue(), strPattern);
    }

    /* --------------------------------------------------------------------- */

    /**
     * 正規表現でマッチするか確認します.
     *
     * @param strTarget
     * @param strPattern
     * @return boolean
     */
    protected boolean checkMatch(String strTarget, String strPattern) {
        // -> Local variable.
        java.util.regex.Pattern objPattern;
        java.util.regex.Matcher objMatcher;

        // -> 引数チェック.
        if ((strTarget == null) || (strPattern == null))
            return false;

        // -> Pattern/Matcherオブジェクト生成.
        objPattern = Pattern.compile(strPattern);
        objMatcher = objPattern.matcher(strTarget);

        // -> Set return value.
        return objMatcher.matches();
     }
}
 ※Java勉強中なのでコードはJava.

 "(?!^(090|080|070))(?=^\\d{2,5}?-\\d{1,4}?-\\d{4}$)[\\d-]{12}|" +

 これで固定電話番号確保(2007-10-20修正. 下部「追記 - 2」参照).
 先頭3桁が「090」「080(0800含む)」「070」以外であり且つ、市外局番は2〜5桁、市内局番は1桁(田舎の方. 北海道では普通)〜4桁(東京とか)、下4桁は固定で、ハイフン含めて合計12桁である場合、または

 "(?=^(090|080|070)-\\d{4}-\\d{4}$)[\\d-]{13}|"

 携帯の古い090と新しい080およびPHSの070から始まる電話番号の場合は、3-4-4桁フォーマットでハイフン含めて合計13桁の場合、または

 "(?=^0120-\\d{2,3}-\\d{3,4})[\\d-]{12}|^0800-\\d{3}-\\d{4}";

 フリーダイヤル「0120」から始まる電話番号の場合は、4-3-3桁および4-2-4桁フォーマットでハイフン含めて合計12桁、フリーダイヤル「0800」から始まる電話番号の場合は、4-3-4桁でハイフン含めて合計13桁(2007-10-20追記. 初回修整時に桁数ミスってました).
 これらに該当するものを電話番号として正しいものとする.

 …あれ?どこか固定で13桁になった所ってありましたっけ?
 何かニュースかWEBで見た記憶が…取り敢えず気にせずいきますw
 // TODO 後で調べる.
 ※追記 - 1参照.

 まぁ、これも正規表現かじった人に言わせれば「なんじゃそりゃw」なのかもしれませんw

 …と言うか正規表現自体が未だに良く分かりません orz

 何であんなにややっこしいんだろ.
 正規表現に触れる度に、もっと自然語(普通の言語. 要するに普段使っている言葉)と親和性の高い方法って無いの?と言いたくなります.
 アレですかね?
 頭のいい人には、正規表現も自然語と同レベルに見えるんでしょうかね?

/**
 * 2007-10-17 追記 - 1(追記の割りに長文です).
 * どうやら増えたのでは無く、今まで9桁だった固定電話番号が10桁に統合された
 * ニュースを見たのを記憶していた様です.
 * http://www.wdic.org/w/WDIC/9%E6%A1%81%E3%81%AE%E9%9B%BB%E8%A9%B1%E7%95%AA%E5%8F%B7
 * 正直今年まで9桁の電話番号があるなんて知りませんでした.
 * …正規表現で一致が抜け落ちるとか、人の正規表現についてアーダコーダ言っ
 * てる場合じゃなかったと言うオチですね orz
 * まぁ、それ以前に「0120」のケースを考えてなかった事にも気づいて、抜け落
 * ち過ぎじゃねーかよっ!と.
 * 「0120」(フリーダイヤル)の場合って、ハイフンの入れる位置が「極企業側
 * の事情」によって変わりますので、4-2-4と4-3-3を想定しないといけません.
 * と言う事で、週末0120について更に追記予定.
 * ん?ハイフン無しのケース?(と言う事を知人に言われましたw)
 * 正直それは「仕様を見直した方がいい」と言いたいのが本音です.
 * それって姓と名を区切り無しに管理しているのと同じです.
 * 印刷する時、市外局番・市内局番・下四桁を区切らず(区別せず)に数値だけ
 * で印刷するんですか?と.
 * 明確に区分されているものを「無かった事に」するんですか?と.
 * そう言う事です…とは言え、「前のシステムからデータ引き継ぐ段階で既にハ
 * イフン無かったんだから仕方ねーだろ!」とか言うケースも有り得ると言えば
 * 有り得なくも無いので、それも週末に.
 * って、別に改めて書く程の事でも無いんですけど.
 * 一応動く事を確認しないと気が済まないので、改めて出直します.
 */

/**
 * 2007-10-20 追記 - 2.
 * フリーダイヤル「0120」および「0800」を追加してみました.
 * ついでに固定電話番号判定部分で括弧が1つ多かったので除去 orz
 * 更に、固定電話番号12桁(ハイフン含む)の場合、先頭に「090」「080」
 * 「070」が先頭に来た場合は除外する記述「(?!〜)」を追加してみました.
 * …何か、やればやるほど抜けが見付かるダメっぷり orz
 */

2007年10月13日土曜日

Javaの勉強 - Post2.

 今日も事前知識0でJavaと対戦中.
 Javaにまったく相手にされてない感じですが orz

 私の様なずぶのJava素人が引っかかりそうな点をいくつか.

◇ServletContext


 ASP.NetなどでもHttpContextと言う(コード本体以外の)クラスで使うとコードが汚くなる上にそれって反則技じゃん!でお馴染みの存在がありますが、JavaのServletContextとは異なる様だ(何方かと言うとHttpServletRequestの方が近いか?).
※Javaのcom.sun.net.httpserver.HttpContextは全くの別物.
 ServletContextはアプリケーション全体で共有のObjectらしく、セットされた値はクライアントの別を問わず共通になる.
 ASP.NetではHttpContextをaspxから直接呼び出す事は殆んど無い(少なくとも私は使わない)けど、Java(Servlet+JSP)のServletContextではASP.Netのaspxに当たるJSPから呼び出されるケースもある様だ.
 Frameworkなどを使わず、純粋にServletからJSPに値を渡す際にもっともポピュラー(?)な方法が以下の様な方法だと思われます.

【Servlet Test.java】
[省略...]
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //-> get servlet object.
    javax.servlet.ServletContext objServContext = getServletContext();

    //-> set attribute on servletcontext.
    objServContext.setAttribute("TestData", "This is a test.");

    //-> get dispatcher object, and forwarding.
    javax.servlet.RequestDispatcher objDisp = request.getRequestDispatcher("/test.jsp");
    objDisp.forward(request, response);
}
 ※何で名前空間フルで書いてるんだよwと思うかもしれないけど、私の様な素人にしてみればServletContextやRequestDispatcherがどの名前空間に属しているのか覚えるには、javax.servlet.*とimportするより、フルで書いた方が覚えると思う.

【JSP test.jsp】
<%
    javax.servlet.ServletContext objServContext = getServletContext();
    String strTest = (String)objServContext.getAttribute("TestData");
    println(strTest);
//-> 結果
This is a test.
%>


 非常に便利です.
 ServletからJSP、はたまたServletからServlet等、Dispatcherでforward/includeした場合や、response.sendRedirectした場合においても使用可能です(スコープがApplicationだから普通はHttpSession使いますけど).

 しかし、このServletContextが妙.
 Servletでは上記の様に「getServletContext」で取得しますが、何故かJSPでは「application」で代替する事が出来る.
 ↓こんな感じで.

【JSP test.jsp】
<%
    String strTest = (String)application.getAttribute("TestData");
    println(strTest);
%>


 確かにこっちの方がスマートだ.
 んが、だったらServletでも「application」って使えてもいいじゃない orz
 何でこんな事になってるんだろう?
 と言う事で調べてみると、「out」や「session」と同じ様に「暗黙的に宣言されているオブジェクト(暗黙オブジェクト)」と言う存在らしい.
 ふーん.
 慣れれば楽だけどなぁ…だから何でServletじゃ使えねーんだよ!と混乱しそうで恐い.

 その他にもServletに関する各種情報を取得・設定出来ます.
 例えばJSPで
<%
    out.println("Servlet Version : " + application.getMajorVersion() + "." + application.getMinorVersion());
;//-> 結果
Servlet Version : 2.4
%>

 なんて事を書くと、Servlet自体のバージョンも取得出来ました.
 …使いどころが思いつきませんがw


◇getAttribute / setAttribute


 上記にある様に、あるインターフェイスに「getAttribute」および「setAttribute」メソッドが存在する場合、各オブジェクトにAttribute(属性)をセットしたり取得したり出来ます.
 主にServletとJSPでの連系や、Application共通での値の保持、Session共通での値の保持なんかに使う事になりそうです.

 Servlet→JSPでこのgetAttribute/setAttributeを使用する場合は、Attributeをセットするスコープ(何ていうか…要するに適用範囲と言いますか境界と言いますか…スコープです)が重要らしい.
 まぁ、ServletContextで少し触れた様に、Application/Session/Requestで使い分けないと大変な事になるから、別にJavaに限らずWebアプリケーションでスコープを気にするのは当たり前ですねw

 Applicationスコープ … アプリケーション(自分で作ったアプリケーション)内で共通
 Sessionスコープ … クライアント別(1クライアントに対して共通)
 Requestスコープ … リクエスト別(1回リクエスト内でのみ共通)

    javax.servlet.ServletContext objServContext = getServletContext();
    objServContext.setAttribute("TestData", 1);

    javax.servlet.http.HttpSession objSession = request.getSession();
    objSession.setAttribute("TestData", 1);

    request.setAttribute("TestData", 1);



 はぁ…
 それにしても全然Java勉強が捗らない orz
 新鮮で楽しいと言えば楽しいんですけど、頭に入るのにここまで時間がかかると、普通に使えるようになる気が一切しませんから…

2007年10月11日木曜日

後で読む.

 マイコミジャーナル『実践サンプルで学ぶStruts 2 - 生まれ変わった定番フレームワークを徹底解説』
 http://journal.mycom.co.jp/special/2007/struts2/001.html

※この投稿は会社でチラ見して「後で自宅で詳しく見よう」と思っていたにも関わらず自宅に帰ったら見ようと思っていたページを見つけ出せなかったorz と言う間抜けな状況を解決する為の付箋紙的な投稿です.

2007年10月8日月曜日

OpenSourceのソースを見るのは何時の日か.

 休日出勤お疲れ様でした>自分.
 そんな事どーでもいいんですがw

 先日Microsoftから「.Net Frameworkのソースコードを公開する準備がある」と言う「今更かよ」なニュースが聞こえてきました.
 今の時代、開発言語をオープンにして(…ソースをオープンにしただけでオープンソースか?と言われると現在の感覚から言えば「オープンソースでは無い」でしょうね. まったく紛らわしい言葉です. オープンソースって)、開発者からのフィードバックでより良い開発環境を構築していくのは至極当然の成り行きか、と思いました.

 …んが.
 実際の所、私の様な低レベル人間はオープンソース(広い意味で)のプログラムでもソースコードなんて見ちゃいないじゃん、と言う実にネガティブな事実に気づいた今日この頃.
 そうだよね.
 数年前にWindows2000のコードが流出した事件がありましたが、私がそのコードを見た所でちんぷんかんぷん120%ですよ.
 何で100%を超えると行き成り120%に行く人が多いのかと言う疑問と同じくらいちんぷんかんぷんです.
 あのソースコード流出で狂喜乱舞したハッカーorクラッカーな人と言うのは、ある程度の知識を有した人だけの話な訳ですよ.
 だから、当時の私(今現在、何の進化もなし)は「ふーん、で?」な感想を持った事を覚えています.

 せっかくのオープンなソースをまったく把握する事が出来ない私.
 何時になったらそんなエクセレントなソースコードが読めるようになるんだろうか orz
 もったいないもったいない…

2007年10月7日日曜日

Javaの勉強 - Post1.

 ひっそりと長らく停止していたJavaの勉強.
 今日からまた週2時間くらいの勢いで再開予定 orz

 まぁ、アレです.
 仕事が忙しいので.
 明日も休日出勤だし.
 本当は毎晩ビール飲んだ暮れてるのが原因だけど orz

 と、それは置いておき、以前勉強した6時間分はすっかり頭の中から抜け落ちていたので、また第1歩からJavaを検証してみます.
 今回はStrutsをいきなり使ったりせず、Java(JSP/Servlet)そのものをいじくります.
 未だにTomcatとGeronimoの違いがよく分かりませんが(前者がJSP/Servletコンテナ・サーバ、後者がJ2EEコンテナ・サーバー(Application Server)…と言われてもねぇ)、それは今のところ無視して、普通にJSPとServletを動かして.

 で、再開1日目にして早速つまづきましたw

 Servletを触っていて、ふと「あれ?POSTされたデータのエスケープって、全部自分でやらないとダメなの?(自動で処理してくれるクラスって無いの?)」と言う疑問が沸き上がり、ちょろちょろと調べてみましたが、いまいち的を得た回答ページを見つける事が出来ず、『取り敢えず』以下の様なクラスを書いてみる事に.

package com.blogspot.lightmaterial.core.String;

import java.util.regex.*;

/**
* 文字列に対するセキュリティ処理を実装します.
*/
public class SecureString {
    /**
     * Property.
     */
    protected String value = null;


    /**
     * Constructor.
     */
    public SecureString() {
    }
    public SecureString(String strValue) {
        this.setValue(strValue);
    }


    /**
     * Accessor.
     */
    public String getValue() {
        return this.value;
    }

    public void setValue(String strValue) {
        this.value = strValue;
    }


    /**
     * Htmlタグをエスケープします.
     * @access public
     * @param void
     * @return String
     */
    public String toEscape() {
        //-> Local variable.
        int nIndex = 0;
        String strTarget = new String();
        String[] strPattern = {"<", ">", "'", "\""};
        String[] strReplace = {"&lt;", "&gt;", "&#039;", "&quot;"};

        //-> Check value property.
        if (this.value == null) return "";

        //-> Preserve value property.
        strTarget = this.value;

        //-> Replace value.
        for (nIndex=0; nIndex<strPattern.length; nIndex++)
            strTarget = this.doReplace(strTarget, strPattern[nIndex], strReplace[nIndex]);
        strTarget = Matcher.quoteReplacement(strTarget);

        //-> Set return value.
        return strTarget;
    }


    /**
     * 文字列をそのまま返します.
     * @access public
     * @param void
     * @return String
     */
    public String toString() {
        return this.value;
    }


    /**
     * 文字列を置換します.
     * @access protected
     * @param String Target
     * @param String Pattern
     * @param String Replace
     * @return String
     */
    protected String doReplace(String strTarget, String strPattern, String strReplace) {
        //-> Local variable.
        Pattern objPattern = null;
        Matcher objMatcher = null;

        //-> Replace target value.
        objPattern = Pattern.compile(strPattern);
        objMatcher = objPattern.matcher(strTarget);
        strTarget = (objMatcher.replaceAll(strReplace));

        //-> Set return value.
        return strTarget;
    }
}

 Stringを使いまわしてるので、メモリが無駄になってる上にエラー処理を一切していないと言う恐怖のコードですが、Java自体よく分かってない上に適当に書いてるので気にせず行きましょう.

 上記のコードを書き終わり、ServletのgetParameterの戻り値に適用.
 「…一応普通に動いてるな…」とは思ったのですが、何しろこんな書き方で正しい訳が無い.
 と言うか、書き方以前にきっとどこかにエスケープするクラスなりメソッドがあるはずなんですが、それが見つけられません.

 そう.
 それもこれもJavaのドキュメントが原因です.
 Javaのドキュメントって、親切そうでいて、以外と使い勝手が悪い様な気がしてなりません.
 それともPHPの親切なドキュメントに慣れすぎているのが悪いんでしょうか?
 正直、あの悪名高きMSDN(サブスクリプションじゃなくてヘルプの方)よりも『個人的には』使い勝手が低い様な気がします.
 いや、クラスの把握とかメソッドの把握にはいいんですが、何しろサンプルが異様に少ない.
 javadocで生成しているが故の制限なのかもしれませんが、正直私の様な初心者にはヘルプにサンプルが載ってないのは致命傷です orz

 こんな調子じゃ、これから先のJava勉強は茨の道確定ですね.
 明日も仕事だし、今日は諦めてさっさと寝よっと.

2007年10月4日木曜日

OpenLDAP for Win32 - その1.

 OpenLDAP for Win32の設定やらでひっかかった所を忘れない内に書きなぐる予定です.

 先日書いた様に、PHPのLDAP関数でActive Directoryには接続・認証出来たので、今度はOpenLDAPで試します.

 Linuxでやろうかとも思いましたが、面倒なので 先にWindows版からやった方が敷居が低いかな?と思い、以下のソフトをインストール.

 OpenLDAP for Win32
 ※2008-03-28追記 気づけば2回目書く前に「Project suspended」だそうです orz
  まだ http://download.bergmans.us/openldap/ ここからダウンロード可能ではありますが

 インストールは普通に終了.
 ※時間があれば手順追って書きますが、今は時間が無いのでパス.

 次に設定を.
 『取り敢えず』動かしてみる事が目標なので、WEB上にあった設定例通り、以下の様に設定.

suffix[tab]"dc=example,dc=com"
rootdn[tab]"cn=Manager,dc=example,dc=com"
rootpw[tab]secret
 ※『[tab]』はTAB文字(\t). その他は変更なし.

 そしてOpenLDAPサーバーを徐に開始(コントロールパネル→「管理ツール」→「サービス」→「OpenLDAP」を開始).
 問題なく起動した模様.

 次にTOPツリーと言う物を作成するらしい.
 Active Directoryで言う所の…何に当たるのかは不明w
 恐らく、Active Directoryを構築する際に「新しいドメインツリーを作成」とか「既存のドメインツリーに…」等々選択する項目の「最初のドメインツリーを作成」と言うものに当たるのでしょう.

 と言う事で、早速ツリーやOU(OrganizationUnit. 綴りが合っているかは未確認)、ユーザーなんかを作成する事が出来るコマンド「ldapadd」を実行する事に.

D:\OpenLDAP> ldapadd -x -D "cn=Manager,dc=example,dc=com" -w secret
ldap_bind: Invalid credentials (49)

 … orz
 なんじゃそりゃ.
 「ldap_bind: Invalid credentials (49)」で検索してみるも、結構色んな原因があるらしく、ページを見つける度に設定ファイルやら何やらいじくりまわす事数十回.
 これ↓が原因だった.

何故Appleのサイト?なMLから抜粋
> OK, I think I see the problem... it looks like it's not possible to do a simple bind against the rootdn if your password is specified in cleartext. The workaround would be to use slappasswd like this:
>
> % slappasswd -s secret
> {SSHA}ioGadl0574KxRPecJ7Pb5q33j2x/Fi3w
 ※注)ハッシュ結果はコマンド実行毎に異なります.

 …あ、そう.
 そんなに単純な事なのかよっ! orz
 確かに設定ファイルには

 Cleartext passwords, especially for the rootdn, should be avoid.

 とは書いてあるが、「駄目」とは書いてないじゃない orz
 と言う事で、先のAppleMLの続きを読むと…

> I believe this is due to Mac OS X's version of OpenLDAP being built with --disable-cleartext.

 アレか.
 OpenLDAP for Win32では「--disable-cleartext」なオプションが適用された状態でビルドされているってのか?
 …ダウンロードサイトなりREADME読めば、きっとちゃんと書いてあるんでしょうね orz
 はい、結局その辺すっ飛ばしてる私が悪いと言う事で.
 結局下記の通り実行.

D:\OpenLDAP> slappasswd -s secret
{SSHA}Fa6TV9xYXXh+iWrXqwRWj3fm1aTpylEt
 ※注)ハッシュ結果はコマンド実行毎に異なります.
 そして設定の「rootpw」を変更.

suffix[tab]"dc=example,dc=com"
rootdn[tab]"cn=Manager,dc=example,dc=com"
rootpw[tab]{SSHA}Fa6TV9xYXXh+iWrXqwRWj3fm1aTpylEt
 ※『{SSHA}』から記述するので注意.

 今日も今日とて時間の無駄!!!
 自分がアホ人間である事を再認識した今日この頃.
 続きはまた今度.

2007年10月2日火曜日

PHPのLDAP関数でActiveDirectoryに接続 - その2.

 メモ走り書き.

 ActiveDirectoryにはuidが存在しない様だ.
 へぇ~…って、じゃあログインユーザー自身の情報をどうやって取得すればいいんだよ!? orz

 普通に考えればldap_searchのフィルタに

 '(uid=' . $userid . ')'

 の様に指定するんだろうけど、uidが存在しないんじゃなぁ…
 と言う事でインターネットの海にどっぷりと沈みこみ、数時間後にようやく発見.
 何でこんなに時間がかかったかは秘密.
 秘密と言うか「cn」や「uid」をAttribute(属性)と呼ぶ事が分からなかったが為に、かなりのタイムロス orz

 で、結局ズバリのページを見つけて歓喜↓

 LDAP Attributes from Active Directory Users and Computers
 ※画面を少し下にスクロールしたら表があります.

 「uid」の代わりに「sAMAccountName」(または「userPrincipalName」)を使えそうです.
 これで心おきなく情報を取り放題ですよ.


$objConnection = ldap_connect('ldap://example.com', 389);
  or die('could not connect Active-Directory.');
ldap_set_option($objConnection, LDAP_OPT_PROTOCOL_VERSION, 3)
  or die('could not set protocol-version...');

if (! $objConnection) die('connection-object is empty.');
if (! @ldap_bind($objConnection, 'userid@example.com', 'password'))
  die("error.<br>reason... " . ldap_error($objConnection) . "<br>");

if ($objResult = @ldap_search($objConnection, 'OU=exampleou,DC=example,DC=com', '(sAMAccountName=userid)', array('cn', 'sAMAccountName', 'userPrincipalName', 'mail'))) {
  $aryResult = ldap_get_entries($objConnection, $objResult);
  print_r($aryResult);
} else {
  echo 'could not get entries.<br>';
}
ldap_unbind($objConnection);
echo 'finish.';
 ※タグべた書きなのでコードが読みにくいと言うか汚いと言うか投げやりなのは気にしない方向で.

PHPのLDAP関数でActiveDirectoryに接続.

 メモ走り書き.

 PHP4の環境からActiveDirectoryでの認証が必要になったのでテスト.

 ・ADサーバー : Windows Server 2003 Standard Edition

 マニュアルに従い、ldap_bindの第二引数にdnとして

  'cn=userid,ou=exampleou,o=excom,c=JP'
  'uid=userid,dc=example,dc=com'

 等々つっこんでみましたが、
Warning: ldap_bind(): Unable to bind to server: Invalid credentials in ....

 とエラーが出るばかりで認証出来ず.
 何でだ?何でだ?と頭を悩ませる事1時間.

 …ん?これって普通に「userid@example.com」形式じゃ駄目?
 と思い至り、早速やってみると……普通に接続しやがりました orz


$objConnection = ldap_connect('ldap://example.com', 389);
  or die('could not connect Active-Directory.');
//-> ↓2007-10-02追記(これもセットした方が良さそうです)
ldap_set_option($objConnection, LDAP_OPT_PROTOCOL_VERSION, 3)
  or die('could not set protocol-version...');

if ($objConnection) {
  if (@ldap_bind($objConnection, 'userid@example.com', 'password')) {
    echo "success.<br>";
  } else {
    echo "error.<br>reason... " . ldap_error($objConnection) . "<br>";
  }
  ldap_unbind($objConnection);
}


 まぁ、あれです.
 アホです.
 生粋のアホです orz
 また今日も時間を無駄にした...

2007年9月28日金曜日

データベースへの追加・更新…どのクラスで実装すべき?

 何を今更…と言う様な話なのは重々承知ですw

 PHP4もライフサイクルが終了しますので、来年を持って会社で開発・使用していたFrameworkも終了し、ZendFrameworkに乗り換え様かと会社のSEさんが言ってました.

 そうだよね.
 と言いますか、ぶっちゃけ乗り換えがかなりの勢いで遅いですw
 しかしそれもPHP4で運用している環境をサポートしなければならなかったが故(ZendFrameworkはPHP5.1.4以降で動作).
 致し方なしと言った所でしょう.

 所で、lightmaterialを含め会社の人はPHP/.Netを使っているんですが、.Netの影響か会社のPHPFrameworkではDBに対するINSERT/UPDATE/DELETEをマネージャで実装しています.
 勿論正確にはDBAdapter(DataBase用のアダプタ)のメソッドを呼び出すのがマネージャな訳です.
 ADO.Netも似た様な構造です.
 fillしたデータの各行に対して変更を加え、それらDBへのコミットはDataAdapterから行いますが、それを呼び出すのは当然マネージャなりデータを操作するクラスだったりします(個別に操作する別の方法もありますが、オブジェクト指向としては醜い方法です…と思いますw).

 が、ZendFrameworkのマニュアルを読むとDataRowクラスに「save」メソッド(追加・更新をDBへ反映させるメソッド)が実装されています.
 要するに

  $objRow = $objTable->createRow();
  $objRow->save();
  //-> 酒飲みながら流し見してたので本当にTableからcreateRowするかは確認してませんが、普通に考えればTableクラスから生成するかと.

 な訳ですよ.
 …いや、確かにそう言う実装方法も色々と見て来ましたので、別に戸惑う事でも何でもないんですが、ふと「あれ?DBへの追加・更新用のメソッドって、どこに実装すべきなんだ?どこに実装するのがエクセレントなんだ?」と言う疑問が湧き上がって訳です.

 実際の所、どちらの方がスマートなんだろう?
 各Rowに対する変更をTableオブジェクトでストアして一気にコミット…大量のデータが変更される環境では、トラフィック効率が非常に魅力的な方法です(リアルタイム性に欠けるんですがw).
 一方、各Rowにsave/deleteメソッドが実装されていると、小回りが効くと言うか、何かしらのインポート処理では無い限り、こちらの方がリアルタイム性+トラフィック効率が良い様な気もします(さっきと書いてる事違うじゃない…と言う事は無く、一度に大量の処理が発生する場合は前者の方がトラフィックが減りますが、1レコードしか更新しない場合には後者のほうがトラフィックは少なくなります).
 ただしこの方法、数万レコードのインポート処理が発生するプログラムの場合、相当処理が遅いんじゃないの? orz

 うーん.
 難しい.
 Javaのデータベース周りって、どっちの方法がスタンダードなんだろ?
 どちらのアプローチも間違いじゃないから悩ましい.
 でもZendFrameworkに乗り換えるのは殆ど決定事項みたいですので、これからは2つのアプローチに慣れる必要がありそうです.

 それにしても、会社のFrameworkってプログラム量が凄い少なくて済む(と言うか、かなりの勢いで全自動)から気に入ってたんですけどねぇ.
 ちょっと残念です.

2007年9月25日火曜日

SafariのLabelエレメント.

 ちょっと仕事中だけど忘れない様にメモ.
 さっさと書きなぐります.

 Macの標準ブラウザであるSafari.
 会社には古いPowerPC系のMacしかないんだけど、そいつに入っているSafari(1.3.x系)ではLabelエレメントに対するJavascriptの取扱がちょっと変(もしかすると、この挙動が正規の動きなのかもしれないけど).

<form name="test_post" method="post">
<label onclick="javascript: alert(this.form.name)">テスト</label>
</form>

 こんな感じで書くと、Formの名前は拾ってくれません(Labelエレメントの「this」そのものが無効. IEやFirefoxは拾います).
 私の中ではこの状態を「Safariの挙動」として把握していたのですが、ふとWindows版のSafariで同じ様なJavaScriptを動かしてみると、正常(?)に動作しやがります.

 …で、結局どの挙動が正常なんだ? orz

 今回はWindows版しか試してませんが、もしかしてIntel Mac用(MacOS X 10.4.x)のSafari(2.0.x)でも普通に動くのか??
 むしろ1.3.x系Safariには、こんな下らないバグがずーっと残ってたとでも言うのか??

 うーん…今現状Intel Macが手元に無いから試しようが無いしなぁ~
 ちらっと検索しても、なかなか該当する記事を見つける事が出来ませんでしたし.
 これを口実に会社でIntel Mac買ってもらうかなw

2007年9月21日金曜日

PDF出力が一対一の直つなぎ環境で出力されなかった問題.

 先日書いた一対一の直つなぎ環境だとPDFが出力されない、と言う問題.
 なんの事は無い、単にサーバー側のDNS設定がおかしかっただけでした orz

 誤設定 → ルータ環境下でのDNS設定のまま
 正設定 → 直つなぎ相手または自分

 …って…んが?
 何でだ?
 そう言うもんなのか?
 DNS設定がおかしいと、HTML/PHPは正常に表示されるが、PDF出力(PHPから生成)の場合は表示されないって?
 そんなバカな話あるのか?

 うーん…と言う事で、やっぱりコードが悪いのかもw

 これは後日要確認!(と書いて調べてない事が山ほどある事は忘却の彼方へ…時間見て遣り残してる確認事項終わらせないとなぁ).

2007年9月18日火曜日

今宵は愚痴を.

 18日22時現在…36時間起きっぱなし、ついさっきまで仕事しっぱなしの状態 orz
 昨日は祝日なのに現時点で36時間…そう、休日仕事からのブチ抜きと言う最悪状態ですw

 いや、自分が悪い部分もあるからある程度仕方ないと思うけど、流石に36時間頭フル回転の状態を続けると心身ともにぐったりです.
 ただ、不思議な事に眠気はさほどありません.
 朝が眠気のピークで、後はダルイだけです.
 しかも余り普段と変わらないダルさ.
 それどころか、さっきシャワーを浴びながら「このまま今日も徹夜で行けるんじゃ?」と思ったから自分が怖い.

 因みに、仕事の山場を過ぎて終焉を迎えようかと言う時に「PDFがインターネットに繋がっている環境だと出力されるが、一対一の直つなぎ等のクローズドなネットワーク環境だと出力されない」と言う意味不明な現象に出くわしましたが、思考回路が焼き付きそうだったので放棄してきました orz
 他のマシンだと問題無いので、たぶんコードじゃなくてネットワークの設定だとは思うんですけど、PDFが出力されないクローズドなネットワークでも普通にページ(スクリプト)の表示は出来るんだよなぁ…何だろ??
 正に意味不明.
 寝てすっきりすれば直ぐ解決と言う楽な話に…はならないか orz

 さ、悩みは明日に回してさっさと寝よ.

2007年9月9日日曜日

PHPの配列によるメモリ消費.

 久々更新.

 前から思っていましたが、何故PHPの配列はあんなにメモリを消費するんだろ.
 大きいデータの場合、文字列→配列へexplodeなりすると、メモリ消費量が一気に10倍程度まで跳ね上がります orz
 この傾向は当然ながらデータサイズが小さい物より大きいものの方がより顕著です.
 迂闊に大きいデータを配列化しようものなら、貴重なメモリ資源が喰い散らかされてしまいます(終了時には解放されますが、Linuxのメモリ最適化処理なんかの環境下だと、終了後も一見掴みっぱなしに見えるから気持ち悪い…).
 例えばデータベース.
 データベース回りの機能をクラス化すると、大抵SELECTクエリの結果データを配列へ格納する様に作ると思いますが、この時も直接mysql_fetch_xxxxで処理を回すより結構なメモリ消費量となってしまいます.
 更に、データベースから取得した配列データのエンコードを変換して出力したいとした時、利便性から「mb_convert_variables」(配列データ中のエンコードを指定のエンコードに一括変換する関数)を使うケースが多いと思いますが、この「mb_convert_variables」も曲者で、処理後のメモリ消費が処理前の倍近くになってしまいます.
 分かり易く書くと↓こんな感じ.

echo "MEMORY0 : " . number_format(memory_get_usage()) . " byte(初期値)<br>";

$strBuffer = str_repeat("ABCDEFG,", 10000);
echo "MEMORY1 : " . number_format(memory_get_usage()) . " byte(文字列生成)<br>";

$aryBuffer = explode(",", $strBuffer);
echo "MEMORY2 : " . number_format(memory_get_usage()) . " byte(配列生成)<br>";

unset($strBuffer);
echo "MEMORY3 : " . number_format(memory_get_usage()) . " byte(文字列解放)<br>";

mb_convert_variables("SJIS-win", "UTF-8", $aryBuffer);
echo "MEMORY4 : " . number_format(memory_get_usage()) . " byte(mb_convert_variables実行)<br>";

unset($aryBuffer);
echo "MEMORY5 : " . number_format(memory_get_usage()) . " byte(配列解放)<br>";

 ※PHP5.2.1以前の場合、「memory_get_usage」は「--enable-memory-limit」付きでメイクする必要があります.

 結果↓

MEMORY0 : 59,160 byte(初期値)
MEMORY1 : 139,568 byte(文字列生成)
MEMORY2 : 1,045,532 byte(配列生成)
MEMORY3 : 965,600 byte(文字列解放)
MEMORY4 : 1,637,344 byte(mb_convert_variables実行)
MEMORY5 : 91,424 byte(配列解放)


 内部で単純に複製して変換しているからなのかもしれませんが、メモリ消費が変換対象の配列変数を解放するまで掴みっぱなしになるのは如何なものかと…

 まぁそんな事言い出すと、全部変数解放した後の消費量も気になるじゃねーか!って話になりますけどw

 こうして考えると、世にあるPHP用Frameworkがそれぞれどの程度のメモリ消費なのか、見比べてみるのも面白いかもしれません.
 同等の機能を実現出来るFrameworkなら、エコなコードの方がいいに決まってますから.

2007年8月23日木曜日

Windows Live Writerで試し書き.

 と言う事で、タイトル通りWindows Live Writerで試しに投稿しようとしてます.

 実際に上手く行くかは分かりませんがw

 と言うか、共通APIを使っているからなのか、カテゴリまでインポートしてくれるんですねぇ.

 …私が時代遅れなだけか orz

 所々動きがおかしいですが(まだBeta版だから仕方ないけど)、Windowsで書くならいいかも(他のblogエディタ使用経験なしw).

 何よりbloggerでも自動認識したのが好印象.

 MSにしてはやりますな.

 さて、投稿実行実行っと.

/**
 * 2007-08-23 23:33追記.
 */

 …改行するのに、Shift+EnterじゃないとPタグで改行されるんだ orz
 この辺は使い難いです.
 まぁ、よくよく考えたら、普段Linuxで投稿してるから関係ないっちゃー関係ないですねw
 と、微妙に追記動作テスト.

MySQLで数値データを桁区切り(3桁区切り).

 to_charが無いMySQL.

 ◆ FORMAT(X[データ],D[小数点以下桁数])
  Select FORMAT(suchi, 0) as suchi From TestTable;

 100%何を今更って話ですがw

 今までデータの成型はコード側で行う事が多かったんですが、諸事情でSQL文で成型する事に.
 「SQL上で成型する場合はto_charを…ってMySQLには無いんだった orz」と言う、常人にしてみれば馬鹿馬鹿しくて俄かには信じられない状況に.
 まぁ、私の脳みそレベルが垣間見れる訳です.

 そして何を血迷ったのか「さっさと調べよう」と検索エンジンへ.
 …んが、まったく出てきやしません orz
 検索の仕方がまずかったのか、30分ほどネットを彷徨うlightmaterial.
 しかも、最終的にドキュメント読んだらすぐに見つかると言う駄目っぷり orz

 あ~アホらしい.
 体調悪いしさっさと帰ろう.

 なんちゃってデータベース使い(要するに素人)から、本当のデータベース使い(MS SQLでもOracleでもPgSQLでもMySQLでも何でも来いや!な玄人)に成りたいと心底思った今日この頃.

2007年8月17日金曜日

Eclipse3.3.

 …久しぶりの更新だ orz
 まぁ、もう一個のblogは半年ほど放置状態なので、まだましと言う事にしておきます.


 更新をサボっている間にEclipse3.3が正式リリースされました.
 今日から微妙にずれた夏期休暇が取れたので(取れたのでと言うか、取るために仕事三昧の日々を送って「取った」んですが)、今日は朝からEclipse3.3をインストールして自宅で仕事の続きをやってました♪
 … orz

 いや、そんな話は置いておき.
 Eclipse3.3ですが、自宅のPen4 1.5GHzと言う廃棄一歩手前でも現役で頑張っているWindowsマシンでは、少々もたつきが発生しました.
 今の所、これまた普通だと廃棄候補にあがる2GHzのFedora Core6マシンだと普通に使えるので、自宅で仕事するには問題なさそうです…悲しい話ですが orz

 lightmaterialにとって一番実用的なのが、各コードタブをダブルクリックした際の挙動.
 今までもダブルクリックでコードエディタ部分がウィンドウいっぱいに広がりましたが、今回からOutlineなどのサブペインが完全に隠れず、クイックアクセスアイコンとして表示されるようになり、すばやくサブペインを復元できます(下画像の赤囲み部分).

 未だにワイドなディスプレイを持っていないlightmaterialには必須機能ですw
 逆にワイドディスプレイ使っている人には、そんなに恩恵が無いかもしれませんが.

 あと、VisualStudio(.Net)の様に、コードの選択範囲をD&D移動出来るとかって言う記事をどこかで見かけましたが、何が悪いのか上手く動いてくれません orz
 Professionalな方はキーボードだけで殆んどの操作を行うんでしょうが、lightmaterialの様な低レベル人間には結構役に立つんですけどね.
 どっか設定の変更が必要なんだろうか?
 後で設定項目を見直してみる必要があるかもしれません.

 その他、細かいけどかなり良くなったのがタブ.
 非アクティブなタブもアイコンとタイトル両方が描画されるようになって、非常に便利になりました.
 便利になりましたと言いますか、今までが不便でした orz

 と、まだ全然触れてませんが、3.2系よりも「使っていて心地よい」改善が気に入りましたので、休み明けには会社の環境も3.3系へ乗り換えようかと計画中.


 所でまったく関係ありませんが、某会社が販売している.Net系コンポーネントを見つけたんですが、Firefox(Firebug付き)でサンプルを試すとすごい状態になります.

 これは何もしていない状態のJavaScriptエラー数です.
 ただ…ただページを表示しただけです orz
 まぁ、確かに対応ブラウザはIE限定となってはいるんですが……ここまで特化したコードも珍しかったので一応メモ.

 上記コンポーネント自体は業務系で使用されるケースが多いような分類なので、今のところIE限定でも問題無いんですが、この先いつまでIE限定のWebアプリケーションが受け入れられるのか…
 仕事で足突っ込んでますが、正直この辺の切り分けってまだまだ不確定要素が多いです.

 来年の今頃もまだIE限定で行けるのか?
 未だに「対応ブラウザはIEとNetscapeで」とか言う状況で行けるのか?(lightmaterialの会社は違いますけど)
 FirefoxやらSafari対応にまで踏み込まないと淘汰されて行くのか?
 と、不安が募るばかり.

 まぁ、そうは言いつつ日本ではまだまだIEオンリーで大丈夫なんでしょうけどねw
 IE天国日本ですから.

 嗚呼恐ろしや恐ろしや…

2007年7月31日火曜日

EnumeratorとIterator.

 …またやってしまった orz
 週末更新が途絶え過ぎです.
 前回反省した様な事を書いておきながら、全然反省してなかった事が白日の下に orz

 と、デジャヴな反省は置いておき.
 最近Javaの勉強も全然進んでいませ…ここでも駄目すぎる事実が orz
 反省しきりです.
 27時間テレビなんて見るもんじゃありませんw

 話が逸れまくりましたので元に戻して.
 Javaの勉強が全然進んでいないと言う駄目すぎる状況にある訳ですが、会社でPHPのコードを書いている時にフと「あれ?…EnumeratorとIteratorって…何が違うんだ?」と言う疑問にブチ当たりました.
 はい、設計の勉強云々以前の問題ですね orz

 いや、これは.Netの弊害です!!
 私も被害者なんです!!! orz

 何でPHP書いててこんな事を考えたのかと言うと、会社では主に「PHP4でも動く事が前提」でコードを書いてますので(もうPHP4系のライフサイクルも終わりますが)、オブジェクト指向ライクな構造をとる場合には、かなりの割合で自力実装が必要です.
 そして、それらは独自Frameworkとして作成・実装している訳ですが、その中でCollectionに対する列挙処理として「Iterator」クラスを作成しています.
 例えば、Collectionクラス(勿論自前実装)には「追加」「クリア」「Item取得」の様な振る舞い+「getIterator」を実装して、列挙処理にIteratorを使用するイメージです.

 ※実際にはこんなにシンプルではありませんw

 んが、.NetではIteratorと言うものは「概念上」ありますが、実際にはEnumerator(IEnumerator)がカバーする仕組みになっていて、lightmaterialの頭の中では「Iterator=Enumerator」と言う図式が完全に出来上がっていました.
 でも、実際にはJavaの実装で見ると、IteratorとEnumeratorには明確な差異があり、IteratorはEnumeratorの後継にあたり、Enumeratorでは実装されていなかった「要素の削除」機能が実装されているものだ、と定義されています.

 あれ?
 何だ?
 ん?

 …結局IteratorとEnumeratorって何が違うんだよぉぉぉぉ~~!!? orz

 Javaなら「はい、そうですか」と明確で明瞭に理解可能ですが、他の言語での実装方法を見ていると、その差異が見えてきません.
 うーん…ここは深く考えずにJavaでは「Enumeratorは過去の産物で、これからはIteratorオンリーです!」と考え、.Netでは「IteratorってEnumeratorの別名でしょ?」と考えておいた方がいいのかなぁ.

 恐るべし列挙子/反復子!
 と言いますか、こんな低レベルな事書いてるPGなんて、全国探しても私くらいのものでしょう orz
 むしろ自分自身が恐ろしい今日この頃.

2007年7月23日月曜日

今週は無し.

 ベランダでタバコを吸ったら、北海道にある我が家から見て北(若干東)の空に高速に点滅する光が一つ.
 飛行機の点滅より速く、位置は一切変わらない.
 ましてやこの時間に北海道の東北へ向かう飛行機なんざ無い訳で…
 ま、そんな事(事実だけど)は気にせず戒めへ.

 今週は更新無し.

 と言う書き込みを月曜日にする駄目っぷり orz
 出張で書けなかった時を除いて一応土日どちらかで書いてたんだけどなぁ.
 建前上反省反省.

2007年7月18日水曜日

Confirm-Addressが窓の杜に掲載されていた.

 風邪引きました orz
 熱がある上に何故か白目が充血しまくりです.

 最近お世話になっているConfirm-Addressと言うThunderbird用のExtensionが窓の杜に紹介されていました.

 kenmazさん、おめでとう御座いま…す…?

 こう言う事があると急にアクセス数が増えたり、サポートの要求が増えたり大変かもしれませんが頑張って下さい.

 さ、脳みそが熱暴走する前にさっさと寝ます.

2007年7月17日火曜日

Ajaxの繁栄とgoogle.

 ちょいと興味深い記事があったのでメモ.

 グーグルが語る:Ajaxはなぜ最初失敗し、その後成功したのか

 半年くらい前だったかなぁ.
 知人と「最近のWebアプリケーションってちょっと前まで考えられなかったくらいリッチだよねぇ」と言う話題になった事がありました.
 最近ではOfficeライクなWebアプリケーションやWeb(Ajax)OSが無償で利用出来る環境にまで成長していますから.
 その時lightmaterialが「Ajaxの基礎技術自体は枯れた技術なのに、何で今までこんなのが出て来なかったんだろうねぇ」と言ったら、知人が「クライアント性能の問題じゃない?」とそっけなく言ったのを鮮明に覚えています.
 なるほど…言われてみれば当たり前の話だな、と.

 そんな話からgoogleがAjaxや自然言語に取り組んで失敗し、そして今の成功がある事を分かり易く(英文訳なので日本語としては多少分かり難いかもしれませんが)書いてある記事でした.
 それと同時に、今や新しいコンピューティングとExperienceはOSの手を離れ、Network/Internet上に移行したのだなぁ、とWebアプリケーションメインでプログラム書いてるPGのくせに、改めて強く痛感した次第です.

※Experienceと書いたのはカッコつけたのでは無く、WindowsXPの語源でありMSが好んで使う言葉を皮肉っただけです.

2007年7月16日月曜日

XML署名.

 XML署名……は、初めて耳にしたよ orz
 何ですかXML署名って?w

 仕事で使うかもしれないと言う話が持ち上がり、色々と調べてみたんですが、結局使わない事になりやがりました.
 が、何か面白そうだったので引き続き調査中.

 元々「XML署名」と言うのは、XML(タグで区切られたデータを扱うファイル)の改ざん防止、ファイル真性の証明を目的として作られた規格との事.
 詳しくは↓ココ参照.
 @IT:XMLデジタル署名とXML暗号

 別に新しい技術と言う訳では無いようです.
 確かに今やあらゆるデータのデファクトスタンダードとなりつつある(既に成ってる?)XMLに電子署名を付けるのは理にかなった考えです.

 が、この機能を実現しようとするとちょいと面倒.
 面倒と言うか、まだ上手く動かせてません orz
 .Netで試してみたんですが、何故かエラーが発生.
 丸々MSのサンプルを動かしてもエラー.
 OpenSSLで自己署名した証明書の作り方が悪いんだろうか??

 でもこれが使える様になったら、結構面白そうです.
 因みに.NetでもJavaでもちゃんと標準ライブラリとして実装されている様です.
 .Netでは

 System.Security.Cryptography.Xml.SignedXml

 で実現するんですが、これ自体は何にも難しい事は無い(と思われる)んですが、ちゃんと動作するか確認するのに証明書を用意しないと駄目な訳で、エラーが出ると「これってコードが間違えてるのか?それとも証明書自体が悪いのか?」と前述した様に迷走モードに突入しますw

 そんなXML電子署名ですが、ちゃんとサードパーティのライブラリもあります.

 Le-XAdES Library / XAdES署名ツール XAdEStool

 まぁ、実際にはライブラリは公開されていない開発途中のライブラリですが、これが実際にライブラリとして公開されたら楽そうです.
 実際問題、SOAPなんかのセキュリティ確保にXML署名が利用されている様ですので、今後ますます需要が出そうな規格かもしれません.

設計が分からない-1.

 たった今、北海道でも揺れました(汗
 新潟には仕事での交流がある方もいらっしゃるので心配.
 無事である事を祈るばかりで.


 相変わらず設計の勉強がまったく進みません orz
 ぜんっぜん分かりませんから.
 まぁ、これから参考資料なり研修なりを基に本格的に勉強するので、まだ出来なくて当たり前なのかも知れませんが、余りにも分からなすぎて怖い.

 例えば、以下の

・ボロバシカメラは個人で経営する家電販売店である
・店員はオーナー一人のみであり、人件費はかかっていない
・POS購入費用が無く、ソロバンと手書き(売上管理台帳)で売り上げ計算を行っている
・商品は在庫を最少数のみ確保し、販売して在庫が無くなりそうな場合に仕入れを行っている
・在庫の管理は在庫管理台帳に記載している
・仕入先は商品により複数存在する
・仕入れ内容は仕入れ管理台帳に記載している
・販売価格は商品の標準価格から値引いて販売する事がある
・一日の販売が終了すると、売上管理台帳を閉めて日の売上集計を行う
・毎月末、月間売り上げを集計する
・システム化にあたり、(こっちの都合で)POSでは無くノートPCとバーコードリーダーを使う事にした

 と言う、かなり強引な『こじつけシナリオ』があったとます.
 通常RFP(提案依頼書)を顧客に書いてもらいますが、架空のお話なのでそんなものありませんw
 純粋に、今手作業でやっている事をシステム化したいと言う案件だとしましょう.
 それでは上記内容に沿ってシステム設計を行います.


 …で、どっから取り掛かればいいのさ? orz


 ええもう、ぶっちゃけこの悲し過ぎる程の初歩段階ですよw
 うーん.
 ちょっと設計と言うモノの流れを自分なりに考えてみよう.

 01. RFPを熟読
 02. 業務フロー作成
 03. ユースケース図作成
 04. 1~3を元に顧客との打ち合わせ
 05. 必要に応じて1~3を繰り返す
 06. ER分析(エンティティを見つけ出す)
 07. ER図(ERD)作成
 08. 大まかなオブジェクト図(クラス図)を作成(クラスを見つけ出す)
 09. 6~8を元に顧客との打ち合わせ
 10. クラス図作成
 11. シーケンス図/コラボレーション図作成
 ここまでが分析か?
 12. ユースケース図/アクティビティ図以外のUMLダイアグラムを駆使
 13. データ設計(一部ERDを基に作成)
 14. 画面設計
 15. 詳細クラス図を基に機能(関数)設計
 ここまでが設計か?

 と言う感じだろうか?
 …適切なのかどうかすら不明だ orz
 さっさと参考資料でも買い漁らないと駄目ですね.
 プログラムだと実際にやって見れば、合ってるのか間違っているのか分かりますが、分析/設計はこの辺の判断が自分では出来ないので厄介です.
 と言う事で、現在amazonでUML/システム設計の書籍を模索中.

 とは言え、探してる間にボーっとしてるのもなんなので、ためしに基本中の基本、業務フロー図でも書いてみましょうか.
 Excelで業務フロー作るの面倒だから、アクティビティダイアグラムを代用です.

 ※画像はJUDE Community

 …どこからどこまで一つのダイアグラムに書けばいいのか分からない orz
 資料が整うまで勉強しても無駄な気がしてきましたw
 と言いますか、正直まともに設計出来る様に成れる気が一切しませんから.

 諦めてJavaの勉強優先しようかなと葛藤中.

2007年7月7日土曜日

UMLモデリングツール.

 先日書いた様にこれからUMLの勉強をしなければなりません.
 …したくは無いんですけどw

 と言う事で勉強用のUMLモデリングツールを探しましたが…使いづらい orz
 そもそもUMLモデリングツールってこんなもんなんですかねぇ?
 皆さんこんなに使い難いものを使って、あれだけのダイアグラムを書いている訳ですね.
 逆に「すごい!」と思わずには居られません.
 まぁ、会社のエンジニアの人が使っている某商用モデリングツールなら、使い易いのかもしれませんが.

 しかし勉強のために商用の物を使うほど懐具合に余裕がある訳では無いので、非商用のモデリングツールを色々と触ってみました.

 ・JUDE
  ※注 現在何故か上記サイトはつながりません
 ・Poseidon
 ・SystemDirector Application Modeler

 それぞれ特徴がありますが、どれも一通り必要なダイアグラムを書けるものです.
 一部書けないものや、機能上一部おかしいものもあります.

 ・ArgoUML
 ・1st Modeller
 …etc…

 ArgoUMLはSequenceダイアグラムの挙動がかなり変なので致命的ですが、その他の機能は結構使えます.
 クラス図なんかを書いた際には、ソースの雛型まで生成してくれます.

 PoseidonはそのArgoUMLを元に作成されたらしいのですが、実際に触ってみるとかなり違います.
 グラフィック回りが大幅に向上しており、またSequenceダイアグラムもまともに作成可能になっています.
 しかしこのツール、マウスとか図の回りに各種メニューのポップアップが出るんですが、これが逆に邪魔で私はあまり好きになれませんでした.
 ちなみにLinuxで入れてみましたが、一部文字化けしますし、License認証はブラウザ経由で行うんですが、これがまた何故かNetscapeを自動検索して見事に失敗しやがります(「Your default browser cannot be started.」).
 Poseidon本体を起動した後「Edit」→「Settings...」→「Browser」項目でFirefoxなどを指定する事でエラーを解消できますが、エラーを解消出来たとしても開いたページで「This Page No Longer Exists」と出ちゃいます.
 何だかなぁ…ライセンス認証しないと保存も出来ないんですが orz



 JUDE(勉強用に試したのはCommunity版)は国産のUMLモデリングツールなので、情報も豊富ですしコミュニティも充実しています.
 現時点ではこれが最有力候補ですかねぇ.
 なんか、NTTデータでは標準UMLモデリングツールをJUDEにしたらしいですし.
 動作も挙動不審な所はほとんどないですし、ちょっといじればLinuxでも動かす事が可能の様です(上にも書いた様に今サイトつながらないので確認出来ませんでしたが).

 SystemDirector Application Modeler(以下SDAM)はNECが開発・保守しているEclipseプラグインです.
 他にもEclipseプラグインでUMLを作図するものがありますが(EclipseUMLなんか)、今回はSDAMのみ試しました.
 JUDEと比べると使い勝手でちょっと見劣りしてしまう所もありますが(あと、斜線引くと実線と点線の区別がつきにくい気が…)、オブジェクト図も書けるので非常に便利です(SDAMでは「オブジェクト図」と言う名前では無く「インスタンス」と言う名前ですが).
 Eclipseでコード書きつつUMLを確認したり、逆にコード書いててつまった時にクラスダイアグラムを書いてみる、なんて事も簡単に出来てしまう点が一番の魅力かもしれません.
 これも候補のひとつですね.



 まぁ、実際に仕事で使う時には(いつになるか分かりませんが orz)別の商用ツールを使いますので、勉強にどれを使うかそんなに真剣に悩む必要もないんでしょうけど.
 取り敢えずJUDEメイン、SDAMがサブと言うかちょっとだけ書く時に使う事になりそうです.

 それにしてもUMLモデリングツールを選ぶだけで一苦労.
 相変わらずUMLの書き方と言うか考え方が理解不能ですし…あーUMLって奥が深い orz

2007年7月4日水曜日

設計.

 今日はメモと言うより愚痴と言うか悩みを.

 密かに先日まで1週間弱出張に行っていた訳ですが、戻った直後に会社の人から「設計の勉強したら?」といきなり言われました.
 出張帰り直後にドキッとする発言は止めて下さい orz
 出張から戻って速攻でそんな事言われたら「え?お、俺お払い箱?」と思ってしまいますから orz

 と言う事で会社の人から言われた言葉を改めて噛み締めてみました.
 …!?
 アレですか?
 要するに「いいかげん人様の書いた仕様書なりUMLダイアグラムで飯を食ってる年でも無いでしょ」と言う事ですか?! orz

 元々プログラム始めた年齢も適齢期(プログラムのね)を完全に過ぎてからだった訳ですし、別に専門学校へ行っていた訳でも理数系だった訳でも無いので、その辺は勘弁して頂きたい!
 むしろプログラム始めて5年目にしてようやくPG半人前の域に達した私に何を望んでいるんですか?と問い詰めたい気分です.

 がしかし、lightmaterialの勤めている会社は極々小さい会社なので、我侭を言っていられる状況にはありません.
 Javaの勉強でウキウキ気分[死語]だったのが一気にどん底へ行った気分です.
 ここ2日色々と調べましたが、ハッキリ言って私の様なうすらバカもしくはうっすらハゲには理解不能です orz

 コードでもありますが、ダイアグラムも同じで「読めるけど書けない」.
 読むと書くのでは大違い.
 事象の分解と定義、オブジェクトへの変換の仕方がまったく理解出来ません.
 2日目にしてこの状況ですから、先が思いやられます.
 オマケに設計関係の研修に勝手にエントリーされてますしw
 そんな訳で素敵な理数系脳みそを移植したい今日この頃です.

2007年6月24日日曜日

.Net/PHPプログラマから見たJava.

 暑いです orz.

 それは置いておき、先週の火曜日から、帰宅後にビールを飲みつつ1〜2時間/日のスローペースでJavaの勉強を始めました.
 以前もJavaの勉強をしようとした事があるのですが、何故かクライアントアプリケーションから取りかかってしまい、敢え無く挫折 orz

 苦い経験(?)から、今回はWebアプリケーションから取りかかってみる事に.

 結果から言えば「最初からWebアプリケーションで始めていれば良かった」と激しく後悔中です orz
 これなら何とか勉強できそう.
 今はStruts/Struts2を使って遊んで 勉強してます.

 勉強する環境にしても、

  ・WindowsまたはLinuxまたはMacOS
  ・J2SE(JDK/J2 SDKとも呼ばれる…名前が変わりすぎw)
  ・Eclipse
  ・WTP(Web Tools Platform)
  ・Tomcat

 が整っていればOK.
 lightmaterialの場合Eclipse+WTPは既に入れていたので、J2SEとTomcatを入れるだけでした.
 今までWebアプリケーションはJ2EEを導入してないと開発出来ないものだと思っていましたが、そう言う訳では無く、本当にEnterpriseな環境を構築する際に必要(と言うか便利)なだけの様です.

 私がJavaを今まで敬遠してきた理由は、「なんか複雑そう」「EJBとかJavaBeansとかDIとか意味不明」等々、専門用語やら色々な要素が関連しあって動く複雑な物、と思っていたからです.
 ASP/ASP.NetにしろPHPにしろ、(PHP用のFrameworkは別として)ほとんど言語環境単体で動く事を考えると、どうしても敬遠しがちになります(あくまで個人的な感想).

 が、実際に触ってみると「初歩的な事は」意外とそうでもありません.
 初歩的な事を勉強するのに、EJBもDIも気にする必要はありませんでしたから.

 今の所Java(Webアプリケーション限定)について把握したのは、
 1. 完全にオブジェクト指向言語(あたりまえ)
 2. メモリの管理がちょっとだけ特殊?
 3. パッケージという概念がある
 4. 現状の標準的構成として、ページを描画するJSPとコードを担当するServletで構成するのが一般的
 5. Frameworkを使わないと死亡
 6. 描画を担当するJSPも初回アクセス時にビルド(?)される
 7. ファイル構成が少し特殊、各種設定がXML

 と言った所でしょうか(間違えてる可能性大).

 [1]は最初から分かっていた事なので、特に戸惑いはありません.
 .Netにしろ、正しくコードを書いていればオブジェクト指向な記述になりますし、PHPにしてもオブジェクト指向な記述の仕方が現状の標準的なコーディングかと思います.

 [2]のメモリ管理ですが、基本的にはオブジェクトが参照されなくなった段階で、メモリから破棄される様です(正確に言えば、ガベージコレクションの対象になるのかな?).
 その為、通常はC/C++の様に明示的に破棄する必要はありませんが、参照サイトによってはnullで参照されなくなった事を明示すべきだ、との記述が見受けられました.
 まぁ、この辺はVB/ASP.NetでもNothing指定すべきだ、とする傾向がありますので、これも戸惑いはありません.

 [3]のパッケージ.
 これはクラスライブラリの様なもの、と私はとらえてます(あってるかは不明).
 今まで「org.apache.xxxx.....」などと言うファイルを見かけた事がありましたが、何の事やらさっぱり不明でした.
 この「org.apache.xxxx.....」の部分がパッケージ名(?)にあたる様です.
 また、パッケージ名は配布や流用等を行う事が多いので、他のパッケージ名とかぶらないように、開発元のドメインを逆さにした名称を付けるのが一般的との事.
 それで「org.apache」だの「org.eclipse」だのと言うファイルがある訳ですね.
 すごく納得しました.

 [4]のJSPとServlet.
 これもASP.Netをやっていれば何も戸惑う事はありません.
 ASP.Netで言う所の、「xxx.aspx」ファイルと「xxx.vb」ファイルの関係と考えればあまり大きく間違える事は無いと思います(厳密には違いますが. JSPの場合Servletが無くても動きますので).
 現状のコーディング方法として、「JSPには極力コードは書くな」「コードはServletに書け」と言う傾向がある様です.

 [5]のFrameworkについては、PHPも結構同じ事が言えると思いますが、Javaの方がよりFrameworkに依存している様に思います.
 そのため、Frameworkを使わずにプログラムを書こうと思うと、非常に雑多なコーディングになりそうです.
 画面遷移ひとつとっても、ServletからJSPに渡す変数を一々setAttribute/getAttributeしたりDispatcher作ってページ呼び出したり…単に私が簡単な方法に気付いてないだけかもしれませんがw
 これらJavaの代表的なFrameworkとしてStruts/Struts2JSF(JavaServer Faces)があります.
 それ以外にもあるのかもしれませんが、今の所勉強の対象にするつもりなのは、この2つのFrameworkです.
 特にJSFは標準機能としての提供がされる予定らしく(?)、今後のJava開発環境では必須になるのかもしれません(StrutsはApacheプロジェクト).
 ただ、StrutsとJSFでは重点部分が異なる様で、StrutsはController部分、JSFはView部分(?)に重点を置かれたFrameworkらしく、今ではStruts+JSFで動作させる方向にも行きつつある様です(Struts2から?)ので、両方勉強しておいて損は無いだろう、と思ってます.

 [6]はよく分かりません.
 よく分かりませんが、初回アクセス時にビルドする事で、その後の処理を高速化する様です.
 この辺は後々触っていれば分かってくるだろうと勝手に妄想中.

 [7]のファイル構成については、どちらかと言うとTomcatの構成なのかもしれませんが、まだその辺は良く分かっていません.
 少し特殊と言うのは、「WEB-INF」や「META-INF」と言った設定用のディレクトリが最初から定義されていて、そこに設定ファイルやらライブラリやらビルドしたServletやらが設置される様に半分強制されている事です.
 これらのディレクトリには、ブラウザ経由で直接アクセス出来ない様になっています.
 まあ、まとめて放りこめるから便利と言えば便利ですが、WTPで作ったプロジェクトの標準ディレクトリ構成と少々あってないんですよね…これどうにかならないんだろうか orz
 また、基本的に各種設定はXMLファイルに記述する事になります.
 Frameworkの設定もXML.
 あれもこれもXMLです.


 その他JavaBeansなんてのもありますが、この正体が分からない.
 JavaBeansで検索すると、GUIなビルダーとの連携により云々と書かれているものもあれば、単純にProperty/Getter/Setterを持ったクラスファイルだよ、と言った書き方のサイトもありました.
 更にはStrutsのActionForm部分をBeanと書いている所もあり、現在かなり混乱中ですw

 取り敢えずひとしきり触ったら、Javaについてのメモを順次記述予定.

※下の画像は単にJSPのみでの動作例です. ServletもStrutsも何も使ってません.

2007年6月16日土曜日

コンデンサ破裂・液漏れ・膨張.

 某所でPCの電源を入れると、CPUファンやCDに通電している状態にも係わらず、まったく画面出力されない現象に出くわしました.
 出くわしましたと言うか、今出くわしてます orz

 つい1ヶ月くらい前まで普通に動いていたんですが、今日電源を入れてみると上記のような状態に.
 「何だろう?」とケースを開け、コネクタ類の接続を確認・抜き差しして、ケースを開けたまま電源ON.
 が、全然動く気配なし.
 何が原因かとマザーボードを眺めるlightmaterial.
 ん?
 コレ何だ?

 こ、これは噂でしか聞いたことが無い「コンデンサ破裂」ってやつじゃ?! orz
 ※後から分かりましたが、「コンデンサの液漏れ」ですね.

 確かにこのPCは2002年に購入した物なので、そろそろガタが来ててもおかしくないんですが、私の自宅にあるPCではコンデンサ破裂なんて今まで経験した事無いですし…
 正直参りました.

 マザボの修理と理想の電源 - ☆たるさんのパソコンフィールド

 上のサイトにコンデンサの破裂や液漏れについて詳しく書かれていますが、どうやら中学校以来ハンダゴテを見た事すら無い私には交換なんて無理そうです orz
 ここは素直に諦めましょう.
 どうせ私のじゃないですし、会社の費用で交換購入する事になるんだから.

 そう言えば、自宅には8年くらい前に購入した初代PC(EPSON DIRECTで買ったやつw)がありますが、未だにちゃんと動きます.
 ただ、マザーボードなんて最近ちゃんと見てないから、もしかしたらコンデンサが膨張してるかもしれません.
 今回みたいに使いたい時に使えなくなる前に、予めリタイアさせた方がいいかもしれません.

2007年6月12日火曜日

PHPからのPDF出力でハマる.

 また珍しく平日にメモ.

 PHPからPDF出力すると言えば

  ・PDFLib
  ・FPDF
  ・Zend Framework

 あたりが代表格かと思います.
 Zend FrameworkでのPDF出力はまだ試してませんが(正確には0.xの時に上手く動作させる事が出来ませんでした orz)、PDFLibもFPDFも基本的にはPHPのコードからPDFを吐き出す事に変わりありません.

 そして出力時の問題で有名なのがIEとsessionの問題.
 PHPでsessionを使っている場合、普通にPDF出力するとIEではまったく表示されない状態になります(画面真っ白).
 その為、IEを考慮する場合に於いて、sessionを使ってるコードからPDFを吐き出す時は

  session_cache_limiter('private')

 をsession_start前に宣言してやる必要があります.
 当たり前ですがここまでは知っています.

 んが!
 まさかOpera9でも同じ状況になるとは?! orz
 そんな事まったく知らず「あれ?何で?何で?何で出ないの?」と大ハマり.
 Opera8まではinlineで表示できなかったので、Operaの事はまったく気にしてませんでしたよ.
 まったく、相変わらずOperaは色々と面白い事をやらかしてくれます.
 Opera8→9で、JavaScriptからIFrame内をprintした時の挙動も違いますしw
 今更ですが、Opera9をもう少し触ってみる必要がありそうです.

 そしてもう一個.
 原因は良く分かりませんが、Safariで同じ様にPHP→PDF出力すると、場合によって

  ファイルの最初に%PDF- がありません。

 と言うエラーが出ます(Ver 1.3.2でしか確認してません).
 出ますと言うか出てしまって、またしてもハマりました orz
 未だに原因が分からないんですが、取り敢えず

  header('Content-Length: [バッファサイズ]')

 を送出しなければこのエラーが起きない事が判明.
 なんだかなぁ.
 対処出来てるのはいいんですが、非常に気持ち悪いです.
 どっかでコード間違えてるんだろうか?
 でもSafari以外で出ないんだよなぁ orz

 しかも、今日『Windows版のSafari』が開発中である事が発表されました.
 iPodでiTunesが普及した様に、抱き合わせ戦法でWindowsにSafariが普及した場合、無視できない存在になるかもしれません.
 正直もうブラウザは増えなくていいですから orz

※現状Windows版Safariはまともに動きません

2007年6月11日月曜日

送信前に宛先は良く確認しよう.

 先日痛恨のミスをやらかしました.
 詳しくは書きませんが…まぁ…タイトルのね…そんな感じの痛恨のミス orz

 恐いわぁ〜.
 最終的に問題なかった訳ですが、メール送信が恐ろしくなりました.

 と言う事で、現在Thunderbirdには↓コレを突っ込んでいます.

 Confirm-Address

 その他にも同類で

 Check and Send

 と言うExtensionがあるのですが、使い勝手の問題からConfirm-Addressを導入.
 それでも動作的に少々怪しげな部分があるので(失礼)、現在更に同類のExtensionを模索中.
 作り方が分かっていれば自分で作りたい所ですが…全然分かりゃしません orz

2007年6月10日日曜日

Tracのマルチプロジェクト管理用Plugin - TraM.

この概要は表示できません。投稿を閲覧するには ここをクリック してください。

2007年6月5日火曜日

Ajax loader icon.

 いつも週末だけ管理してるので、平日に投稿と言うのも珍しいですが、ちと忘れそうだったのでメモ.

 Ajaxload - Ajax loading gif generator

 AjaxなんかでAsynchronousにデータを読み込む時に表示するアイコンをFeeFree且つオンラインで生成してくれるサイト.

 こんな感じ.
 ※左の画像はbloggerでアップロードしてるので動いてませんが、通常はグルグル回ってます.

 この他にも、プログレスバーとか変わったのとか色々生成出来ます.

 しかしこのサイト、ライセンスについての記述がフッタの一文しか見当たらない訳ですが、これって商用で使ってもOKなんだろうか?

2007年6月3日日曜日

PDTとSubclipse.

 以前も書いたPHP Development Tools.
 実際に使ってみると、結構いい感じです.
 コメントで日本語なんか使うと、色分けや太字処理なんかで問題が出ますが、その辺が気にならなければ快適に使えます.

 ※使う日本語によって、現象が出る出ないがあります.

 ただ、私のやり方が悪いのか、Subclipseが悪いのか、Subversionで管理されたPHPのコードをPDTで編集しようと思うと、思い通りに行きません.
 前に書いた様に、PDTはPHP Projectとして作成したプロジェクト以外では、コードアシスタントもアウトラインも動いてくれませんので、SubclipseでチェックアウトしたプロジェクトをPDT用のプロジェクトにしないといけませんが、この方法が分からない.
 どうやればいいんだろう???

 結局今は力業で.projectファイルをPDT用の物に置き換えてSubclipseとPDTを共存させてますが、まさかこんな力業が正当な使いかたじゃないと思うんですよね.
 どうやったらいいんだろうか?

 うーん分かりません orz

Fedora7リリース.

数日前の話になりますが、Fedora7が正式リリース.

Fedora7からは、通常版のインストールイメージがDVD化されています.
つまり、今まではCD5枚分(レスキュー除く)のイメージが必要でしたが、今回からはDVDイメージ1枚分でOK!と言うことです.
…DVD-Rドライブもってない私はどうすれば? orz
と言う事で、貧乏マックスなlightmaterialはおとなしくLiveCD版をダウンロード.
LiveCD版なら普通にCDイメージですし、(会社の)CD-R/RWドライブを使えば焼けますので.
本当はダメなんですけどねw

LiveCD版には更にGnome版/KDE版が揃ってます.
この辺は好みの問題ですが、最近Xfceが気に入っている私としては、Xfce版も用意してもらいたかった所です.

 LiveCD起動直後はこんな感じです.
 ネットワーク接続通知が出ているのは、単にLANケーブルをルータに差し忘れていたからですw
 印象的には「何も変わってないじゃん」と言うのが第一印象.
 グラフィックはVistaに倣ってか、GDM/KDMともにOpacity的な処理がされていますが、それ以外はパッと見特にFC6と変わっていません.

 もちろん内部的にはリポジトリの統合やら、導入環境のバージョンアップ等々あるんですけど.

 それでも劇的な変化というのはありません.
 LiveCDとしての特徴は、以前書いたUbuntuと同様に、デスクトップにHDDへインストールするためのショートカットが用意されている点、デフォルトでは(当然)英語で起動するので、毎回毎回languageにJapanese選んだ上でキーボード設定を日本語にする必要がある点です.
 正直面倒です orz
 おまけに、lightmaterialのやり方がまずいのか、KDE版では結局日本語に出来ませんでしたw

 名称が変わった事も含め、もう少し劇的な変化があるのかと期待していただけに、少し拍子抜けした感があります.

2007年5月27日日曜日

今週は無し.

 今週は予定があって時間を取れなかったのでメモは無し.

 同時に、自分のスケジュール管理の甘さに茫然自失 orz

2007年5月20日日曜日

Subversionのリビジョン間差分をExport.

 Subversionを会社でテスト導入.
 最終的にVSSからの置き換えが出来るかどうかは置いておき、あらゆる作成物のバージョン管理が出来る、FSFSで運用している場合、リポジトリのバックアップもコピーも簡単に可能と言う利点がありますので、十分役にはたつでしょう.

 と言う事で実際にテスト運用してみると、リビジョン間の差分のみをExportしたいケースがある事に気づきました.
 何百ページもあるWebサイトのデータ管理なんかがそうです.

※ここから以下、すべてWindows上での話です

 結論から言えば、TortoiseSVNで普通に出来ますね.

 ◆リポジトリブラウザ→リポジトリ選択→右クリック→ログを表示→対象リビジョン(2つ)選択→リビジョンを比較→リストのファイルをすべて選択→右クリック→選択をエクスポート

 がしかし、lightmaterialはこのExport方法にまったく気づかず orz

 探してもなかなかリビジョン間差分をExportするツールが見つからず(TortoiseSVNで出来るので当たり前かもしれませんが)、やっと探し当てたのが「SvnChangeList」と言うソフト.
 しかし、このソフトでは何故かエクスポートに失敗してしまうので(ファイルが1つも出力されない. lightmaterialの環境が悪いのか?)、仕方ないから自分で作ろうと手っ取り早くVB.Netを起動.
 TortoiseSVNで出来るにも拘らず…拘らず…拘らず… orz

 まぁ、そのマヌケ過ぎて笑える程悲しい現実は置いておき.
 このメモで本当に書きたかったのはここから.
 作り始めようと思ってすぐ問題が.
 直接Subversionのクライアント機能を実装しようとすると面倒なので、「SvnChangeList」に倣ってSubversion付属のクライアント(svn.exe)を起動する方法で試みた所、日本語が思い切り文字化けします.

C:\Subversion\bin>svn
?\228?\189?\191?\231?\148?\168?\230?\150?\185?\230?\179?\149?\227?\130?\146?\231
?\159?\165?\227?\130?\138?\227?\129?\159?\227?\129?\132?\227?\129?\168?\227?\129
?\141?\227?\129?\175 'svn help' ?\227?\129?\168?\230?\137?\147?\227?\129?\163?\227
?\129?\166?\227?\129?\143?\227?\129?\160?\227?\129?\149?\227?\129?\132?\227?\128
?\130

 は?

 と思いつつネット探索してみると、この現象はかなーり有名な現象の様で、インストーラでインストールしていない場合やTortoiseSVNと同居させていると発生するとの事.
 どうやらiconvのパス指定が正常に取れていないのが原因らしいので、PATH指定してあげる事で解消します.

set APR_ICONV_PATH=[iconv diretory]
C:\Subversion\bin\svn
使用方法を知りたいときは 'svn help' と打ってください。

 [iconv directory]はSubversionのディレクトリ下にある「iconv」ディレクトリを指定します.
 これで訳の分からない文字化けからは解消されます.

 System.Diagnostics.Process(とProcessInfo)でこの辺をどう処理して良いのか思い浮かばなかったので、結局文字化けする場合はbatファイルを出力して、それを起動する方法を選択.
 何度も言うようにTortoiseSVNで出来るにも拘らず…拘らず…拘らず… orz

 完成させる前に気づきましたし、文字化けの解消方法も分かったので、すべてが無駄だった訳ではありません!!

 …はい、無駄過ぎます orz
 4時間オール無駄.
 涙でディスプレイが霞んで見えるけど気のせい気のせい.

フレッツ網の例の件.

 まぁ、各所blog含め散々あらゆる所で話題になった東日本全域にわたるフレッツ網の接続エラー問題.
 もう5日も前の話ですが、週一でしかblog管理してないので平気で過去の話題を引っ張り出しますw

 札幌に住むlightmaterialも例に漏れず影響を受けました.
 その時は仕事中で大変な事に.
 会社のチープなルータは、事業所とのVPN的な設定のせいで、事業所間通信が落ちると社内のネットワークを巻き込んで不安定になってしまうので、余計大変な事になりました.
 しかも、社内で外部に通じている回線がすべてフレッツ網経由だったので、「繋がらない理由がまったく分からない」と言う状況.
 考えてみれば、今の時代、情報収集=インターネットと言う構図が成り立っているので、そこが落ちてしまうと何の情報も得られません.
 プロバイダの問題か?
 回線(光ファイバ)の問題か?
 NTTの問題か?
 まーったく分からず一時間あれやこれやと大騒ぎ.
 結局同業他社の知人から連絡を貰い、東日本のフレッツ網が落ちていると判明.
 一時間無駄に使ってその結果かい!と何故か爆笑してしまいました.

 と同時に、こんな事態になった時、TV・ラジオでしか情報収集出来ないと言う事を痛感.
 こんな事はめったに無いでしょうが、別経由の回線増設やTV・ラジオなりの外部情報入手経路を確保しとくのも大事な事だと思う今日この頃.

svchostがCPUを食い散らかす.その後2.

 先日書いたWindowsUpdateで固まるのはMSさんのミス?、と言う件ですが、前回の記事を書いた翌日(と言っても約一週間前 orz)、さっそく試しました.

 …ほ、本当に固まらない!w
 要するに、WindowsUpdate自体の不具合だったようで.

 ただなぁ
 この現象、4月の頭から発生してたんですが、実際に対応されたのが5月の半ばなので、4月の時点で固まるケースは無かったのかもしれません.
 私の環境(会社PC)が特殊だったんでしょうか?

 

2007年5月13日日曜日

Trac Web Admin Pluginを入れてみた.

 先日書いた「Tracインストール手順メモ.」の続きです.
 とは言え、かなり間が開いてしまいましたが orz

 今回は
  
 ・Trac Web Admin Plugin [ver 0.1.2dev_r4240](Python2.4版)

 をインストールし、TracのWeb画面上から管理者機能を使える様にしようと思います.

1. setuptoolsをインストール.



 オプション機能のsetuptoolsをインストールします.
 上記の「Tracインストール手順メモ.」を先に見ていれば、ダウンロードからインストール方法まで書いてあります.
 Trac Web Admin Pluginをインストールする前に、このオプション機能をインストールしておかなければいけないようです.



2. Trac Web Admin Pluginをインストール.



 インストールと言っても、手順は非常に簡単です.
 インストールパスは、前回作成したテストプロジェクトのディレクトリである事を前提にしています.

[??@fedora]# cd /sources
mv TracWebAdmin-0.1.2dev_r4240-py2.4.egg.zip /usr/local/trac/testprj/plugins/TracWebAdmin-0.1.2dev_r4240-py2.4.egg
[??@fedora]# chown [apache user]:[apache group] TracWebAdmin-0.1.2dev_r4240-py2.4.egg

 実行している事は、Trac Web Admin Pluginの本家サイトに書いてある事だけです.
  1. ダウンロードしたファイルから「.zip」拡張子を削除
  2. プロジェクトの「plugins」ディレクトリにファイルを配置
  3. ファイル権限変更(これは書いてませんが)

 次に、プロジェクト設定ファイルで、Trac Web Admin Pluginを有効にします.

[??@fedora]# vi /usr/local/trac/testprj/conf/trac.ini
…[中略]…
[components]
webadmin.* = enable

 設定ファイル中に[components]セクションが無い場合は、適切な場所に追記します.
 この設定方法は、Tracのマニュアル(TracGuid)に記載してあります.

 さて、インストールは完了しましたが、これだけでTrac Web Admin Pluginが使える訳ではありません.
 ちゃんとユーザー設定、パーミッション設定をする必要があります.



3. ユーザー設定.



 前回のインストール手順メモでは、ごく簡単に(と言うか概要のみ)しか触れていませんでしたが、Trac用のユーザー設定を行います.

[??@fedora]# vi /usr/local/apache2/conf/extra/httpd-trac.conf
 # Tracの設定項目は省略. 前回分参照.
 <LocationMatch "/trac/[^/]+/login">
  AuthType Basic
  AuthName "Test Project"
  AuthUserFile /usr/local/trac/testprj/.htpasswd
  Require valid-user
 </LocationMatch>

 「AuthUserFile」は好みのパスを指定します.
 今回は分かり易い様に、Tracのテストプロジェクト内に「.htpasswd」と言うファイルを作成する事にしました.
 そして、実際に「.htpasswd」(要するに、普通にApacheでパスワード認証する場合と同じファイル)を生成します.

[??@fedora]# htpasswd -c -b /usr/local/trac/testprj [user name] [password]
 ※当然[user name]と[password]を自分の環境にあわせて書き換えます.

 これでユーザー設定が完了しました.
 続いて、Tracプロジェクトのパーミッション設定を行います.



3. パーミッション設定.



 Trac Web Admin Pluginはその名前の通り、Web上からAdministrator的な機能を実行する為のプラグインですので、設定したユーザーがTrac上のAdministrator権限を持っていなければいけません.
 先ほど作成したユーザーに、「TRAC_ADMIN」と言うAdministrator権限を付与します.

[??@fedora]# trac-admin /usr/local/trac/testprj permission add [user name] TRAC_ADMIN

 後は実際に使ってみるだけです.



4. Trac Web Admin Pluginを使う.



 まず、Tracからログインします.
 Tracのトップ画面標示後、右上にある「ログイン」から認証処理を実行します.
 当然、htpasswdで作成したユーザー名、パスワードを入力します.

 そうすると、画面上にユーザー名が表示され(ここまでは標準機能のログイン)、メニューバー(?)に「Admin」ボタンが追加されます.

 環境によっては(?)、認証時に以下の様なエラーが発生するかもしれません.

Traceback (most recent call last):
…[中略]…
The following error occurred while trying to extract file(s) to the Python egg
cache:

[Errno 13] Permission denied: '/root/.python-eggs'

The Python egg cache directory is currently set to:

/root/.python-eggs

Perhaps your account does not have write access to this directory? You can
change the cache directory by setting the PYTHON_EGG_CACHE environment
variable to point to an accessible directory.


 要するに、キャッシュファイルをrootディレクトリに作成しようとしてエラーが発生しているので、アクセス可能なディレクトリを指定して下さいよ、と言う事でしょう.
 この場合、↑の指示に従って、Apacheの設定ファイルに変更を加えます.

[??@fedora]# vi /usr/local/apache2/conf/extra/httpd-trac.conf
 <Location /trac>
  SetHandler mod_python
  PythonHandler trac.web.modpython_frontend
  PythonOption TracEnvParentDir /usr/local/trac
  PythonOption TracUriRoot /trac
  SetEnv PYTHON_EGG_CACHE /usr/local/trac/testprj/.python_eggs
  #↑この1行を追記
 </Location>
 # 以下はパスワード制限する場合に必要.
 <LocationMatch "/trac/[^/]+/login">
  AuthType Basic
  AuthName "Test Project"
  AuthUserFile /usr/local/trac/testprj/.htpasswd
  Require valid-user
 </LocationMatch>

 設定に誤りが無ければ、これで正常にログインできるかと思います.

 Trac Web Admin Pluginの各機能は、この「Admin」ボタンから実行可能です.
 この各種機能を使う事で、上述したtrac-adminを使用したパーミッション設定などをWeb画面上から設定可能になります.
 おお、何とも便利!!

 …ただ、これ公開用で使うのはちょっと恐い気がしないでも無いですね.
 どうなんだろう?
 まぁ、私はローカルでしか使わないので問題ありませんが.