Nov 28, 2005

[Maven] maven-metadata.xml の読み込み方

先日作成した MavenRepositoryBrowser で使用した maven-metadata.xml の読み込み方法をメモ。

maven-metadata.xml 読み込みの実行環境構築

  1. maven-repository-metadata-2.0.jar をクラスパスに追加。
  2. plexus-utils-1.0.4.jar をクラスパスに追加。

サンプルコード

org.apache.maven.artifact.repository.metadata.Metadata というクラスが Metadata を表す。 ストリーム等から maven-metadata.xml を読み込み Metadata を生成するのが org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader。 この 2 つのクラスを利用すると苦も無く maven-metadata.xml を読み込むことができる。便利。

    public Metadata readMetadata(final String groupId,
            final String artifactId, final String version) throws Exception {
        String mavenMetadataRelativePath = "/" + groupId.replaceAll("\\.", "/")
                + "/" + artifactId + "/" + version + "/" + "maven-metadata.xml";
        String repositoryRootPath = this.repositoryRoot.toExternalForm();
        if (!repositoryRootPath.endsWith("/")) {
            repositoryRootPath = repositoryRootPath + "/";
        }

        URL mavenMetadataURL = new URL(repositoryRootPath
                + mavenMetadataRelativePath);
        Metadata metadata = this.readMetadata(mavenMetadataURL);
        return metadata;
    }

    protected Metadata readMetadata(final URL url) throws Exception {

        Metadata metadata = null;
        InputStream is = null;
        Reader source = null;
        try {
            URLConnection connection = url.openConnection();
            is = connection.getInputStream();
            source = new InputStreamReader(is);

            MetadataXpp3Reader reader = new MetadataXpp3Reader();
            metadata = reader.read(source);
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } finally {
                if (source != null) {
                    source.close();
                }
            }
        }
        return mavenMetadata;
    }

Posted in Maven | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 27, 2005

[Maven] pom.xml の読み込み方

先日作成した MavenRepositoryBrowser で使用した pom.xml の読み込み方法をメモ。

pom.xml 読み込みの実行環境構築

  1. maven-model-2.0.jar をクラスパスに追加。
  2. plexus-utils-1.0.4.jar をクラスパスに追加。

サンプルコード

org.apache.maven.model.Model というクラスが POM を表す。 ストリーム等から pom.xml を読み込み Model を生成するのが org.apache.maven.model.io.xpp3.MavenXpp3Reader。 この 2 つのクラスを利用すると苦も無く pom.xml を読み込むことができる。便利。

    public Model readModel(final String groupId, final String artifactId,
            final String version) throws Exception {

        // Maven2 リポジトリのディレクトリ構成に合わせて URL を生成。
        String pomRelativePath = "/" + groupId.replaceAll("\\.", "/") + "/"
                + artifactId + "/" + version + "/" + artifactId + "-" + version
                + ".pom";
        String repositoryRootPath = this.repositoryRoot.toExternalForm();
        if (!repositoryRootPath.endsWith("/")) {
            repositoryRootPath = repositoryRootPath + "/";
        }

        // pom.xml の読み込み。
        URL pomURL = new URL(repositoryRootPath + pomRelativePath);
        Model model = this.readModel(pomURL);

        return model;
    }

    protected Model readModel(final URL url) throws Exception {
        Model model = null;
        InputStream is = null;
        Reader source = null;
        try {
            // 指定された URL からデータを取得
            URLConnection connection = url.openConnection();
            is = connection.getInputStream();
            source = new InputStreamReader(is);

            // pom.xml の解析
            MavenXpp3Reader reader = new MavenXpp3Reader();
            model = reader.read(source);
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } finally {
                if (source != null) {
                    source.close();
                }
            }
        }
        return model;
    }

Posted in Maven | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 24, 2005

[Maven] Maven2 のリポジトリにある jar の依存関係を見たい!!

Maven2 はリポジトリに各種ライブラリが揃っていて有難いのだが、 jar 同士の依存関係は各々の pom ファイルに散っているので意外と追いかけづらい。 「struts-1.2.4.jar が依存しているライブラリをとりあえず見てみたい」等という状況になると、 struts-1.2.4.pom を見て → commons-beanutils-1.6.1.pom を見て → commons-logging-1.0.pom を見て・・・ と頑張って辿ることになる。 段々面倒になってきたので、リポジトリ内の pom の依存関係を追いかけるツールを作ってみた。

Maven2 Repository Browser

↓のリンクをクリックすると Java Web Start で Maven2 Repository Browser が起動する。
Maven2 Repository Browser を起動

とりあえず半日ちょいで作ったお気軽ツールなので、マトモに動くかどうか不明。 動かない場合は諦めが肝心。ちなみに Maven1 のリポジトリは面倒なので未対応。

Maven2 Repository Browser 使用上の注意

このソフトは・・・

  1. Maven2 のリポジトリから pom ファイルを読み込み、dependencies を追いかける。
  2. オレオレ証明書で署名されている。 → 正式な証明書を所有していない && 署名しないとセキュリティ制約で動作しないため
  3. 外部へのネットワークアクセスを要求する。 → Maven2 のリポジトリにアクセスするため
このソフトを利用する際には・・・
  1. J2SE 5.0 以上の JVM が必要。
  2. ネットワークのアクセス権限が必要。
  3. Maven2 の知識が必要。

Posted in Maven | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 23, 2005

[Misc] Java Web Start メモ

Java Web Start に関してちょっと調べてみた。 簡単にメモ。

Java Web Start 公式サイト
http://java.sun.com/products/javawebstart/index.jsp
Java Web Start Architecture JNLP Specification
http://java.sun.com/products/javawebstart/download-spec.html
Java Forums - Java Web Start & JNLP
http://forum.java.sun.com/forum.jspa?forumID=38

JNLP ファイルさえ書ければ簡単に Java Web Start アプリケーションを構築できる。 ただ、JNLP ファイルが意外と落とし穴だったりする。 JNLP ファイルの DTD は Java Web Start の仕様書(JSR-56) に記載されている。

Posted in Misc | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 20, 2005

[Misc] コンテンツ移動のお知らせ

http://www.in-vitro.jp/blog/index.cgi/Misc/20051120_01.html はこちらに移動しました。
Posted in Misc | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

[VMWare] VMWare Player のサービス停止

Windows XP Professiona に VMWare Player をインストールしたら、ログイン後の処理にやたらと時間がかかるようになった気がする。 タスクマネージャでプロセスを見てみると、

  • vmnat
  • vmnetdhcp
  • vmware-authd
というプロセスが常駐している。これが重いのかもしれない(←本当かどうかは分からない)。 このプロセスを止めてしまうと VMWare Player を起動したときにゲスト OS の動作に支障が出るので、必要なときにだけ起動するようにしたい。

とりあえず↓の様なバッチを作って必要なときに起動するようにした。 しばらくこれで様子を見てみよう。

startVMWareService.bat

net start "VMWare Authorization Service"
net start "VMWare DHCP Service"
net start "VMWare NAT Service"
stopVMWareService.bat
net stop "VMWare NAT Service"
net stop "VMWare DHCP Service"
net stop "VMWare Authorization Service"

Posted in VMWare | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 19, 2005

[Book] A Practical Guide to Feature-Driven Development (The Coad Series)

書籍情報


A Practical Guide to Feature-Driven Development (The Coad Series)

レビュー

アジャイルプロセスの一つである FDD(Feature Driven Development) の解説書。 FDD の基本は当然押さえてあるのだが、"Practical Guide" と銘打っているだけあって報告書のサンプルから開発者のロール毎のアドバイスなど有用な情報が多い。 FDD は、アジャイルプロセスの中ではバランスが良いようなので一読しても損はない。 訳書も出ている(
アジャイル開発手法FDD―ユーザ機能駆動によるアジャイル開発
)が、非常に残念なことに訳者が・・・orz 非常に残念。

Posted in Book | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 17, 2005

[Library] tinySQL にチャレンジ

tinySQL とは

tinySQL は Pure Java の RDBMS。 どうも何かの書籍で使用されたサンプルアプリケーションらしい。 色々試してみたのだが、結局 insert が全く動作しなかった。 当然 select、update、delete も試しようがない。 というわけで、あっさりと使い物にならないことが判明。 まぁ、書籍のサンプルだし。
とりあえず create table、drop table だけは動作した。 ↓はそのサンプルコード。意味はないけれども。

tinySQL
http://sourceforge.net/projects/tinysql/

tinySQL の実行環境構築

  1. tinySQL(tinySQL.jar) ver.2.0 をクラスパスに追加

サンプルコード

package jp.in_vitro.codelets.tinysql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class Codelet {

    public Codelet() throws ClassNotFoundException {
        super();
    }

    public static void main(final String[] args) throws SQLException,
            ClassNotFoundException, InstantiationException,
            IllegalAccessException {
        Codelet me = new Codelet();
        me.execute();
    }

    protected void execute() throws InstantiationException,
            IllegalAccessException, ClassNotFoundException, SQLException {

        this.initializeDBMS();
        try {
            try {
                // テーブルの生成。
                this.createTable();
            } catch (SQLException e) {
                // 既に Table が生成済みの可能性があるので・・・
            }
            
            // insert が全く動作しないので、select、update、delete も試しようがない・・・
            
            // テーブルの削除。
            this.dropTable();
        } finally {
            this.destroyDBMS();
        }
    }

    protected void initializeDBMS() throws ClassNotFoundException {
        Class.forName("com.sqlmagic.tinysql.textFileDriver");
    }

    protected void destroyDBMS() {

    }

    protected Connection getConnection() throws SQLException {
        String url = "jdbc:tinySQL";
        return DriverManager.getConnection(url);
    }

    protected void createTable() throws SQLException {
        Connection connection = this.getConnection();
        try {
            Statement statement = connection.createStatement();
            statement.executeUpdate("CREATE TABLE sample (field01 INT)");

            connection.commit();
            connection.close();

        } finally {
            if (connection != null) {
                connection.close();
            }
        }

    }

    protected void dropTable() throws SQLException {
        Connection connection = this.getConnection();
        try {
            Statement statement = connection.createStatement();
            statement.executeUpdate("DROP TABLE sample");

            connection.commit();
            connection.close();

        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }
}

Posted in Library | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 10, 2005

[Misc] 影舞のレポートを CSV 形式でエクスポートしたい

影舞は RSS もサポートしているし統計も自前で表示してくれるのスグレモノなのだけれど、事情により CSV 形式のエクスポートもしたい。 ということで、影舞に少し手を入れてみた。 Ruby は初めてなので「とりあえず動く」レベルの仕上がり(^^;

ダウンロード

影舞用CSV出力プラグイン

動作環境

このプログラムは下記の環境で動作する。

  • Debian Sarge
  • 影舞 0.8.6

インストール方法

  1. export_csv.rb を $KAGEMAI_HOME/lib/kagemai/cgi/action にコピー
  2. export_csv.rhtml を $KAGEMAI_HOME/resource/ja/template/_default にコピー
  3. http://localhost/kagemai-0.8.6/html/admin.cgi?project=myproject&action=export_csv にアクセスして動作確認を行う

出力例

下記の様な感じで、「レポートID、レポート作成日時、レポート更新日時、メッセージID、報告者、状態、処理方法、優先度、重大度、担当者」というフォーマットの CSV が出力される。

1,2005/11/08 01:53:09,2005/11/08 01:53:24,1,myaccount@example.com,新規,未処理,緊急,重大,未定,
1,2005/11/08 01:53:09,2005/11/08 01:53:24,2,myaccount@example.com,新規,未処理,緊急,重大,未定,
2,2005/11/08 02:11:19,2005/11/08 02:11:19,1,myaccount@example.com,新規,未処理,中,普通,未定,
3,2005/11/08 02:11:34,2005/11/08 02:11:34,1,myaccount@example.com,新規,未処理,中,普通,未定,

カスタマイズ方法

出力する項目をカスタマイズしたい
export_csv.rb を適当に編集してください
CSV ファイルにコメントを付加したい
export_csv.rhtml を適当に編集してください

Posted in Misc | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 09, 2005

[Maven] Continuum にチャレンジ

Continuum とは

Continuum は、Maven2、Maven、Ant などに対応した継続的インテグレーションツール。 実際のところはシェルスクリプトをキックできるようになっているので、他のビルドツールを使用していても大丈夫。 Apache Maven プロジェクトの一環として開発が行われている。 先日ついにバージョン 1.0 がリリースされたので実際に試してみた。

Continuum 公式サイト
http://maven.apache.org/continuum/

Continuum の実行環境構築

JDK(1.4以上) 及び開発に使用している JDK、SCM クライアント、ビルドツールが既にインストールされていることが前提。

  1. ダウンロードページから continuum-1.0-bin.tar.gz をダウンロード
  2. Continuum をインストール
    # tar zxvf ./continuum-1.0-bin.tar.gz
    # mv ./continuum-1.0 /opt
    # ln -s /opt/continuum-1.0/ /opt/continuum
    
  3. JAVA_HOME を設定
    # export JAVA_HOME=/opt/jdk15
    # export PATH=$JAVA_HOME/bin:$PATH
    # java -version
    java version "1.5.0_05"
    Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
    Java HotSpot(TM) Client VM (build 1.5.0_05-b05, mixed mode, sharing)
    
  4. /opt/continuum/bin/linux/run.sh の先頭の方に "PATH=/opt/maven2/bin:$PATH" を追記(開発に Maven2 を使っている場合)。
  5. Continuum を起動する。初回起動にはかなり時間がかかる(Pen4 2.4G 上の VMWare で数分かかった)ので気長に待つ。2 回目からは速くなるのでじっとガマン。
    # /opt/continuum/bin/linux/run.sh console
    
    ※run.sh のパラメータには通常 start を使用するが、初回はエラーが出る可能性があるのでフォアグラウンドで実行される console を使用すると便利。
  6. http://localhost:8080/continuum/ にアクセスして動作確認を行う。初回起動時に管理者用アカウントの設定画面が表示される。
    [管理者用アカウント設定画面] [初期画面]

Continuum へのプロジェクトの追加

Maven2 + Subversion で管理しているプロジェクトを Continuum に追加してみる。

pom.xml の編集

pom.xml に scm と ciManagement を追記する。

<model>
  <scm>
    <connection>scm:svn:http://svn.example.com/repos/MyProject/trunk/</connection>
    <developerConnection>scm:svn:http://svn.example.com/repos/MyProject/trunk/</developerConnection>
    <url>http://svn.example.com/repos/MyProject/</url>
  </scm>

  <ciManagement>
    <system>continuum</system>
    <notifiers>
      <notifier>
        <type>mail</type>
        <configuration>
          <address>me@example.com</address>
        </configuration>
      </notifier>
    </notifiers>
  </ciManagement>
</model>

Continuum へ pom.xml を登録

"Add Project" > "Maven 2.0+ Project" で pom.xml をアップロードする。
[pom.xml のアップロード] [プロジェクトが登録されたところ]

ビルドの実行

"Continuum" > "Show Projects" から該当プロジェクトの "Build Now" をクリックして強制的にビルドを実行する。
[ビルド結果一覧]

Posted in Maven | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 08, 2005

[Misc] 影舞にチャレンジ

影舞とは

Ruby 製の Bug Tracker。 名前で分かる通り国産。素晴らしい!!

影舞 公式サイト
http://www.daifukuya.com/kagemai/
影舞のインストール方法
http://www.daifukuya.com/kagemai/doc/install.html
インストール中に参考にしたのはこちら↓
[kagemai-users:0343] Re: コンフィグファイルとsafe
http://www.daifukuya.com/kagemai/ml/users/msg00343.html
[kagemai-users:0438] Ruby/MySQL 0.2.5 での影舞の利用について
http://www.daifukuya.com/kagemai/ml/users/msg00438.html

インストールメモ

影舞を Debian Sarge にインストールしたときのインストールメモ。 GD 周りでいくつかパッケージを調べたりしたけれど、基本的には非常に簡単だった。 後でもう一度構築する可能性があるのでとりあえずメモを残しておく。 それにしても、VMWare Player は中々調子が良い。 素晴らしい!!

# uname -a
Linux debian-sarge 2.6.8-2-386 #1 Thu May 19 17:40:50 JST 2005 i686 GNU/Linux

  1. 下準備
    Apache2 のインストール
    # apt-get install apache2
    
    Ruby のインストール
    # apt-get install ruby1.8
    # apt-get install libapache2-mod-ruby
    
    Apache2 の設定
    • /etc/apache2/apache2.conf にある AddHandler cgi-script .cgi のコメントアウトを外す。
    • /etc/apache2/sites-available/default にある /var/www/ 用の Directory の設定で Options に ExecCGI を追加する。
  2. 影舞のインストール
    インストール
    # tar zxvf ./kagemai-0.8.6.tar.gz
    # mv ./kagemai-0.8.6 /var/www
    # chown -R www-data:www-data /var/www/kagemai-0.8.6
    # chmod 755 /var/www/kagemai-0.8.6/html/*.cgi
    
    確認
    http://localhost/kagemai-0.8.6/html/guest.cgi にアクセスしてみる。
  3. MySQL のインストール
    インストール
    # apt-get install mysql-server-4.1
    # apt-get install libdbd-mysql-ruby1.8
    
  4. 影舞のデータベース設定
    影舞用のデータベースを作成
    # mysql
    mysql> create database kagemai;
    Query OK, 1 row affected (0.01 sec)
    
    mysql> grant all on kagemai.* to kagemai@localhost;
    Query OK, 0 rows affected (0.01 sec)
    
    影舞の設定変更
    影舞の管理メニューから"全体の設定の変更"を選択して下記の通り設定。
    • enable_mysql=true
    • mysql_host=localhost
    • mysql_port=3306
    • mysql_user=kagemai
    • mysql_pass=
    • mysql_dbname=kagemai
  5. グラフ出力用設定
    GD, GDChart インストール
    # apt-get install libgd-ruby1.8
    # apt-get install libgdchart-gd2-xpm
    
    Ruby/GDChart インストール
    1. http://sourceforge.jp/projects/ruby-gdchart/ から ruby-gdchart-0.0.9-beta.tar.gz をダウンロード
    2. Ruby/GDChart をコンパイル
      # tar zxvf ./ruby-gdchart-0.0.9-beta.tar.gz
      # cd ruby-gdchart-0.0.9-beta
      # apt-get install ruby1.8-dev ・・・ require 'mkmf' を解決するために ruby1.8-dev を入れる
      # apt-get install libgd-dev ・・・ ruby/gdchart のコンパイルに必要なので libgd-dev を入れる
      # ruby extconf.rb
      # make
      # make install
      
    日本語フォントインストール
    # apt-get install ttf-kochi-gothic ttf-kochi-mincho ttf-sazanami-gothic ttf-sazanami-mincho
    
    影舞の設定変更
    影舞の管理メニューから"全体の設定の変更"を選択して下記の通り設定。
    • enable-gdchart=true
    • gd-font=/usr/share/fonts/truetype/kochi/kochi-gothic.ttf
    • gd_chasert=UTF-8
Posted in Misc | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 06, 2005

[Library] JExcelAPI の概要

JExcelAPI のクラス図

JExcelAPI 2.5.8 の「イイカゲン」なクラス図を作ってみた。

[JExcelAPI 2.5.8 のクラス図]

Posted in Library | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 05, 2005

[Library] JExcelAPI にチャレンジ

JExcelAPI とは

JExcelAPI は、 MS Excel の Workbook を Java で扱うライブラリ。 Workbook の読み込み/書き出しからシートの印刷設定まで様々な機能を持っている。 Jakarta POI も同様の機能を持っているが、POI は PowerPoint/Excel/Word に対応しているのに対し JExcelAPI は Excel だけに絞っているので Excel を使うだけなら JExcelAPI の方が楽。 何も手を入れなくても、日本語がきちんと通るみたいなので嬉しい。

JExcelAPI
http://jexcelapi.sourceforge.net/
JExcelAPI のチュートリアル
http://www.andykhan.com/jexcelapi/tutorial.html

JExcelAPI の実行環境構築

  1. JExcelAPI(jxl.jar) をクラスパスに追加(ここではバージョン 2.5.8 を利用)。

サンプルコード

package jp.in_vitro.codelets.jexcelapi;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import jxl.BooleanCell;
import jxl.Cell;
import jxl.CellType;
import jxl.Sheet;
import jxl.Workbook;
import jxl.format.PageOrientation;
import jxl.format.PaperSize;
import jxl.read.biff.BiffException;
import jxl.write.Boolean;
import jxl.write.DateTime;
import jxl.write.Label;
import jxl.write.Number;
import jxl.write.WritableCell;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;

public class Codelet {

    public Codelet() {
        super();
    }

    public static void main(final String[] args) throws IOException,
            RowsExceededException, WriteException, BiffException {
        File inputFile = new File("c:\\template.xls");
        File outputFile = new File("c:\\output.xls");
        Map<String, String> data = new HashMap<String, String>();
        data.put("bookname", "Object Design");

        Codelet me = new Codelet();
        me.createBook(inputFile);
        me.mergeBook(inputFile, outputFile, data);
    }

    public void createBook(final File target) throws IOException,
            RowsExceededException, WriteException {

        WritableWorkbook book = Workbook.createWorkbook(target);
        WritableSheet sheet = book.createSheet("sheet0", 0);
        sheet.setPageSetup(PageOrientation.PORTRAIT, PaperSize.B5, 1.0, 1.0);

        // line 0
        sheet.addCell(new Label(0, 0, "TODO"));
        sheet.addCell(new Label(1, 0, "期限"));
        sheet.addCell(new Label(2, 0, "優先度"));
        sheet.addCell(new Label(3, 0, "完了"));
        // line 1
        sheet.addCell(new Label(0, 1, "ANSI COMMON LISP を読む"));
        sheet.addCell(new DateTime(1, 1, new Date(System.currentTimeMillis())));
        sheet.addCell(new Number(2, 1, 1));
        sheet.addCell(new Boolean(3, 1, false));
        // line 2
        sheet.addCell(new Label(0, 2, "${bookname} を読む"));
        sheet.addCell(new DateTime(1, 2, new Date(System.currentTimeMillis())));
        sheet.addCell(new Number(2, 2, 2));
        sheet.addCell(new Boolean(3, 2, false));

        book.write();
        book.close();
    }

    public void mergeBook(final File inputFile, final File outputFile,
            final Map<String, String> data) throws BiffException, IOException,
            RowsExceededException, WriteException {

        Workbook inputBook = Workbook.getWorkbook(inputFile);
        WritableWorkbook outputBook = Workbook.createWorkbook(outputFile);

        Sheet[] inputSheets = inputBook.getSheets();
        for (int k = 0; k < inputSheets.length; k++) {
            Sheet inputSheet = inputSheets[k];
            WritableSheet outputSheet = outputBook.createSheet(this.merge(
                    inputSheet.getName(), data), k);
            outputSheet.setPageSetup(PageOrientation.PORTRAIT, PaperSize.B5, 1.0, 1.0);

            for (int i = 0; i < inputSheet.getRows(); i++) {
                for (int j = 0; j < inputSheet.getColumns(); j++) {
                    Cell inputCell = inputSheet.getCell(j, i);
                    CellType inputCellType = inputCell.getType();
                    WritableCell outputCell = null;
                    if (inputCellType == CellType.LABEL) {
                        outputCell = new Label(j, i, this.merge(inputCell
                                .getContents(), data));
                    } else if (inputCellType == CellType.BOOLEAN) {
                        outputCell = new Boolean((BooleanCell) inputCell);
                    } else if (inputCellType == CellType.NUMBER) {
                        outputCell = new Number(j, i, new BigDecimal(inputCell
                                .getContents()).doubleValue());
                    } else if (inputCellType == CellType.DATE) {
                        outputCell = new DateTime(j, i, new Date());
                    }
                    outputSheet.addCell(outputCell);
                }
            }
        }

        outputBook.write();
        outputBook.close();
    }

    protected String merge(final String target, final Map<String, String> data) {

        if (target == null || "".equals(target)) {
            return "";
        }

        int prefixIndex = target.indexOf("${");
        int suffixIndex = target.indexOf("}");
        if (-1 < prefixIndex && prefixIndex < suffixIndex) {
            String key = target.substring(prefixIndex + "${".length(),
                    suffixIndex);
            String value = data.get(key);
            return target.replaceAll("\\$\\{" + key + "\\}", value);
        } else {
            return target;
        }
    }
}

Posted in Library | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 04, 2005

[Misc] コンテンツ移動のお知らせ

http://www.in-vitro.jp/blog/index.cgi/Misc/20051104_01.html はこちらに移動しました。
Posted in Misc | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

[VMWare] VMWare Player にチャレンジ

VMWare Player とは

PC エミュレータの VMWare に、無償版の VMWare Player があるらしい。 "Player" と銘打っているだけあって仮想イメージを作成する機能がなく、実際に利用するためには仮想イメージを作成できる製品版の VMWare Workstation が必要とのこと。

でも、逃げ道があった。→ 本当に無償で使える「VMware Player」 素晴らしい!! というわけで早速チャレンジ。

VMWare Player のインストール

↑の "Weboo! Returns" さんの説明通りで困ることも無くさくっと終了。

追加で調べたところだけ少しメモ。

qemu-img のコマンド

仮想イメージの作成に利用する QEMU のコマンド qemu-img について。

>qemu-img create -f vmdk d:\debian-sarge.vmdk 4G

qemu-img で指定できるコマンド

  • create
  • commit
  • convert
  • info

対応ファイルフォーマット

create 時に -f オプションで指定可能なファイルフォーマットは

raw
Raw disk image format (default).
qcow
QEMU image format, the most versatile format.
cow
User Mode Linux Copy On Write image format.
vmdk
VMware 3 and 4 compatible image format.
cloop
Linux Compressed Loop image, useful only to reuse directly compressed CD-ROM images present for example in the Knoppix CD-ROMs.
らしい。今回は VMWare で動かすことが目的なので vmdk のみを使用しているみたい。

qemu-img info

仮想イメージの情報を表示するコマンドは何故か動作しなかった(エラーで落ちる)。

>qemu-img info -f vmdk d:\debian-sarge.vmdk

仮想イメージの複数登録

仮想イメージを複数登録する場合、以下の手順で行う (OS は Debian を想定)。

  1. 新しいイメージを作成。
    >qemu-img create -f vmdk d:\debian-sarge2.vmdk 10G
  2. debian-sarge.vmx に以下を追加(/deb/hdb に追加する場合)。
    ide0:1.present = "TRUE"
    ide0:1.fileName = "debian-sarge2.vmdk"
  3. Debian を起動
  4. /deb/hdb の primary 1 にパーティション(タイプは Linux)を作成。
    #fdisk /dev/hdb
  5. EXT3 でパーティションをフォーマット。
    #mke2fs -j /dev/hdb1
  6. 作成したパーティションをテストする。
    #mkdir /mnt/test
    #mount -t ext3 /dev/hdb1 /mnt/test
    #umount /mnt/test
    #rmdir /mnt/test
後は /etc/fstab を適当に編集。

ゲスト OS あれこれ

指定可能な questOs

Galileo Computing さんによると、vmx ファイルの guestOS の値は以下のものが利用できるらしい。

Guest OS 名 vmx の guestOS
Windows Server 2003 Standard Edition winnetstandard
Windows XP Professional winxppro
Windows 2000 Professional win2000Pro
Red Hat Linux (generic) redhat
SuSE Linux (generic) suse
Netware 5 netware5
Netware 6 netware6
Solaris 9 solaris9
Solaris 10 (experimental) solaris10
FreeBSD (generic) freebsd
Other Linux otherlinux
Other Linux 2.4x kernel other24xlinux
Other Linux 2.6x kernel other26xlinux

ゲスト OS のインストール時メモ

というわけで色々なゲスト OS を入れてみたので、そのときのメモ。 全て最小インストールを選択し、X Window などの GUI はインストールしていない。 インストールは全て Daemon Tools で直接 ISO をマウントして行った。

Debian Sarge
questOs="other24xlinux" でインストールは何事もなく終了。"apt-get install kernel-image-2.6.8-2-386" をしてみたが問題なく動作した。Kernel のアップデート前から
atkbd.c: Unknown key released (translated set 2, code 0x01 on isa0060/serio0).
atkbd.c: Use 'setkeycodes e001 ' to make it known.
というエラーが出る。Kernel アップデート後も変わらず。但し、コンソール上にエラーが表示されるだけで実害はナシ。なんだろう、これ??
[Debian Sarge]
Solaris 10
questOs="solaris10" でインストールは何事もなく終了。DHCP クライアントでネットワークの設定を行うと、ホスト名が正常に設定されない。修正方法は
  1. /etc/nodename にホスト名(FQDN)を書く
  2. /etc/hostname.pcn0 にホスト名を書く
  3. #uname -S ホスト名
  4. #reboot
[Solaris 10]
Fedora Core4
questOs="other26xlinux" でインストールは何事もなく終了。その後も特に問題なし。guestOs="redhat" もあるけれど、どちらが良いのだろう??
[Fedora Core 4]
FreeBSD 5.4
questOs="freebsd" でインストールは何事もなく終了。ホスト名、ネットワークは /etc/rc.conf に以下の通り設定した。
hostname=ホスト名
ifconfig.lnc0="dhcp"
[FreeBSD 5.4]

Posted in VMWare | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |

Nov 01, 2005

[Library] Drools にチャレンジ

Drools とは

Drools は、 Charles Forgy's Rete algorithm をベースにした codehaus 謹製ルールエンジン。 JSR 94 にも準拠している。

Drools
http://drools.org/
Drools のサンプルコード
http://drools.org/Tutorials+and+Examples

Drools の実行環境構築

  1. Drools(drools-core-2.1.jar, drools-base-2.1.jar, drools-java-2.1.jar, drools-jsr94-2.1.jar, drools-io-2.1.jar, drools-smf-2.1.jar) をクラスパスに追加。
  2. その他必要なライブラリ (commons-logging-1.0.4.jar, jsr94-1.1.jar, jsr94-tck-1.1.jar, xercesImpl-2.6.2.jar, xml-apis-1.0b2.jar, antlr-2.7.5.jar, janino-2.3.8.jar) をクラスパスに追加

サンプルコード

Codelet.java (ここで使用している Rule は、Drools で公開されているサンプル)

package jp.in_vitro.codelets.drools;

import java.io.IOException;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;

import javax.rules.ConfigurationException;
import javax.rules.InvalidRuleSessionException;
import javax.rules.ObjectFilter;
import javax.rules.RuleExecutionSetNotFoundException;
import javax.rules.RuleRuntime;
import javax.rules.RuleServiceProvider;
import javax.rules.RuleServiceProviderManager;
import javax.rules.RuleSessionCreateException;
import javax.rules.RuleSessionTypeUnsupportedException;
import javax.rules.StatelessRuleSession;
import javax.rules.admin.RuleAdministrator;
import javax.rules.admin.RuleExecutionSet;
import javax.rules.admin.RuleExecutionSetCreateException;
import javax.rules.admin.RuleExecutionSetRegisterException;

import org.drools.jsr94.rules.RuleServiceProviderImpl;

public class Codelet {

    public Codelet() throws ConfigurationException {
        super();

        this.initializeRuleEngine();

    }

    public static void main(final String[] args) throws Exception {

        Codelet me = new Codelet();
        me.execute();
    }

    public void execute() throws RuleExecutionSetCreateException,
            RuleExecutionSetRegisterException, ConfigurationException,
            RemoteException, IOException, RuleSessionTypeUnsupportedException,
            RuleSessionCreateException, RuleExecutionSetNotFoundException,
            InvalidRuleSessionException {

        String uri = "res://sample.drl";
        String resource = "/"
                + Codelet.class.getPackage().getName().replaceAll("\\.", "/")
                + "/sample.drl";

        InputStream is = null;
        try {
            is = Codelet.class.getResourceAsStream(resource);
            this.loadRuleExecutionSet(uri, is);
        } finally {
            if (is != null) {
                is.close();
            }
        }

        // Fibonacci は下記のサンプルをそのまま利用。
        // http://drools.org/Fibonacci+Example
        List facts = new ArrayList();
        facts.add(new Fibonacci(50));
        List conclusions = this.executeRuleExecutionSet(uri, facts, null);
        for (Object conclusion : conclusions) {
            System.out.println("" + conclusion);
        }
    }

    protected void initializeRuleEngine() throws ConfigurationException {
        RuleServiceProviderManager.registerRuleServiceProvider(
                RuleServiceProviderImpl.class.getName(),
                RuleServiceProviderImpl.class);
    }

    protected RuleServiceProvider prepareRuleServiceProvider()
            throws ConfigurationException {
        RuleServiceProvider provider = RuleServiceProviderManager
                .getRuleServiceProvider(RuleServiceProviderImpl.class.getName());

        return provider;
    }

    protected void loadRuleExecutionSet(final String uri, final InputStream is)
            throws ConfigurationException, RuleExecutionSetCreateException,
            RemoteException, IOException, RuleExecutionSetRegisterException {
        RuleServiceProvider provider = this.prepareRuleServiceProvider();
        RuleAdministrator administrator = provider.getRuleAdministrator();

        RuleExecutionSet ruleSet = administrator
                .getLocalRuleExecutionSetProvider(null).createRuleExecutionSet(
                        is, null);
        administrator.registerRuleExecutionSet(uri, ruleSet, null);
    }

    protected List executeRuleExecutionSet(final String uri, final List facts,
            final ObjectFilter filter) throws ConfigurationException,
            RuleSessionTypeUnsupportedException, RuleSessionCreateException,
            RuleExecutionSetNotFoundException, RemoteException,
            InvalidRuleSessionException {

        RuleServiceProvider provider = this.prepareRuleServiceProvider();
        RuleRuntime runtime = provider.getRuleRuntime();
        StatelessRuleSession session = null;
        List conclusions = null;
        try {
            session = (StatelessRuleSession) runtime.createRuleSession(uri,
                    null, RuleRuntime.STATELESS_SESSION_TYPE);

            conclusions = session.executeRules(facts, filter);
        } finally {
            if (session != null) {
                session.release();
            }
        }

        return conclusions;
    }
}
sample.drl (ここで使用している Rule は、Drools で公開されているサンプル)
<?xml version="1.0"?>
<rule-set name="fibonacci"
          xmlns="http://drools.org/rules"
          xmlns:java="http://drools.org/semantics/java"
          xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
          xs:schemaLocation="http://drools.org/rules rules.xsd
                             http://drools.org/semantics/java java.xsd">
  
  <java:import>jp.in_vitro.codelets.drools.Fibonacci</java:import>
  
  <rule name="Recurse" salience="10">
    <parameter identifier="f">
      <class>Fibonacci</class>
    </parameter>
    <java:condition>f.getValue() == -1</java:condition>
    <java:consequence>
      System.err.println( "recurse for " + f.getSequence() );
      drools.assertObject( new Fibonacci( f.getSequence() - 1 ) );
    </java:consequence>
  </rule>
  
  <rule name="Bootstrap 1" salience="20">
    <parameter identifier="f">
      <class>Fibonacci</class>
    </parameter>

    <java:condition>f.getSequence() == 1</java:condition>
    <java:condition>f.getValue() == -1</java:condition>
    <java:consequence>
      f.setValue( 1 );
      System.err.println( f.getSequence() + " == " + f.getValue() );
      drools.modifyObject( f );
    </java:consequence>
  </rule>
  
  <rule name="Bootstrap 2">
    <parameter identifier="f">
      <class>Fibonacci</class>
    </parameter>
    <java:condition>f.getSequence() == 2</java:condition>
    <java:condition>f.getValue() == -1</java:condition>
    <java:consequence>
      f.setValue( 1 );
      System.err.println( f.getSequence() + " == " + f.getValue() );
      drools.modifyObject( f );
    </java:consequence>
  </rule>
  
  <rule name="Calculate">
    <parameter identifier="f1">
      <java:class>Fibonacci</java:class>
    </parameter>
    <parameter identifier="f2">
      <java:class>Fibonacci</java:class>
    </parameter>
    <parameter identifier="f3">
      <java:class>Fibonacci</java:class>
    </parameter>
    <java:condition>f2.getSequence() == (f1.getSequence() + 1)</java:condition>
    <java:condition>f3.getSequence() == (f2.getSequence() + 1)</java:condition>
    <java:condition>f1.getValue() != -1</java:condition>
    <java:condition>f2.getValue() != -1</java:condition>
    <java:condition>f3.getValue() == -1</java:condition>
    <java:consequence>
      f3.setValue( f1.getValue() + f2.getValue() );
      System.err.println( f3.getSequence() + " == " + f3.getValue() );
      drools.modifyObject( f3 );
      drools.retractObject( f1 );
    </java:consequence>
  </rule>

</rule-set>

Posted in Library | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |